(trunk gtk) #1473: Properties dialog should let you edit/view multiple torrents at once
This commit is contained in:
parent
015baf83db
commit
7f60d9db17
1
NEWS
1
NEWS
|
@ -20,6 +20,7 @@ NEWS file for Transmission <http://www.transmissionbt.com/>
|
|||
+ Speed Limit: Second set of bandwidth limits that can be toggled or scheduled
|
||||
+ Show the file icon in the list
|
||||
+ Allow sorting of the torrent list by size and by ETA
|
||||
+ Properties dialog now lets you edit/view multiple torrents at once
|
||||
- Qt
|
||||
+ New beta Qt client
|
||||
- Daemon
|
||||
|
|
|
@ -98,8 +98,7 @@ removeOldTorrent( struct AddData * data )
|
|||
{
|
||||
if( data->gtor )
|
||||
{
|
||||
file_list_set_torrent( data->list, NULL );
|
||||
|
||||
file_list_clear( data->list );
|
||||
tr_torrent_set_remove_flag( data->gtor, TRUE );
|
||||
g_object_unref( G_OBJECT( data->gtor ) );
|
||||
data->gtor = NULL;
|
||||
|
@ -143,11 +142,13 @@ addResponseCB( GtkDialog * dialog,
|
|||
static void
|
||||
updateTorrent( struct AddData * o )
|
||||
{
|
||||
if( o->gtor )
|
||||
tr_torrentSetDownloadDir( tr_torrent_handle(
|
||||
o->gtor ), o->downloadDir );
|
||||
|
||||
file_list_set_torrent( o->list, o->gtor );
|
||||
if( !o->gtor )
|
||||
file_list_clear( o->list );
|
||||
else {
|
||||
tr_torrent * tor = tr_torrent_handle( o->gtor );
|
||||
tr_torrentSetDownloadDir( tor, o->downloadDir );
|
||||
file_list_set_torrent( o->list, tr_torrentId( tor ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -292,7 +293,7 @@ addSingleTorrentDialog( GtkWindow * parent,
|
|||
data->ctor = ctor;
|
||||
data->filename = g_strdup( tr_ctorGetSourceFile( ctor ) );
|
||||
data->downloadDir = g_strdup( str );
|
||||
data->list = file_list_new( NULL );
|
||||
data->list = file_list_new( core, 0 );
|
||||
data->trash_check =
|
||||
gtk_check_button_new_with_mnemonic( _( "_Move source file to Trash" ) );
|
||||
data->run_check =
|
||||
|
|
2691
gtk/details.c
2691
gtk/details.c
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,9 @@
|
|||
#include "tr-torrent.h"
|
||||
|
||||
GtkWidget* torrent_inspector_new( GtkWindow * parent,
|
||||
TrCore * core,
|
||||
TrTorrent * tor );
|
||||
TrCore * core );
|
||||
|
||||
void torrent_inspector_set_torrents( GtkWidget * widgets,
|
||||
GSList * torrent_ids );
|
||||
|
||||
#endif /* TG_PREFS_H */
|
||||
|
|
115
gtk/file-list.c
115
gtk/file-list.c
|
@ -41,8 +41,7 @@ enum
|
|||
SUB_STATE_HIGH = ( 1 << 0 ),
|
||||
SUB_STATE_NORMAL = ( 1 << 1 ),
|
||||
SUB_STATE_LOW = ( 1 << 2 ),
|
||||
SUB_STATE_PRIORITY_MASK =
|
||||
( SUB_STATE_HIGH | SUB_STATE_NORMAL | SUB_STATE_LOW ),
|
||||
SUB_STATE_PRIORITY_MASK = ( SUB_STATE_HIGH | SUB_STATE_NORMAL | SUB_STATE_LOW ),
|
||||
SUB_STATE_DOWNLOAD = ( 1 << 4 ),
|
||||
SUB_STATE_IGNORE = ( 1 << 5 ),
|
||||
SUB_STATE_DOWNLOAD_MASK = ( SUB_STATE_DOWNLOAD | SUB_STATE_IGNORE )
|
||||
|
@ -68,7 +67,9 @@ enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
TrTorrent * gtor;
|
||||
int torrentId;
|
||||
TrCore * core;
|
||||
tr_torrent * tor;
|
||||
GtkWidget * top;
|
||||
GtkWidget * view;
|
||||
GtkTreeModel * model; /* same object as store, but recast */
|
||||
|
@ -81,10 +82,9 @@ FileData;
|
|||
static void
|
||||
clearData( FileData * data )
|
||||
{
|
||||
data->gtor = NULL;
|
||||
data->torrentId = -1;
|
||||
|
||||
if( data->timeout_tag )
|
||||
{
|
||||
if( data->timeout_tag ) {
|
||||
g_source_remove( data->timeout_tag );
|
||||
data->timeout_tag = 0;
|
||||
}
|
||||
|
@ -199,21 +199,22 @@ done:
|
|||
***/
|
||||
|
||||
static gboolean
|
||||
refreshFilesForeach( GtkTreeModel * model,
|
||||
GtkTreePath * path UNUSED,
|
||||
GtkTreeIter * iter,
|
||||
gpointer gdata )
|
||||
refreshFilesForeach( GtkTreeModel * model,
|
||||
GtkTreePath * path UNUSED,
|
||||
GtkTreeIter * iter,
|
||||
gpointer gdata )
|
||||
{
|
||||
FileData * data = gdata;
|
||||
gboolean is_file;
|
||||
unsigned int index;
|
||||
|
||||
gtk_tree_model_get( model, iter, FC_IS_FILE, &is_file, FC_INDEX, &index,
|
||||
-1 );
|
||||
gtk_tree_model_get( model, iter, FC_IS_FILE, &is_file,
|
||||
FC_INDEX, &index,
|
||||
-1 );
|
||||
if( is_file )
|
||||
{
|
||||
GtkTreeStore * store = GTK_TREE_STORE( model );
|
||||
tr_torrent * tor = tr_torrent_handle( data->gtor );
|
||||
tr_torrent * tor = data->tor;
|
||||
int download = tr_torrentGetFileDL( tor, index );
|
||||
int priority = tr_torrentGetFilePriority( tor, index );
|
||||
uint64_t have = data->refresh_file_stat[index].bytesCompleted;
|
||||
|
@ -299,17 +300,29 @@ addSubForeach( GtkTreeModel * model,
|
|||
static void
|
||||
refresh( FileData * data )
|
||||
{
|
||||
tr_file_index_t fileCount;
|
||||
tr_torrent * tor = tr_torrent_handle( data->gtor );
|
||||
tr_torrent * tor = tr_torrentFindFromId( tr_core_session( data->core ), data->torrentId );
|
||||
|
||||
data->refresh_file_stat = tr_torrentFiles( tor, &fileCount );
|
||||
if( tor == NULL )
|
||||
{
|
||||
file_list_clear( data->top );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_file_index_t fileCount;
|
||||
|
||||
gtk_tree_model_foreach( data->model, refreshFilesForeach, data );
|
||||
gtk_tree_model_foreach( data->model, resetSubForeach, data );
|
||||
gtk_tree_model_foreach( data->model, addSubForeach, data );
|
||||
/* initialize the temporary variables */
|
||||
data->tor = tr_torrentFindFromId( tr_core_session( data->core ), data->torrentId );
|
||||
data->refresh_file_stat = tr_torrentFiles( tor, &fileCount );
|
||||
|
||||
tr_torrentFilesFree( data->refresh_file_stat, fileCount );
|
||||
data->refresh_file_stat = NULL;
|
||||
gtk_tree_model_foreach( data->model, refreshFilesForeach, data );
|
||||
gtk_tree_model_foreach( data->model, resetSubForeach, data );
|
||||
gtk_tree_model_foreach( data->model, addSubForeach, data );
|
||||
|
||||
/* clean up the temporary variables */
|
||||
data->refresh_file_stat = NULL;
|
||||
tr_torrentFilesFree( data->refresh_file_stat, fileCount );
|
||||
data->tor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -442,13 +455,16 @@ getActiveFilesForPath( GtkTreeView * view,
|
|||
***/
|
||||
|
||||
void
|
||||
file_list_set_torrent( GtkWidget * w,
|
||||
TrTorrent * gtor )
|
||||
file_list_clear( GtkWidget * w )
|
||||
{
|
||||
file_list_set_torrent( w, -1 );
|
||||
}
|
||||
|
||||
void
|
||||
file_list_set_torrent( GtkWidget * w, int torrentId )
|
||||
{
|
||||
GtkTreeStore * store;
|
||||
FileData * data;
|
||||
|
||||
data = g_object_get_data( G_OBJECT( w ), "file-data" );
|
||||
FileData * data = g_object_get_data( G_OBJECT( w ), "file-data" );
|
||||
|
||||
/* unset the old fields */
|
||||
clearData( data );
|
||||
|
@ -468,34 +484,34 @@ file_list_set_torrent( GtkWidget * w,
|
|||
G_TYPE_UINT64, /* sub size */
|
||||
G_TYPE_UINT64, /* sub have */
|
||||
G_TYPE_INT ); /* sub state */
|
||||
|
||||
data->store = store;
|
||||
data->model = GTK_TREE_MODEL( store );
|
||||
data->gtor = gtor;
|
||||
|
||||
data->torrentId = torrentId;
|
||||
|
||||
/* populate the model */
|
||||
if( gtor )
|
||||
if( torrentId > 0 )
|
||||
{
|
||||
tr_file_index_t i;
|
||||
const tr_info * inf = tr_torrent_info( gtor );
|
||||
tr_torrent * tor = tr_torrent_handle( gtor );
|
||||
|
||||
for( i = 0; inf && i < inf->fileCount; ++i )
|
||||
tr_session * session = tr_core_session( data->core );
|
||||
tr_torrent * tor = tr_torrentFindFromId( session, torrentId );
|
||||
if( tor != NULL )
|
||||
{
|
||||
const char * path = inf->files[i].name;
|
||||
const char * base =
|
||||
g_path_is_absolute( path ) ? g_path_skip_root( path ) :
|
||||
path;
|
||||
parsepath( w, tor, store, NULL, base, i, inf->files[i].length );
|
||||
tr_file_index_t i;
|
||||
const tr_info * inf = tr_torrentInfo( tor );
|
||||
|
||||
for( i=0; i<inf->fileCount; ++i )
|
||||
{
|
||||
const char * path = inf->files[i].name;
|
||||
const char * base = g_path_is_absolute( path ) ? g_path_skip_root( path ) : path;
|
||||
parsepath( w, tor, store, NULL, base, i, inf->files[i].length );
|
||||
}
|
||||
}
|
||||
|
||||
refresh( data );
|
||||
|
||||
data->timeout_tag = gtr_timeout_add_seconds( 2, refreshModel, data );
|
||||
}
|
||||
|
||||
gtk_tree_view_set_model( GTK_TREE_VIEW( data->view ),
|
||||
GTK_TREE_MODEL( store ) );
|
||||
gtk_tree_view_set_model( GTK_TREE_VIEW( data->view ), GTK_TREE_MODEL( store ) );
|
||||
gtk_tree_view_expand_all( GTK_TREE_VIEW( data->view ) );
|
||||
}
|
||||
|
||||
|
@ -656,6 +672,10 @@ onViewButtonPressed( GtkWidget * w,
|
|||
{
|
||||
FileData * data = gdata;
|
||||
gboolean handled = FALSE;
|
||||
tr_torrent * tor = tr_torrentFindFromId( tr_core_session( data->core ), data->torrentId );
|
||||
|
||||
if( tor == NULL )
|
||||
return handled;
|
||||
|
||||
if( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 1 )
|
||||
&& !( event->state & ( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) )
|
||||
|
@ -720,8 +740,7 @@ onViewButtonPressed( GtkWidget * w,
|
|||
}
|
||||
|
||||
/* apply that new state to the active files */
|
||||
tr_torrentSetFilePriorities( tr_torrent_handle( data->
|
||||
gtor ),
|
||||
tr_torrentSetFilePriorities( tor,
|
||||
(tr_file_index_t*)a->data,
|
||||
(tr_file_index_t)a->len,
|
||||
priority );
|
||||
|
@ -744,7 +763,7 @@ onViewButtonPressed( GtkWidget * w,
|
|||
enabled = ( sub_state & SUB_STATE_IGNORE ) ? 1 : 0;
|
||||
|
||||
/* apply that new state to the active files */
|
||||
tr_torrentSetFileDLs( tr_torrent_handle( data->gtor ),
|
||||
tr_torrentSetFileDLs( tor,
|
||||
(tr_file_index_t*)a->data,
|
||||
(tr_file_index_t)a->len,
|
||||
enabled );
|
||||
|
@ -769,7 +788,7 @@ onViewButtonPressed( GtkWidget * w,
|
|||
}
|
||||
|
||||
GtkWidget *
|
||||
file_list_new( TrTorrent * gtor )
|
||||
file_list_new( TrCore * core, int torrentId )
|
||||
{
|
||||
GtkWidget * ret;
|
||||
GtkWidget * view, * scroll;
|
||||
|
@ -778,6 +797,8 @@ file_list_new( TrTorrent * gtor )
|
|||
GtkTreeSelection * sel;
|
||||
FileData * data = g_new0( FileData, 1 );
|
||||
|
||||
data->core = core;
|
||||
|
||||
/* create the view */
|
||||
view = gtk_tree_view_new( );
|
||||
gtk_tree_view_set_rules_hint( GTK_TREE_VIEW( view ), TRUE );
|
||||
|
@ -845,7 +866,7 @@ file_list_new( TrTorrent * gtor )
|
|||
data->view = view;
|
||||
data->top = scroll;
|
||||
g_object_set_data_full( G_OBJECT( ret ), "file-data", data, freeData );
|
||||
file_list_set_torrent( ret, gtor );
|
||||
file_list_set_torrent( ret, torrentId );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
#define GTK_TORRENT_FILE_LIST_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "tr-torrent.h"
|
||||
#include "tr-core.h"
|
||||
|
||||
/* create a new file list */
|
||||
GtkWidget * file_list_new( TrTorrent * );
|
||||
GtkWidget * file_list_new( TrCore *, int torrentId );
|
||||
|
||||
void file_list_set_torrent( GtkWidget *,
|
||||
TrTorrent * );
|
||||
void file_list_clear( GtkWidget * );
|
||||
|
||||
void file_list_set_torrent( GtkWidget *, int torrentId );
|
||||
|
||||
#endif
|
||||
|
|
180
gtk/main.c
180
gtk/main.c
|
@ -97,19 +97,18 @@ static const char * LICENSE =
|
|||
|
||||
struct cbdata
|
||||
{
|
||||
unsigned int isIconified : 1;
|
||||
unsigned int isClosing : 1;
|
||||
guint timer;
|
||||
gpointer icon;
|
||||
GtkWindow * wind;
|
||||
TrCore * core;
|
||||
GtkWidget * msgwin;
|
||||
GtkWidget * prefs;
|
||||
GSList * errqueue;
|
||||
GSList * dupqueue;
|
||||
GHashTable * tor2details;
|
||||
GHashTable * details2tor;
|
||||
GtkTreeSelection * sel;
|
||||
gboolean isIconified;
|
||||
gboolean isClosing;
|
||||
guint timer;
|
||||
gpointer icon;
|
||||
GtkWindow * wind;
|
||||
TrCore * core;
|
||||
GtkWidget * msgwin;
|
||||
GtkWidget * prefs;
|
||||
GSList * errqueue;
|
||||
GSList * dupqueue;
|
||||
GtkTreeSelection * sel;
|
||||
GtkWidget * details;
|
||||
};
|
||||
|
||||
#define CBDATA_PTR "callback-data-pointer"
|
||||
|
@ -189,7 +188,7 @@ accumulateCanUpdateForeach( GtkTreeModel * model,
|
|||
}
|
||||
|
||||
static void
|
||||
refreshTorrentActions( struct cbdata * data )
|
||||
refreshActions( struct cbdata * data )
|
||||
{
|
||||
int canUpdate;
|
||||
struct counts_data counts;
|
||||
|
@ -205,7 +204,7 @@ refreshTorrentActions( struct cbdata * data )
|
|||
action_sensitize( "delete-torrent", counts.totalCount != 0 );
|
||||
action_sensitize( "verify-torrent", counts.totalCount != 0 );
|
||||
action_sensitize( "open-torrent-folder", counts.totalCount == 1 );
|
||||
action_sensitize( "show-torrent-properties", counts.totalCount == 1 );
|
||||
action_sensitize( "show-torrent-properties", counts.totalCount != 0 );
|
||||
|
||||
canUpdate = 0;
|
||||
gtk_tree_selection_selected_foreach( s, accumulateCanUpdateForeach, &canUpdate );
|
||||
|
@ -228,10 +227,42 @@ refreshTorrentActions( struct cbdata * data )
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
refreshDetailsDialog( struct cbdata * data )
|
||||
{
|
||||
GtkTreeSelection * s = tr_window_get_selection( data->wind );
|
||||
GtkTreeModel * model;
|
||||
GSList * ids = NULL;
|
||||
GList * selrows = NULL;
|
||||
GList * l;
|
||||
|
||||
if( data->details == NULL )
|
||||
return;
|
||||
|
||||
/* 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( data->details, ids );
|
||||
|
||||
/* cleanup */
|
||||
g_slist_free( ids );
|
||||
g_list_foreach( selrows, (GFunc)gtk_tree_path_free, NULL );
|
||||
g_list_free( selrows );
|
||||
}
|
||||
|
||||
static void
|
||||
selectionChangedCB( GtkTreeSelection * s UNUSED, gpointer data )
|
||||
{
|
||||
refreshTorrentActions( data );
|
||||
refreshActions( data );
|
||||
refreshDetailsDialog( data );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -355,8 +386,6 @@ main( int argc,
|
|||
};
|
||||
|
||||
cbdata = g_new0( struct cbdata, 1 );
|
||||
cbdata->tor2details = g_hash_table_new( g_str_hash, g_str_equal );
|
||||
cbdata->details2tor = g_hash_table_new( g_direct_hash, g_direct_equal );
|
||||
|
||||
/* bind the gettext domain */
|
||||
setlocale( LC_ALL, "" );
|
||||
|
@ -583,7 +612,7 @@ rowChangedCB( GtkTreeModel * model UNUSED,
|
|||
{
|
||||
struct cbdata * data = gdata;
|
||||
if( gtk_tree_selection_path_is_selected ( data->sel, path ) )
|
||||
refreshTorrentActions( gdata );
|
||||
refreshActions( gdata );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -602,42 +631,15 @@ winsetup( struct cbdata * cbdata,
|
|||
model = tr_core_model( cbdata->core );
|
||||
g_signal_connect( model, "row-changed", G_CALLBACK( rowChangedCB ), cbdata );
|
||||
g_signal_connect( wind, "delete-event", G_CALLBACK( winclose ), cbdata );
|
||||
refreshTorrentActions( cbdata );
|
||||
refreshActions( cbdata );
|
||||
|
||||
setupdrag( GTK_WIDGET( wind ), cbdata );
|
||||
}
|
||||
|
||||
static gpointer
|
||||
quitThreadFunc( gpointer gdata )
|
||||
quitThreadFunc( gpointer core )
|
||||
{
|
||||
struct cbdata * cbdata = gdata;
|
||||
|
||||
tr_core_close( cbdata->core );
|
||||
|
||||
/* shutdown the gui */
|
||||
if( cbdata->prefs )
|
||||
gtk_widget_destroy( GTK_WIDGET( cbdata->prefs ) );
|
||||
if( cbdata->wind )
|
||||
gtk_widget_destroy( GTK_WIDGET( cbdata->wind ) );
|
||||
g_object_unref( cbdata->core );
|
||||
if( cbdata->icon )
|
||||
g_object_unref( cbdata->icon );
|
||||
if( cbdata->errqueue )
|
||||
{
|
||||
g_slist_foreach( cbdata->errqueue, (GFunc)g_free, NULL );
|
||||
g_slist_free( cbdata->errqueue );
|
||||
}
|
||||
if( cbdata->dupqueue )
|
||||
{
|
||||
g_slist_foreach( cbdata->dupqueue, (GFunc)g_free, NULL );
|
||||
g_slist_free( cbdata->dupqueue );
|
||||
}
|
||||
|
||||
g_hash_table_destroy( cbdata->details2tor );
|
||||
g_hash_table_destroy( cbdata->tor2details );
|
||||
g_free( cbdata );
|
||||
|
||||
/* exit the gtk main loop */
|
||||
tr_core_close( core );
|
||||
gtk_main_quit( );
|
||||
return NULL;
|
||||
}
|
||||
|
@ -652,8 +654,9 @@ do_exit_cb( GtkWidget *w UNUSED,
|
|||
static void
|
||||
wannaquit( void * vdata )
|
||||
{
|
||||
GtkWidget * r, * p, * b, * w, *c;
|
||||
struct cbdata * cbdata = vdata;
|
||||
TrCore * core;
|
||||
GtkWidget *r, *p, *b, *w, *c;
|
||||
struct cbdata *cbdata = vdata;
|
||||
|
||||
/* stop the update timer */
|
||||
if( cbdata->timer )
|
||||
|
@ -688,16 +691,36 @@ wannaquit( void * vdata )
|
|||
w = gtr_button_new_from_stock( GTK_STOCK_QUIT, _( "_Quit Now" ) );
|
||||
g_signal_connect( w, "clicked", G_CALLBACK( do_exit_cb ), NULL );
|
||||
gtk_container_add( GTK_CONTAINER( b ), w );
|
||||
gtk_table_attach( GTK_TABLE(
|
||||
p ), b, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 10 );
|
||||
gtk_table_attach( GTK_TABLE( p ), b, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 10 );
|
||||
|
||||
gtk_widget_show_all( r );
|
||||
|
||||
/* clear the UI */
|
||||
gtk_list_store_clear( GTK_LIST_STORE( tr_core_model( cbdata->core ) ) );
|
||||
|
||||
/* shutdown the gui */
|
||||
core = cbdata->core;
|
||||
if( cbdata->details )
|
||||
gtk_widget_destroy( GTK_WIDGET( cbdata->details ) );
|
||||
if( cbdata->prefs )
|
||||
gtk_widget_destroy( GTK_WIDGET( cbdata->prefs ) );
|
||||
if( cbdata->wind )
|
||||
gtk_widget_destroy( GTK_WIDGET( cbdata->wind ) );
|
||||
g_object_unref( cbdata->core );
|
||||
if( cbdata->icon )
|
||||
g_object_unref( cbdata->icon );
|
||||
if( cbdata->errqueue ) {
|
||||
g_slist_foreach( cbdata->errqueue, (GFunc)g_free, NULL );
|
||||
g_slist_free( cbdata->errqueue );
|
||||
}
|
||||
if( cbdata->dupqueue ) {
|
||||
g_slist_foreach( cbdata->dupqueue, (GFunc)g_free, NULL );
|
||||
g_slist_free( cbdata->dupqueue );
|
||||
}
|
||||
g_free( cbdata );
|
||||
|
||||
/* shut down libT */
|
||||
g_thread_create( quitThreadFunc, vdata, TRUE, NULL );
|
||||
g_thread_create( quitThreadFunc, core, TRUE, NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1091,7 +1114,7 @@ updatemodel( gpointer gdata )
|
|||
tr_window_update( data->wind );
|
||||
|
||||
/* update the actions */
|
||||
refreshTorrentActions( data );
|
||||
refreshActions( data );
|
||||
}
|
||||
|
||||
return !done;
|
||||
|
@ -1181,18 +1204,6 @@ updateTrackerForeach( GtkTreeModel * model,
|
|||
tr_torrentManualUpdate( tor );
|
||||
}
|
||||
|
||||
static void
|
||||
detailsClosed( gpointer user_data,
|
||||
GObject * details )
|
||||
{
|
||||
struct cbdata * data = user_data;
|
||||
gpointer hashString = g_hash_table_lookup( data->details2tor,
|
||||
details );
|
||||
|
||||
g_hash_table_remove( data->details2tor, details );
|
||||
g_hash_table_remove( data->tor2details, hashString );
|
||||
}
|
||||
|
||||
static void
|
||||
openFolderForeach( GtkTreeModel * model,
|
||||
GtkTreePath * path UNUSED,
|
||||
|
@ -1206,34 +1217,6 @@ openFolderForeach( GtkTreeModel * model,
|
|||
g_object_unref( G_OBJECT( gtor ) );
|
||||
}
|
||||
|
||||
static void
|
||||
showInfoForeach( GtkTreeModel * model,
|
||||
GtkTreePath * path UNUSED,
|
||||
GtkTreeIter * iter,
|
||||
gpointer user_data )
|
||||
{
|
||||
const char * hashString;
|
||||
struct cbdata * data = user_data;
|
||||
TrTorrent * tor = NULL;
|
||||
GtkWidget * w;
|
||||
|
||||
gtk_tree_model_get( model, iter, MC_TORRENT, &tor, -1 );
|
||||
hashString = tr_torrent_info( tor )->hashString;
|
||||
w = g_hash_table_lookup( data->tor2details, hashString );
|
||||
if( w != NULL )
|
||||
gtk_window_present( GTK_WINDOW( w ) );
|
||||
else
|
||||
{
|
||||
w = torrent_inspector_new( GTK_WINDOW( data->wind ), data->core, tor );
|
||||
gtk_widget_show( w );
|
||||
g_hash_table_insert( data->tor2details, (gpointer)hashString, w );
|
||||
g_hash_table_insert( data->details2tor, w, (gpointer)hashString );
|
||||
g_object_weak_ref( G_OBJECT( w ), detailsClosed, data );
|
||||
}
|
||||
|
||||
g_object_unref( G_OBJECT( tor ) );
|
||||
}
|
||||
|
||||
static void
|
||||
recheckTorrentForeach( GtkTreeModel * model,
|
||||
GtkTreePath * path UNUSED,
|
||||
|
@ -1348,8 +1331,10 @@ doAction( const char * action_name, gpointer user_data )
|
|||
}
|
||||
else if( !strcmp( action_name, "show-torrent-properties" ) )
|
||||
{
|
||||
GtkTreeSelection * s = tr_window_get_selection( data->wind );
|
||||
gtk_tree_selection_selected_foreach( s, showInfoForeach, data );
|
||||
if( data->details == NULL )
|
||||
data->details = torrent_inspector_new( GTK_WINDOW( data->wind ), data->core );
|
||||
refreshDetailsDialog( data );
|
||||
gtk_widget_show( data->details );
|
||||
}
|
||||
else if( !strcmp( action_name, "update-tracker" ) )
|
||||
{
|
||||
|
@ -1435,4 +1420,3 @@ doAction( const char * action_name, gpointer user_data )
|
|||
if( changed )
|
||||
updatemodel( data );
|
||||
}
|
||||
|
||||
|
|
|
@ -426,7 +426,7 @@ make_meta_ui( GtkWindow * parent,
|
|||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Trackers" ) );
|
||||
|
||||
w = tracker_list_new( NULL );
|
||||
w = tracker_list_new( session, -1, TRUE );
|
||||
|
||||
n = pref_int_get( ANNOUNCE_KEY"-count" );
|
||||
if( n > 0 )
|
||||
|
|
|
@ -1428,3 +1428,22 @@ tr_core_blocklist_update( TrCore * core )
|
|||
g_snprintf( buf, sizeof( buf ), "{ \"method\": \"blocklist-update\", \"tag\": %d }", tag );
|
||||
sendRequest( core, buf, tag, blocklistResponseFunc, NULL );
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
void
|
||||
tr_core_exec_json( TrCore * core, const char * json )
|
||||
{
|
||||
g_message( "executing %s", json );
|
||||
sendRequest( core, json, 0, NULL, NULL );
|
||||
}
|
||||
|
||||
void
|
||||
tr_core_exec( TrCore * core, const tr_benc * top )
|
||||
{
|
||||
char * json = tr_bencToJSON( top );
|
||||
tr_core_exec_json( core, json );
|
||||
tr_free( json );
|
||||
}
|
||||
|
|
|
@ -189,6 +189,11 @@ void tr_core_port_test( TrCore * core );
|
|||
|
||||
void tr_core_blocklist_update( TrCore * core );
|
||||
|
||||
void tr_core_exec( TrCore * core, const tr_benc * benc );
|
||||
|
||||
void tr_core_exec_json( TrCore * core, const char * json );
|
||||
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
|
|
@ -32,7 +32,10 @@
|
|||
|
||||
struct tracker_page
|
||||
{
|
||||
TrTorrent * gtor;
|
||||
gboolean isNew;
|
||||
|
||||
tr_session * session;
|
||||
int torrentId;
|
||||
|
||||
GtkTreeView * view;
|
||||
GtkListStore * store;
|
||||
|
@ -60,6 +63,11 @@ enum
|
|||
TR_N_COLS
|
||||
};
|
||||
|
||||
static tr_torrent * getTorrent( struct tracker_page * page )
|
||||
{
|
||||
return tr_torrentFindFromId( page->session, page->torrentId );
|
||||
}
|
||||
|
||||
static void
|
||||
setTrackerChangeState( struct tracker_page * page,
|
||||
gboolean changed )
|
||||
|
@ -105,14 +113,13 @@ onTrackerSelectionChanged( GtkTreeSelection * sel,
|
|||
const gboolean has_selection =
|
||||
gtk_tree_selection_count_selected_rows( sel ) > 0;
|
||||
GtkTreeModel * model = GTK_TREE_MODEL( page->store );
|
||||
const int trackerCount = gtk_tree_model_iter_n_children( model, NULL );
|
||||
const gboolean ok_to_remove = !page->gtor || ( trackerCount > 1 );
|
||||
const int trackerCount = model ? gtk_tree_model_iter_n_children( model, NULL ) : 0;
|
||||
const gboolean ok_to_remove = page->isNew || ( trackerCount > 1 );
|
||||
gtk_widget_set_sensitive( page->remove_button, has_selection && ok_to_remove );
|
||||
}
|
||||
|
||||
static void
|
||||
onTrackerRemoveClicked( GtkButton * w UNUSED,
|
||||
gpointer gpage )
|
||||
onTrackerRemoveClicked( GtkButton * w UNUSED, gpointer gpage )
|
||||
{
|
||||
struct tracker_page * page = gpage;
|
||||
GtkTreeModel * model;
|
||||
|
@ -143,8 +150,7 @@ onTrackerRemoveClicked( GtkButton * w UNUSED,
|
|||
}
|
||||
|
||||
static void
|
||||
onTrackerAddClicked( GtkButton * w UNUSED,
|
||||
gpointer gpage )
|
||||
onTrackerAddClicked( GtkButton * w UNUSED, gpointer gpage )
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
struct tracker_page * page = gpage;
|
||||
|
@ -193,9 +199,7 @@ onTrackerSaveClicked( GtkButton * w UNUSED,
|
|||
g_assert( i == n );
|
||||
|
||||
/* set the tracker list */
|
||||
tr_torrentSetAnnounceList( tr_torrent_handle( page->gtor ),
|
||||
trackers, n );
|
||||
|
||||
tr_torrentSetAnnounceList( getTorrent( page ), trackers, n );
|
||||
|
||||
setTrackerChangeState( page, FALSE );
|
||||
|
||||
|
@ -211,12 +215,13 @@ onTrackerRevertClicked( GtkButton * w UNUSED,
|
|||
gpointer gpage )
|
||||
{
|
||||
struct tracker_page * page = gpage;
|
||||
GtkTreeModel * model =
|
||||
tracker_model_new( tr_torrent_handle( page->gtor ) );
|
||||
GtkTreeModel * model;
|
||||
|
||||
model = tracker_model_new( getTorrent( page ) );
|
||||
gtk_tree_view_set_model( page->view, model );
|
||||
page->store = GTK_LIST_STORE( model );
|
||||
g_object_unref( G_OBJECT( model ) );
|
||||
|
||||
setTrackerChangeState( page, FALSE );
|
||||
}
|
||||
|
||||
|
@ -291,71 +296,74 @@ onTierEdited( GtkCellRendererText * renderer UNUSED,
|
|||
gtk_tree_path_free( path );
|
||||
}
|
||||
|
||||
void
|
||||
tracker_list_set_torrent( GtkWidget * w, int torrentId )
|
||||
{
|
||||
struct tracker_page * page = g_object_get_data( G_OBJECT( w ), PAGE_KEY );
|
||||
GtkTreeModel * m;
|
||||
|
||||
m = tracker_model_new( tr_torrentFindFromId( page->session, torrentId ) );
|
||||
page->torrentId = torrentId;
|
||||
page->store = GTK_LIST_STORE( m );
|
||||
gtk_tree_view_set_model( GTK_TREE_VIEW( page->view ), m );
|
||||
g_object_unref( m );
|
||||
}
|
||||
|
||||
void
|
||||
tracker_list_clear( GtkWidget * w )
|
||||
{
|
||||
tracker_list_set_torrent( w, -1 );
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
tracker_list_new( TrTorrent * gtor )
|
||||
tracker_list_new( tr_session * session, int torrentId, gboolean isNew )
|
||||
{
|
||||
GtkWidget * w;
|
||||
GtkWidget * buttons;
|
||||
GtkWidget * box;
|
||||
GtkWidget * top;
|
||||
GtkWidget * fr;
|
||||
GtkTreeModel * m;
|
||||
GtkCellRenderer * r;
|
||||
GtkTreeViewColumn * c;
|
||||
GtkTreeSelection * sel;
|
||||
struct tracker_page * page = g_new0( struct tracker_page, 1 );
|
||||
|
||||
page->gtor = gtor;
|
||||
page->session = session;
|
||||
|
||||
top = gtk_hbox_new( FALSE, GUI_PAD );
|
||||
box = gtk_vbox_new( FALSE, GUI_PAD );
|
||||
buttons = gtk_vbox_new( TRUE, GUI_PAD );
|
||||
|
||||
m = tracker_model_new( tr_torrent_handle( gtor ) );
|
||||
page->store = GTK_LIST_STORE( m );
|
||||
w = gtk_tree_view_new_with_model( m );
|
||||
//m = tracker_model_new( tr_torrent_handle( gtor ) );
|
||||
//page->store = GTK_LIST_STORE( m );
|
||||
w = gtk_tree_view_new( );
|
||||
g_signal_connect( w, "button-release-event",
|
||||
G_CALLBACK( on_tree_view_button_released ), NULL );
|
||||
page->view = GTK_TREE_VIEW( w );
|
||||
gtk_tree_view_set_enable_search( page->view, FALSE );
|
||||
r = gtk_cell_renderer_text_new( );
|
||||
g_object_set( G_OBJECT( r ),
|
||||
"editable", TRUE,
|
||||
NULL );
|
||||
g_signal_connect( r, "edited",
|
||||
G_CALLBACK( onTierEdited ), page );
|
||||
c = gtk_tree_view_column_new_with_attributes( _( "Tier" ), r,
|
||||
"text", TR_COL_TIER,
|
||||
NULL );
|
||||
g_object_set( G_OBJECT( r ), "editable", TRUE, NULL );
|
||||
g_signal_connect( r, "edited", G_CALLBACK( onTierEdited ), page );
|
||||
c = gtk_tree_view_column_new_with_attributes( _( "Tier" ), r, "text", TR_COL_TIER, NULL );
|
||||
gtk_tree_view_column_set_sort_column_id( c, TR_COL_TIER );
|
||||
gtk_tree_view_append_column( page->view, c );
|
||||
r = gtk_cell_renderer_text_new( );
|
||||
g_object_set( G_OBJECT( r ),
|
||||
"editable", TRUE,
|
||||
"ellipsize", PANGO_ELLIPSIZE_END,
|
||||
NULL );
|
||||
g_signal_connect( r, "edited",
|
||||
G_CALLBACK( onAnnounceEdited ), page );
|
||||
c = gtk_tree_view_column_new_with_attributes( _( "Announce URL" ), r,
|
||||
"text", TR_COL_ANNOUNCE,
|
||||
NULL );
|
||||
g_object_set( G_OBJECT( r ), "editable", TRUE, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
|
||||
g_signal_connect( r, "edited", G_CALLBACK( onAnnounceEdited ), page );
|
||||
c = gtk_tree_view_column_new_with_attributes( _( "Announce URL" ), r, "text", TR_COL_ANNOUNCE, NULL );
|
||||
gtk_tree_view_column_set_sort_column_id( c, TR_COL_ANNOUNCE );
|
||||
gtk_tree_view_append_column( page->view, c );
|
||||
w = gtk_scrolled_window_new( NULL, NULL );
|
||||
gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC );
|
||||
gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
|
||||
sel = gtk_tree_view_get_selection( page->view );
|
||||
page->sel = sel;
|
||||
g_signal_connect( sel, "changed",
|
||||
G_CALLBACK( onTrackerSelectionChanged ), page );
|
||||
g_signal_connect( sel, "changed", G_CALLBACK( onTrackerSelectionChanged ), page );
|
||||
gtk_tree_selection_set_mode( sel, GTK_SELECTION_MULTIPLE );
|
||||
gtk_container_add( GTK_CONTAINER( w ), GTK_WIDGET( page->view ) );
|
||||
gtk_widget_set_size_request( w, -1, 133 );
|
||||
fr = gtk_frame_new( NULL );
|
||||
gtk_frame_set_shadow_type( GTK_FRAME( fr ), GTK_SHADOW_IN );
|
||||
gtk_container_add( GTK_CONTAINER( fr ), w );
|
||||
g_object_unref( G_OBJECT( m ) );
|
||||
|
||||
w = gtk_button_new_from_stock( GTK_STOCK_ADD );
|
||||
g_signal_connect( w, "clicked", G_CALLBACK( onTrackerAddClicked ), page );
|
||||
|
@ -366,7 +374,8 @@ tracker_list_new( TrTorrent * gtor )
|
|||
onTrackerRemoveClicked ), page );
|
||||
gtk_box_pack_start( GTK_BOX( buttons ), w, TRUE, TRUE, 0 );
|
||||
page->remove_button = w;
|
||||
if( gtor )
|
||||
|
||||
if( !isNew )
|
||||
{
|
||||
w = gtk_button_new_from_stock( GTK_STOCK_SAVE );
|
||||
g_signal_connect( w, "clicked", G_CALLBACK(
|
||||
|
@ -390,6 +399,7 @@ tracker_list_new( TrTorrent * gtor )
|
|||
onTrackerSelectionChanged( sel, page );
|
||||
|
||||
g_object_set_data_full( G_OBJECT( top ), PAGE_KEY, page, g_free );
|
||||
tracker_list_set_torrent( top, torrentId );
|
||||
return top;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
#define TRACKER_LIST_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "tr-torrent.h"
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
GtkWidget* tracker_list_new( TrTorrent * gtor );
|
||||
void tracker_list_set_torrent( GtkWidget*, int torrentId );
|
||||
|
||||
void tracker_list_clear( GtkWidget* );
|
||||
|
||||
GtkWidget* tracker_list_new( tr_session*, int torrentId, gboolean isNew );
|
||||
|
||||
/**
|
||||
* @return an array of tr_tracker_info's. It's the caller's responsibility
|
||||
|
@ -17,4 +21,5 @@ void tracker_list_add_trackers( GtkWidget * list,
|
|||
const tr_tracker_info * trackers,
|
||||
int trackerCount );
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,9 +59,6 @@ void tr_torrentSetHasPiece( tr_torrent * tor,
|
|||
|
||||
void tr_torrentChangeMyPort( tr_torrent * session );
|
||||
|
||||
tr_torrent* tr_torrentFindFromId( tr_session * session,
|
||||
int id );
|
||||
|
||||
tr_torrent* tr_torrentFindFromHash( tr_session * session,
|
||||
const uint8_t * hash );
|
||||
|
||||
|
|
|
@ -953,6 +953,9 @@ uint64_t tr_torrentGetBytesLeftToAllocate( const tr_torrent * torrent );
|
|||
*/
|
||||
int tr_torrentId( const tr_torrent * torrent );
|
||||
|
||||
tr_torrent* tr_torrentFindFromId( tr_session * session, int id );
|
||||
|
||||
|
||||
/***
|
||||
**** Torrent speed limits
|
||||
****
|
||||
|
|
Loading…
Reference in New Issue