(trunk gtk) #1473: Properties dialog should let you edit/view multiple torrents at once

This commit is contained in:
Charles Kerr 2009-04-24 01:37:04 +00:00
parent 015baf83db
commit 7f60d9db17
14 changed files with 1934 additions and 1221 deletions

1
NEWS
View File

@ -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

View File

@ -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 =

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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 );
}

View File

@ -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 )

View File

@ -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 );
}

View File

@ -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 );
/**
***
**/

View File

@ -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;
}

View File

@ -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

View File

@ -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 );

View File

@ -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
****