mirror of
https://github.com/transmission/transmission.git
synced 2026-05-08 09:39:08 +01:00
patches from Charles Kerr to update the Inspector in GTK and fix some memory leaks
This commit is contained in:
@@ -214,6 +214,7 @@ cf_readfile(const char *file, const char *oldfile, gsize *len,
|
||||
}
|
||||
|
||||
done:
|
||||
g_free (path);
|
||||
if(NULL != err)
|
||||
g_error_free(err);
|
||||
if(NULL != io)
|
||||
@@ -280,6 +281,7 @@ cf_loadprefs(char **errstr) {
|
||||
cf_saveprefs(errstr);
|
||||
}
|
||||
|
||||
tr_bencFree(&val);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
|
||||
-557
@@ -111,36 +111,12 @@ static void
|
||||
dirclick(GtkWidget *widget, gpointer gdata);
|
||||
static void
|
||||
addresp(GtkWidget *widget, gint resp, gpointer gdata);
|
||||
static GtkWidget *
|
||||
makeinfotab( TrTorrent * tor, struct infowind * iw );
|
||||
static void
|
||||
infoupdate( struct infowind * iw, int force );
|
||||
static void
|
||||
fmtpeercount( GtkLabel * label, int count );
|
||||
static void
|
||||
promptdirnocore( gpointer gdata, GObject * core );
|
||||
static void
|
||||
promptresp( GtkWidget * widget, gint resp, gpointer data );
|
||||
static void
|
||||
quitresp( GtkWidget * widget, gint resp, gpointer data );
|
||||
static GtkWidget *
|
||||
makefilestab( TrTorrent * tor, GtkTreeModel ** modelret );
|
||||
static void
|
||||
stylekludge( GObject * obj, GParamSpec * spec, gpointer data );
|
||||
static void
|
||||
infowinddead( GtkWidget * widget, gpointer data );
|
||||
static void
|
||||
infotorclosed( gpointer data, GObject * tor );
|
||||
static void
|
||||
parsepath( GtkTreeStore * store, GtkTreeIter * ret,
|
||||
const char * path, int index, uint64_t size );
|
||||
static uint64_t
|
||||
getdirtotals( GtkTreeStore * store, GtkTreeIter * parent );
|
||||
static gboolean
|
||||
infowindupdate( gpointer data );
|
||||
static float
|
||||
updateprogress( GtkTreeModel * model, GtkTreeIter * parent,
|
||||
uint64_t total, float * progress );
|
||||
|
||||
void
|
||||
makeaddwind( GtkWindow * parent, TrCore * core )
|
||||
@@ -278,258 +254,6 @@ addresp(GtkWidget *widget, gint resp, gpointer gdata) {
|
||||
gtk_widget_destroy(widget);
|
||||
}
|
||||
|
||||
void
|
||||
makeinfowind( GtkWindow * parent, GtkTreeModel * model, GtkTreePath * path,
|
||||
TrTorrent * tor )
|
||||
{
|
||||
struct infowind * iw;
|
||||
GtkWidget * wind, * box, * label, * sep, * tabs, * page;
|
||||
tr_info_t * inf;
|
||||
char * name, * size;
|
||||
|
||||
iw = g_new0( struct infowind, 1 );
|
||||
inf = tr_torrent_info( tor );
|
||||
name = g_strdup_printf( _("%s - Properties for %s"),
|
||||
g_get_application_name(), inf->name );
|
||||
wind = gtk_dialog_new_with_buttons( name, parent,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT |
|
||||
GTK_DIALOG_NO_SEPARATOR,
|
||||
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
|
||||
NULL );
|
||||
g_free( name );
|
||||
gtk_dialog_set_default_response( GTK_DIALOG( wind ), GTK_RESPONSE_ACCEPT );
|
||||
gtk_window_set_resizable( GTK_WINDOW( wind ), TRUE );
|
||||
gtk_window_set_role( GTK_WINDOW( wind ), "tr-info" );
|
||||
gtk_widget_set_name( wind, "TransmissionDialog" );
|
||||
box = GTK_DIALOG( wind )->vbox;
|
||||
|
||||
/* add label with file name and size */
|
||||
label = gtk_label_new( NULL );
|
||||
size = readablesize( inf->totalSize );
|
||||
name = g_markup_printf_escaped( "<big>%s (%s)</big>", inf->name, size );
|
||||
free( size );
|
||||
gtk_label_set_markup( GTK_LABEL( label ), name );
|
||||
g_free( name );
|
||||
gtk_label_set_selectable( GTK_LABEL( label ), TRUE );
|
||||
gtk_widget_show( label );
|
||||
gtk_box_pack_start( GTK_BOX( box ), label, FALSE, FALSE, 6 );
|
||||
|
||||
/* add separator */
|
||||
sep = gtk_hseparator_new();
|
||||
gtk_widget_show( sep );
|
||||
gtk_box_pack_start( GTK_BOX( box ), sep, FALSE, FALSE, 6 );
|
||||
|
||||
/* add tab bar */
|
||||
tabs = gtk_notebook_new();
|
||||
gtk_widget_show( tabs );
|
||||
gtk_box_pack_start( GTK_BOX( box ), tabs, TRUE, TRUE, 6 );
|
||||
|
||||
/* add general tab */
|
||||
label = gtk_label_new( _("General") );
|
||||
gtk_widget_show( label );
|
||||
page = makeinfotab( tor, iw );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( tabs ), page, label );
|
||||
|
||||
/* add files tab */
|
||||
label = gtk_label_new( _("Files") );
|
||||
gtk_widget_show( label );
|
||||
/* XXX should use sizingmagic() here */
|
||||
page = makefilestab( tor, &iw->filesmodel );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( tabs ), page, label );
|
||||
|
||||
/* set up the callback data */
|
||||
iw->widget = wind;
|
||||
iw->tor = tor;
|
||||
iw->size = inf->totalSize;
|
||||
iw->model = model;
|
||||
iw->row = gtk_tree_row_reference_new( model, path );
|
||||
iw->timer = g_timeout_add( UPDATE_INTERVAL, infowindupdate, iw );
|
||||
|
||||
g_object_ref( model );
|
||||
g_object_weak_ref( G_OBJECT( tor ), infotorclosed, iw );
|
||||
g_signal_connect( wind, "destroy", G_CALLBACK( infowinddead ), iw );
|
||||
g_signal_connect( wind, "response", G_CALLBACK( gtk_widget_destroy ), 0 );
|
||||
infoupdate( iw, 1 );
|
||||
infowindupdate( iw );
|
||||
|
||||
gtk_widget_show( wind );
|
||||
}
|
||||
|
||||
#define INFOLINE( tab, ii, nam, val ) \
|
||||
do \
|
||||
{ \
|
||||
char * txt = g_markup_printf_escaped( "<b>%s</b>", (nam) ); \
|
||||
GtkWidget * wid = gtk_label_new( NULL ); \
|
||||
gtk_misc_set_alignment( GTK_MISC( wid ), 0, .5 ); \
|
||||
gtk_label_set_markup( GTK_LABEL( wid ), txt ); \
|
||||
gtk_table_attach( GTK_TABLE( (tab) ), wid, 0, 1, (ii), (ii) + 1, \
|
||||
GTK_FILL, GTK_FILL, 0, 0 ); \
|
||||
gtk_label_set_selectable( GTK_LABEL( (val) ), TRUE ); \
|
||||
gtk_misc_set_alignment( GTK_MISC( (val) ), 0, .5 ); \
|
||||
gtk_table_attach( GTK_TABLE( (tab) ), (val), 1, 2, (ii), (ii) + 1, \
|
||||
GTK_FILL, GTK_FILL, 0, 0); \
|
||||
(ii)++; \
|
||||
g_free( txt ); \
|
||||
} while( 0 )
|
||||
|
||||
#define INFOLINEF( tab, ii, fmt, nam, val ) \
|
||||
do \
|
||||
{ \
|
||||
char * buf = g_strdup_printf( fmt, val ); \
|
||||
GtkWidget * lwid = gtk_label_new( buf ); \
|
||||
g_free( buf ); \
|
||||
INFOLINE( tab, ii, nam, lwid ); \
|
||||
} while( 0 )
|
||||
|
||||
#define INFOLINEW( tab, ii, nam, val ) \
|
||||
do \
|
||||
{ \
|
||||
GtkWidget * lwid = gtk_label_new( (val) ); \
|
||||
INFOLINE( (tab), (ii), (nam), lwid ); \
|
||||
} while( 0 )
|
||||
|
||||
#define INFOLINEA( tab, ii, nam, val ) \
|
||||
do \
|
||||
{ \
|
||||
GtkWidget * lwid = gtk_label_new( (val) ); \
|
||||
g_free( val ); \
|
||||
INFOLINE( (tab), (ii), (nam), lwid ); \
|
||||
} while( 0 )
|
||||
|
||||
#define INFOLINEU( tab, ii, nam, stor ) \
|
||||
do \
|
||||
{ \
|
||||
GtkWidget * lwid = gtk_label_new( NULL ); \
|
||||
(stor) = GTK_LABEL( lwid ); \
|
||||
INFOLINE( (tab), (ii), (nam), lwid); \
|
||||
} while( 0 )
|
||||
|
||||
#define INFOSEP( tab, ii ) \
|
||||
do \
|
||||
{ \
|
||||
GtkWidget * wid = gtk_hseparator_new(); \
|
||||
gtk_table_attach( GTK_TABLE( (tab) ), wid, 0, 2, (ii), (ii) + 1, \
|
||||
GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0 ); \
|
||||
(ii)++; \
|
||||
} while( 0 )
|
||||
|
||||
GtkWidget *
|
||||
makeinfotab( TrTorrent * tor, struct infowind * iw )
|
||||
{
|
||||
const int rowcount = 17;
|
||||
tr_info_t * inf;
|
||||
int ii;
|
||||
GtkWidget * table;
|
||||
|
||||
inf = tr_torrent_info( tor );
|
||||
table = gtk_table_new( rowcount, 2, FALSE );
|
||||
gtk_table_set_col_spacings( GTK_TABLE( table ), 12 );
|
||||
gtk_table_set_row_spacings( GTK_TABLE( table ), 12 );
|
||||
gtk_container_set_border_width( GTK_CONTAINER( table ), 6 );
|
||||
|
||||
ii = 0;
|
||||
|
||||
INFOLINEU( table, ii, _("Tracker:"), iw->inf.trackwid );
|
||||
INFOLINEU( table, ii, _("Announce:"), iw->inf.annwid );
|
||||
INFOLINEU( table, ii, _("Scrape:"), iw->inf.scrwid );
|
||||
INFOSEP( table, ii );
|
||||
INFOLINEW( table, ii, _("Info Hash:"), inf->hashString );
|
||||
INFOLINEA( table, ii, _("Piece Size:"), readablesize( inf->pieceSize ) );
|
||||
INFOLINEF( table, ii, "%i", _("Pieces:"), inf->pieceCount );
|
||||
INFOLINEA( table, ii, _("Total Size:"), readablesize( inf->totalSize ) );
|
||||
INFOSEP( table, ii );
|
||||
INFOLINEU( table, ii, _("Seeders:"), iw->inf.seedwid );
|
||||
INFOLINEU( table, ii, _("Leechers:"), iw->inf.leechwid );
|
||||
INFOLINEU( table, ii, _("Completed:"), iw->inf.donewid );
|
||||
INFOSEP( table, ii );
|
||||
INFOLINEW( table, ii, _("Directory:"),
|
||||
tr_torrentGetFolder( tr_torrent_handle( tor ) ) );
|
||||
INFOLINEU( table, ii, _("Downloaded:"), iw->inf.downwid );
|
||||
INFOLINEU( table, ii, _("Uploaded:"), iw->inf.upwid );
|
||||
INFOLINEU( table, ii, _("Remaining:"), iw->inf.leftwid );
|
||||
|
||||
g_assert( rowcount == ii );
|
||||
|
||||
gtk_widget_show_all( table );
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void
|
||||
infoupdate( struct infowind * iw, int force )
|
||||
{
|
||||
int seed, leech, done;
|
||||
uint64_t up, down, left;
|
||||
tr_tracker_info_t * track;
|
||||
GtkTreePath * path;
|
||||
GtkTreeIter iter;
|
||||
char * str;
|
||||
|
||||
path = gtk_tree_row_reference_get_path( iw->row );
|
||||
if( NULL == path || !gtk_tree_model_get_iter( iw->model, &iter, path ) )
|
||||
{
|
||||
g_free( path );
|
||||
return;
|
||||
}
|
||||
g_free( path );
|
||||
gtk_tree_model_get( iw->model, &iter, MC_TRACKER, &track,
|
||||
MC_SEED, &seed, MC_LEECH, &leech, MC_DONE, &done,
|
||||
MC_DOWN, &down, MC_UP, &up, MC_LEFT, &left, -1 );
|
||||
|
||||
if( track != iw->inf.track || force )
|
||||
{
|
||||
if( 80 == track->port )
|
||||
{
|
||||
str = g_strdup_printf( "http://%s", track->address );
|
||||
}
|
||||
else
|
||||
{
|
||||
str = g_strdup_printf( "http://%s:%i",
|
||||
track->address, track->port );
|
||||
}
|
||||
gtk_label_set_text( iw->inf.trackwid, str );
|
||||
g_free( str );
|
||||
gtk_label_set_text( iw->inf.annwid, track->announce );
|
||||
gtk_label_set_text( iw->inf.scrwid, track->scrape );
|
||||
}
|
||||
if( seed != iw->inf.seed || force )
|
||||
{
|
||||
fmtpeercount( iw->inf.seedwid, seed );
|
||||
iw->inf.seed = seed;
|
||||
}
|
||||
if( leech != iw->inf.leech || force )
|
||||
{
|
||||
fmtpeercount( iw->inf.leechwid, leech );
|
||||
iw->inf.leech = leech;
|
||||
}
|
||||
if( done != iw->inf.done || force )
|
||||
{
|
||||
fmtpeercount( iw->inf.donewid, done );
|
||||
iw->inf.done = done;
|
||||
}
|
||||
if( down != iw->inf.down || force )
|
||||
{
|
||||
str = readablesize( down );
|
||||
gtk_label_set_text( iw->inf.downwid, str );
|
||||
g_free( str );
|
||||
iw->inf.down = down;
|
||||
}
|
||||
if( up != iw->inf.up || force )
|
||||
{
|
||||
str = readablesize( up );
|
||||
gtk_label_set_text( iw->inf.upwid, str );
|
||||
g_free( str );
|
||||
iw->inf.up = up;
|
||||
}
|
||||
if( left != iw->inf.left || force )
|
||||
{
|
||||
str = readablesize( left );
|
||||
gtk_label_set_text( iw->inf.leftwid, str );
|
||||
g_free( str );
|
||||
iw->inf.left = left;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fmtpeercount( GtkLabel * label, int count )
|
||||
{
|
||||
@@ -681,284 +405,3 @@ quitresp( GtkWidget * widget, gint resp, gpointer data )
|
||||
g_free( stuff );
|
||||
gtk_widget_destroy( widget );
|
||||
}
|
||||
|
||||
enum filescols
|
||||
{
|
||||
FC_STOCK = 0, FC_LABEL, FC_PROG, FC_KEY, FC_INDEX, FC_SIZE, FC__MAX
|
||||
};
|
||||
|
||||
GtkWidget *
|
||||
makefilestab( TrTorrent * tor, GtkTreeModel ** modelret )
|
||||
{
|
||||
GType cols[] =
|
||||
{
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_FLOAT,
|
||||
G_TYPE_STRING, G_TYPE_INT, G_TYPE_UINT64
|
||||
};
|
||||
tr_info_t * inf;
|
||||
GtkTreeStore * store;
|
||||
int ii;
|
||||
GtkWidget * view, * scroll, * frame;
|
||||
GtkCellRenderer * rend;
|
||||
GtkTreeViewColumn * col;
|
||||
GtkTreeSelection * sel;
|
||||
char * label;
|
||||
|
||||
g_assert( ALEN( cols ) == FC__MAX );
|
||||
|
||||
/* set up the model */
|
||||
inf = tr_torrent_info( tor );
|
||||
store = gtk_tree_store_newv( FC__MAX, cols );
|
||||
*modelret = GTK_TREE_MODEL( store );
|
||||
for( ii = 0; ii < inf->fileCount; ii++ )
|
||||
{
|
||||
parsepath( store, NULL, STRIPROOT( inf->files[ii].name ),
|
||||
ii, inf->files[ii].length );
|
||||
}
|
||||
getdirtotals( store, NULL );
|
||||
gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE( store ),
|
||||
FC_KEY, GTK_SORT_ASCENDING );
|
||||
|
||||
/* create the view */
|
||||
view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) );
|
||||
/* add file column */
|
||||
col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_set_expand( col, TRUE );
|
||||
gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_AUTOSIZE );
|
||||
gtk_tree_view_column_set_title( col, _("File") );
|
||||
/* add icon renderer */
|
||||
rend = gtk_cell_renderer_pixbuf_new();
|
||||
gtk_tree_view_column_pack_start( col, rend, FALSE );
|
||||
gtk_tree_view_column_add_attribute( col, rend, "stock-id", FC_STOCK );
|
||||
/* add text renderer */
|
||||
rend = gtk_cell_renderer_text_new();
|
||||
g_object_set( rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
|
||||
gtk_tree_view_column_pack_start( col, rend, TRUE );
|
||||
gtk_tree_view_column_add_attribute( col, rend, "markup", FC_LABEL );
|
||||
gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
|
||||
/* add progress column */
|
||||
col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_set_title( col, _("Progress") );
|
||||
rend = tr_cell_renderer_progress_new();
|
||||
/* this string is only used to determine the size of the progress bar */
|
||||
label = g_markup_printf_escaped( "<small>%s</small>", _(" fnord fnord ") );
|
||||
g_object_set( rend, "show-text", FALSE, "bar-sizing", label, NULL );
|
||||
g_free( label );
|
||||
gtk_tree_view_column_pack_start( col, rend, FALSE );
|
||||
gtk_tree_view_column_add_attribute( col, rend, "progress", FC_PROG );
|
||||
gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
|
||||
/* XXX this shouldn't be necessary */
|
||||
g_signal_connect( view, "notify::style", G_CALLBACK( stylekludge ), rend );
|
||||
/* set up view */
|
||||
sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) );
|
||||
gtk_tree_selection_set_mode( sel, GTK_SELECTION_NONE );
|
||||
gtk_tree_view_expand_all( GTK_TREE_VIEW( view ) );
|
||||
gtk_tree_view_set_search_column( GTK_TREE_VIEW( view ), FC_LABEL );
|
||||
gtk_widget_show( view );
|
||||
|
||||
/* create the scrolled window and stick the view in it */
|
||||
scroll = gtk_scrolled_window_new( NULL, NULL );
|
||||
gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scroll ),
|
||||
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
|
||||
gtk_container_add( GTK_CONTAINER( scroll ), view );
|
||||
gtk_widget_show( scroll );
|
||||
|
||||
/* create a frame around the scroll to make it look a little better */
|
||||
frame = gtk_frame_new( NULL );
|
||||
gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_IN );
|
||||
gtk_container_add( GTK_CONTAINER( frame ), scroll );
|
||||
gtk_widget_show( frame );
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
/* kludge to have the progress bars notice theme changes */
|
||||
static void
|
||||
stylekludge( GObject * obj, GParamSpec * spec, gpointer data )
|
||||
{
|
||||
TrCellRendererProgress * rend = TR_CELL_RENDERER_PROGRESS( data );
|
||||
|
||||
if( 0 == strcmp( "style", spec->name ) )
|
||||
{
|
||||
tr_cell_renderer_progress_reset_style( rend );
|
||||
gtk_widget_queue_draw( GTK_WIDGET( obj ) );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
infowinddead( GtkWidget * widget SHUTUP, gpointer data )
|
||||
{
|
||||
struct infowind * iw = data;
|
||||
|
||||
if( NULL != iw->widget )
|
||||
{
|
||||
g_object_weak_unref( G_OBJECT( iw->tor ), infotorclosed, iw );
|
||||
infotorclosed( iw, G_OBJECT( iw->tor ) );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
infotorclosed( gpointer data, GObject * tor SHUTUP )
|
||||
{
|
||||
struct infowind * iw = data;
|
||||
GtkWidget * widget;
|
||||
|
||||
/* neuter the widget's destroy callback */
|
||||
widget = iw->widget;
|
||||
iw->widget = NULL;
|
||||
|
||||
g_source_remove( iw->timer );
|
||||
g_object_unref( iw->filesmodel );
|
||||
g_object_unref( iw->model );
|
||||
gtk_tree_row_reference_free( iw->row );
|
||||
gtk_widget_destroy( widget );
|
||||
g_free( iw );
|
||||
}
|
||||
|
||||
static void
|
||||
parsepath( GtkTreeStore * store, GtkTreeIter * ret,
|
||||
const char * path, int index, uint64_t size )
|
||||
{
|
||||
GtkTreeModel * model;
|
||||
GtkTreeIter * parent, start, iter;
|
||||
char * file, * dir, * lower, * mykey, * modelkey;
|
||||
const char * stock;
|
||||
|
||||
model = GTK_TREE_MODEL( store );
|
||||
parent = NULL;
|
||||
file = g_path_get_basename( path );
|
||||
if( 0 != strcmp( file, path ) )
|
||||
{
|
||||
dir = g_path_get_dirname( path );
|
||||
parsepath( store, &start, dir, index, size );
|
||||
g_free( dir );
|
||||
parent = &start;
|
||||
}
|
||||
|
||||
lower = g_utf8_casefold( file, -1 );
|
||||
mykey = g_utf8_collate_key( lower, -1 );
|
||||
if( gtk_tree_model_iter_children( model, &iter, parent ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
gtk_tree_model_get( model, &iter, FC_KEY, &modelkey, -1 );
|
||||
if( NULL != modelkey && 0 == strcmp( mykey, modelkey ) )
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
while( gtk_tree_model_iter_next( model, &iter ) );
|
||||
}
|
||||
|
||||
gtk_tree_store_append( store, &iter, parent );
|
||||
if( NULL == ret )
|
||||
{
|
||||
stock = GTK_STOCK_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
stock = GTK_STOCK_DIRECTORY;
|
||||
size = 0;
|
||||
index = -1;
|
||||
}
|
||||
gtk_tree_store_set( store, &iter, FC_INDEX, index, FC_LABEL, file,
|
||||
FC_KEY, mykey, FC_STOCK, stock, FC_SIZE, size, -1 );
|
||||
done:
|
||||
g_free( mykey );
|
||||
g_free( lower );
|
||||
g_free( file );
|
||||
if( NULL != ret )
|
||||
{
|
||||
memcpy( ret, &iter, sizeof( iter ) );
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
getdirtotals( GtkTreeStore * store, GtkTreeIter * parent )
|
||||
{
|
||||
GtkTreeModel * model;
|
||||
GtkTreeIter iter;
|
||||
uint64_t mysize, subsize;
|
||||
char * sizestr, * name, * label;
|
||||
|
||||
model = GTK_TREE_MODEL( store );
|
||||
mysize = 0;
|
||||
if( gtk_tree_model_iter_children( model, &iter, parent ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
if( gtk_tree_model_iter_has_child( model, &iter ) )
|
||||
{
|
||||
subsize = getdirtotals( store, &iter );
|
||||
gtk_tree_store_set( store, &iter, FC_SIZE, subsize, -1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_tree_model_get( model, &iter, FC_SIZE, &subsize, -1 );
|
||||
}
|
||||
gtk_tree_model_get( model, &iter, FC_LABEL, &name, -1 );
|
||||
sizestr = readablesize( subsize );
|
||||
label = g_markup_printf_escaped( "<small>%s (%s)</small>",
|
||||
name, sizestr );
|
||||
g_free( sizestr );
|
||||
g_free( name );
|
||||
gtk_tree_store_set( store, &iter, FC_LABEL, label, -1 );
|
||||
g_free( label );
|
||||
mysize += subsize;
|
||||
}
|
||||
while( gtk_tree_model_iter_next( model, &iter ) );
|
||||
}
|
||||
|
||||
return mysize;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
infowindupdate( gpointer data )
|
||||
{
|
||||
struct infowind * iw;
|
||||
float * progress;
|
||||
|
||||
iw = data;
|
||||
progress = tr_torrentCompletion( tr_torrent_handle( iw->tor ) );
|
||||
updateprogress( iw->filesmodel, NULL, iw->size, progress );
|
||||
free( progress );
|
||||
infoupdate( iw, 0 );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static float
|
||||
updateprogress( GtkTreeModel * model, GtkTreeIter * parent,
|
||||
uint64_t total, float * progress )
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
float myprog, subprog;
|
||||
int index;
|
||||
uint64_t size;
|
||||
|
||||
myprog = 0.0;
|
||||
if( gtk_tree_model_iter_children( model, &iter, parent ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
if( gtk_tree_model_iter_has_child( model, &iter ) )
|
||||
{
|
||||
gtk_tree_model_get( model, &iter, FC_SIZE, &size, -1 );
|
||||
subprog = updateprogress( model, &iter, size, progress );
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_tree_model_get( model, &iter,
|
||||
FC_SIZE, &size, FC_INDEX, &index, -1 );
|
||||
g_assert( 0 <= index );
|
||||
subprog = progress[index];
|
||||
}
|
||||
gtk_tree_store_set( GTK_TREE_STORE( model ), &iter,
|
||||
FC_PROG, subprog, -1 );
|
||||
myprog += subprog * ( total ? ( float )size / ( float )total : 1 );
|
||||
}
|
||||
while( gtk_tree_model_iter_next( model, &iter ) );
|
||||
}
|
||||
|
||||
return myprog;
|
||||
}
|
||||
|
||||
@@ -33,11 +33,6 @@
|
||||
void
|
||||
makeaddwind( GtkWindow * parent, TrCore * core );
|
||||
|
||||
/* show the info window for a torrent */
|
||||
void
|
||||
makeinfowind( GtkWindow * parent, GtkTreeModel * model, GtkTreePath * path,
|
||||
TrTorrent * tor );
|
||||
|
||||
/* prompt for a download directory for torrents, then add them */
|
||||
void
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
|
||||
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
/* GdkPixbuf RGBA C-Source image dump */
|
||||
|
||||
#ifdef __SUNPRO_C
|
||||
#pragma align 4 (red_dot)
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
const guint8 red_dot[] __attribute__ ((__aligned__ (4))) =
|
||||
#else
|
||||
const guint8 red_dot[] =
|
||||
#endif
|
||||
{ ""
|
||||
/* Pixbuf magic (0x47646b50) */
|
||||
"GdkP"
|
||||
/* length: header (24) + pixel_data (1024) */
|
||||
"\0\0\4\30"
|
||||
/* pixdata_type (0x1010002) */
|
||||
"\1\1\0\2"
|
||||
/* rowstride (64) */
|
||||
"\0\0\0@"
|
||||
/* width (16) */
|
||||
"\0\0\0\20"
|
||||
/* height (16) */
|
||||
"\0\0\0\20"
|
||||
/* pixel_data: */
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\1Z\0\0]P\0\0\253O\0\0\346O\0\0\346P\0\0\253Z\0\0]\0\0"
|
||||
"\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2"
|
||||
"Z\0\0\201v\2\2\377\271gg\377\323\210\210\377\323\210\210\377\271gg\377"
|
||||
"v\2\2\377Z\0\0\201\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\2b\0\0`z\1\1\377\320pp\377\353\254\254\377\372\315\315\377\372\315"
|
||||
"\315\377\353\254\254\377\320pp\377z\1\1\377b\0\0`\0\0\0\2\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\1\0\0\0\6_\0\0\260\245##\377\322__\377\333tt\377\322"
|
||||
"]]\377\323]]\377\333tt\377\322__\377\245##\377_\0\0\260\0\0\0\6\0\0\0"
|
||||
"\1\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\13f\0\0\350\266\16\16\377\303\35\35"
|
||||
"\377\31600\377\32200\377\32400\377\31600\377\302\35\35\377\266\16\16"
|
||||
"\377f\0\0\350\0\0\0\13\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\20n\0\0"
|
||||
"\351\263\0\0\377\320\17\17\377\332\22\22\377\336\22\22\377\341\22\22"
|
||||
"\377\341\22\22\377\322\17\17\377\263\0\0\377n\0\0\351\0\0\0\20\0\0\0"
|
||||
"\2\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\22q\0\0\271\263\0\0\377\345\0\0\377"
|
||||
"\353\0\0\377\357\0\0\377\362\0\0\377\365\0\0\377\347\0\0\377\262\0\0"
|
||||
"\377q\0\0\271\0\0\0\22\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\20r\0\0"
|
||||
"x\266\0\0\377\377\35\35\377\377\10\10\377\377\27\27\377\377\27\27\377"
|
||||
"\377\14\14\377\377\36\36\377\266\0\0\377r\0\0x\0\0\0\20\0\0\0\2\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\1\0\0\0\13\0\0\0%\244\0\0\236\354\0\0\377\377FF\377"
|
||||
"\377gg\377\377gg\377\377RR\377\357\0\0\377\251\0\0\236\0\0\0%\0\0\0\13"
|
||||
"\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\23\0\0\0/\247\0\0\206"
|
||||
"\333\0\0\303\366\30\30\355\366\30\30\355\333\0\0\303\251\0\0\206\0\0"
|
||||
"\0/\0\0\0\23\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\5"
|
||||
"\0\0\0\24\0\0\0(\0\0\0""7\0\0\0\77\0\0\0\77\0\0\0""7\0\0\0(\0\0\0\24"
|
||||
"\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0"
|
||||
"\0\5\0\0\0\14\0\0\0\23\0\0\0\27\0\0\0\27\0\0\0\23\0\0\0\14\0\0\0\5\0"
|
||||
"\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0"};
|
||||
|
||||
|
||||
/* GdkPixbuf RGBA C-Source image dump */
|
||||
|
||||
#ifdef __SUNPRO_C
|
||||
#pragma align 4 (yellow_dot)
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
const guint8 yellow_dot[] __attribute__ ((__aligned__ (4))) =
|
||||
#else
|
||||
const guint8 yellow_dot[] =
|
||||
#endif
|
||||
{ ""
|
||||
/* Pixbuf magic (0x47646b50) */
|
||||
"GdkP"
|
||||
/* length: header (24) + pixel_data (1024) */
|
||||
"\0\0\4\30"
|
||||
/* pixdata_type (0x1010002) */
|
||||
"\1\1\0\2"
|
||||
/* rowstride (64) */
|
||||
"\0\0\0@"
|
||||
/* width (16) */
|
||||
"\0\0\0\20"
|
||||
/* height (16) */
|
||||
"\0\0\0\20"
|
||||
/* pixel_data: */
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\1\2344\0]\212.\0\253\207-\0\346\207-\0\346\212.\0\253"
|
||||
"\2344\0]\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\2\2247\0\201\270T\2\377\353\241g\377\374\275\210\377\374\275"
|
||||
"\210\377\353\241g\377\270T\2\377\2247\0\201\0\0\0\2\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\242B\0`\275[\1\377\375\270p\377\377\335"
|
||||
"\256\377\377\360\320\377\377\360\320\377\377\335\256\377\375\270p\377"
|
||||
"\275[\1\377\242B\0`\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\6\233"
|
||||
"B\0\260\340\206#\377\375\271a\377\377\307z\377\377\274d\377\377\275d"
|
||||
"\377\377\307z\377\375\271a\377\340\206#\377\233B\0\260\0\0\0\6\0\0\0"
|
||||
"\1\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\13\250L\0\350\357\226\16\377\367\245"
|
||||
"\40\377\373\2615\377\374\2645\377\375\2665\377\373\2615\377\367\243\40"
|
||||
"\377\357\226\16\377\250L\0\350\0\0\0\13\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\2\0\0\0\20\264Y\0\351\356\222\0\377\373\262\22\377\375\271\24\377\377"
|
||||
"\275\24\377\377\277\24\377\377\277\24\377\373\263\22\377\356\222\0\377"
|
||||
"\264Y\0\351\0\0\0\20\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\22\267_\0"
|
||||
"\271\353\231\0\377\377\304\0\377\377\311\0\377\377\314\0\377\377\317"
|
||||
"\0\377\377\317\0\377\377\304\0\377\353\227\0\377\267_\0\271\0\0\0\22"
|
||||
"\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\20\252c\0x\353\226\0\377\377\330"
|
||||
"\0\377\377\333\0\377\377\345\32\377\377\352%\377\377\340\0\377\377\330"
|
||||
"\0\377\353\226\0\377\252f\0x\0\0\0\20\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\1"
|
||||
"\0\0\0\13\6\0\0%\301u\0\236\373\262\0\377\377\353H\377\377\375t\377\377"
|
||||
"\377\204\377\377\357V\377\373\262\0\377\301w\0\236\6\0\0%\0\0\0\13\0"
|
||||
"\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\23\0\0\0/\255\203\0\206"
|
||||
"\337\247\0\303\366\313\35\355\366\322,\355\337\252\0\303\255\205\0\206"
|
||||
"\0\0\0/\0\0\0\23\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0"
|
||||
"\0\5\0\0\0\24\0\0\0(\0\0\0""7\0\0\0\77\0\0\0\77\0\0\0""7\0\0\0(\0\0\0"
|
||||
"\24\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0"
|
||||
"\0\0\5\0\0\0\14\0\0\0\23\0\0\0\27\0\0\0\27\0\0\0\23\0\0\0\14\0\0\0\5"
|
||||
"\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0"};
|
||||
|
||||
|
||||
/* GdkPixbuf RGBA C-Source image dump */
|
||||
|
||||
#ifdef __SUNPRO_C
|
||||
#pragma align 4 (green_dot)
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
const guint8 green_dot[] __attribute__ ((__aligned__ (4))) =
|
||||
#else
|
||||
const guint8 green_dot[] =
|
||||
#endif
|
||||
{ ""
|
||||
/* Pixbuf magic (0x47646b50) */
|
||||
"GdkP"
|
||||
/* length: header (24) + pixel_data (1024) */
|
||||
"\0\0\4\30"
|
||||
/* pixdata_type (0x1010002) */
|
||||
"\1\1\0\2"
|
||||
/* rowstride (64) */
|
||||
"\0\0\0@"
|
||||
/* width (16) */
|
||||
"\0\0\0\20"
|
||||
/* height (16) */
|
||||
"\0\0\0\20"
|
||||
/* pixel_data: */
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\1\0U\0]\0I\0\253\0F\0\346\0F\0\346\0I\0\253\0U\0]\0\0"
|
||||
"\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2"
|
||||
"\1Q\0\201\40n\2\377}\263g\377\232\316\210\377\232\316\210\377}\263g\377"
|
||||
"\40n\2\377\1Q\0\201\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\2\12\\\0`$s\1\377\214\314p\377\301\351\256\377\335\370\320\377\335"
|
||||
"\370\320\377\301\351\256\377\214\314p\377$s\1\377\12\\\0`\0\0\0\2\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\6\17X\0\260P\234#\377\210\315a\377"
|
||||
"\235\330z\377\214\317d\377\214\317d\377\235\330z\377\210\315a\377P\234"
|
||||
"#\377\17X\0\260\0\0\0\6\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\13\27`"
|
||||
"\0\350M\255\16\377a\274\40\377t\3055\377y\3115\377z\3115\377t\3055\377"
|
||||
"^\274\40\377M\255\16\377\27`\0\350\0\0\0\13\0\0\0\2\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\2\0\0\0\20\37g\0\351;\253\0\377i\307\22\377v\315\24\377}\317\24"
|
||||
"\377\201\322\24\377\200\322\24\377j\307\22\377;\253\0\377\37g\0\351\0"
|
||||
"\0\0\20\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\22&l\0\271J\254\0\377z"
|
||||
"\325\0\377\205\332\0\377\213\333\0\377\220\335\0\377\222\337\0\377~\326"
|
||||
"\0\377H\253\0\377&l\0\271\0\0\0\22\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\2\0"
|
||||
"\0\0\20.n\0xX\243\0\377\224\345\0\377\235\351\0\377\260\360\32\377\267"
|
||||
"\364%\377\245\353\0\377\225\346\0\377X\243\0\377.n\0x\0\0\0\20\0\0\0"
|
||||
"\2\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\13\0\0\0%K\207\0\236z\305\0\377\267"
|
||||
"\364H\377\330\377t\377\337\377\204\377\276\367V\377}\310\0\377M\211\0"
|
||||
"\236\0\0\0%\0\0\0\13\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\23"
|
||||
"\0\0\0/U\220\0\206f\267\0\303|\330\35\355\201\336,\355i\271\0\303U\220"
|
||||
"\0\206\0\0\0/\0\0\0\23\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\1\0\0\0\5\0\0\0\24\0\0\0(\0\0\0""7\0\0\0\77\0\0\0\77\0\0\0""7\0\0\0"
|
||||
"(\0\0\0\24\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\1\0\0\0\5\0\0\0\14\0\0\0\23\0\0\0\27\0\0\0\27\0\0\0\23\0\0\0\14"
|
||||
"\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* Pan - A Newsreader for Gtk+
|
||||
* Copyright (C) 2002 Charles Kerr <charles@rebelbase.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "hig.h"
|
||||
|
||||
GtkWidget*
|
||||
hig_workarea_create (void)
|
||||
{
|
||||
GtkWidget * t = gtk_table_new (4, 100, FALSE);
|
||||
gtk_table_set_row_spacings (GTK_TABLE(t), 6);
|
||||
gtk_container_set_border_width (GTK_CONTAINER(t), 12);
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_add_section_divider (GtkWidget * table,
|
||||
int * row)
|
||||
{
|
||||
GtkWidget * w = gtk_alignment_new (0.0f, 0.0f, 0.0f, 0.0f);
|
||||
gtk_widget_set_usize (w, 0u, 6u);
|
||||
gtk_table_attach (GTK_TABLE(table), w, 0, 4, *row, *row+1, 0, 0, 0, 0);
|
||||
++*row;
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_add_section_title (GtkWidget * table,
|
||||
int * row,
|
||||
const char * section_title)
|
||||
{
|
||||
char buf[512];
|
||||
GtkWidget * l;
|
||||
|
||||
g_snprintf (buf, sizeof(buf), "<b>%s</b>", section_title);
|
||||
l = gtk_label_new (buf);
|
||||
gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
|
||||
gtk_label_set_use_markup (GTK_LABEL(l), TRUE);
|
||||
gtk_table_attach (GTK_TABLE(table), l, 0, 4, *row, *row+1, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
|
||||
++*row;
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_add_section_spacer (GtkWidget * table,
|
||||
int row,
|
||||
int items_in_section)
|
||||
{
|
||||
GtkWidget * w;
|
||||
|
||||
/* spacer to move the fields a little to the right of the name header */
|
||||
w = gtk_alignment_new (0.0f, 0.0f, 0.0f, 0.0f);
|
||||
gtk_widget_set_usize (w, 18u, 0u);
|
||||
gtk_table_attach (GTK_TABLE(table), w, 0, 1, row, row+items_in_section, 0, 0, 0, 0);
|
||||
|
||||
/* spacer between the controls and their labels */
|
||||
w = gtk_alignment_new (0.0f, 0.0f, 0.0f, 0.0f);
|
||||
gtk_widget_set_usize (w, 12u, 0u);
|
||||
gtk_table_attach (GTK_TABLE(table), w, 2, 3, row, row+items_in_section, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_add_wide_control (GtkWidget * table,
|
||||
int * row,
|
||||
GtkWidget * w)
|
||||
{
|
||||
gtk_table_attach (GTK_TABLE(table), w,
|
||||
1, 4, *row, *row+1,
|
||||
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
|
||||
++*row;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
hig_workarea_add_wide_checkbutton (GtkWidget * table,
|
||||
int * row,
|
||||
const char * mnemonic_string,
|
||||
gboolean is_active)
|
||||
{
|
||||
GtkWidget * w = gtk_check_button_new_with_mnemonic (mnemonic_string);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(w), is_active);
|
||||
hig_workarea_add_wide_control (table, row, w);
|
||||
return w;
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_add_label_w (GtkWidget * table,
|
||||
int row,
|
||||
GtkWidget * l)
|
||||
{
|
||||
if (GTK_IS_MISC(l))
|
||||
gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.0f);
|
||||
if (GTK_IS_LABEL(l))
|
||||
gtk_label_set_use_markup (GTK_LABEL(l), TRUE);
|
||||
gtk_table_attach (GTK_TABLE(table), l, 1, 2, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
hig_workarea_add_label (GtkWidget * table,
|
||||
int row,
|
||||
const char * mnemonic_string)
|
||||
{
|
||||
GtkWidget * l = gtk_label_new_with_mnemonic (mnemonic_string);
|
||||
hig_workarea_add_label_w (table, row, l);
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_add_control (GtkWidget * table,
|
||||
int row,
|
||||
GtkWidget * control)
|
||||
{
|
||||
gtk_table_attach (GTK_TABLE(table), control,
|
||||
3, 4, row, row+1,
|
||||
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_add_row_w (GtkWidget * table,
|
||||
int * row,
|
||||
GtkWidget * label,
|
||||
GtkWidget * control,
|
||||
GtkWidget * mnemonic)
|
||||
{
|
||||
hig_workarea_add_label_w (table, *row, label);
|
||||
hig_workarea_add_control (table, *row, control);
|
||||
if (GTK_IS_LABEL(label))
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL(label),
|
||||
mnemonic ? mnemonic : control);
|
||||
++*row;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
hig_workarea_add_row (GtkWidget * table,
|
||||
int * row,
|
||||
const char * mnemonic_string,
|
||||
GtkWidget * control,
|
||||
GtkWidget * mnemonic)
|
||||
{
|
||||
GtkWidget * l = gtk_label_new_with_mnemonic (mnemonic_string);
|
||||
hig_workarea_add_row_w (table, row, l, control, mnemonic);
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
hig_workarea_finish (GtkWidget * table,
|
||||
int * row)
|
||||
{
|
||||
GtkWidget * w = gtk_alignment_new (0.0f, 0.0f, 0.0f, 0.0f);
|
||||
gtk_widget_set_size_request (w, 0u, 6u);
|
||||
gtk_table_attach_defaults (GTK_TABLE(table), w, 0, 4, *row, *row+1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/******************************************************************************
|
||||
* $Id:$
|
||||
*
|
||||
* Copyright (c) 2007 Transmission authors and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __HIG_H__
|
||||
#define __HIG_H__
|
||||
|
||||
#include <gtk/gtkwidget.h>
|
||||
|
||||
/**
|
||||
*** utility code to make it slightly less painful to create
|
||||
*** dialogs compliant with Gnome's Human Interface Guidelines
|
||||
**/
|
||||
|
||||
GtkWidget* hig_workarea_create (void);
|
||||
|
||||
void
|
||||
hig_workarea_add_section_divider (GtkWidget * table,
|
||||
int * row);
|
||||
|
||||
void
|
||||
hig_workarea_add_section_title (GtkWidget * table,
|
||||
int * row,
|
||||
const char * section_title);
|
||||
|
||||
void
|
||||
hig_workarea_add_section_spacer (GtkWidget * table,
|
||||
int row,
|
||||
int items_in_section);
|
||||
|
||||
void
|
||||
hig_workarea_add_wide_control (GtkWidget * table,
|
||||
int * row,
|
||||
GtkWidget * w);
|
||||
|
||||
GtkWidget*
|
||||
hig_workarea_add_wide_checkbutton (GtkWidget * table,
|
||||
int * row,
|
||||
const char * mnemonic_string,
|
||||
gboolean is_active);
|
||||
|
||||
GtkWidget*
|
||||
hig_workarea_add_label (GtkWidget * table,
|
||||
int row,
|
||||
const char * mnemonic_string);
|
||||
|
||||
void
|
||||
hig_workarea_add_label_w (GtkWidget * table,
|
||||
int row,
|
||||
GtkWidget * label_widget);
|
||||
|
||||
void
|
||||
hig_workarea_add_control (GtkWidget * table,
|
||||
int row,
|
||||
GtkWidget * control);
|
||||
|
||||
GtkWidget*
|
||||
hig_workarea_add_row (GtkWidget * table,
|
||||
int * row,
|
||||
const char * mnemonic_string,
|
||||
GtkWidget * control,
|
||||
GtkWidget * mnemonic_or_null_if_control_is_mnemonic);
|
||||
|
||||
void
|
||||
hig_workarea_add_row_w (GtkWidget * table,
|
||||
int * row,
|
||||
GtkWidget * label,
|
||||
GtkWidget * control,
|
||||
GtkWidget * mnemonic_or_null_if_control_is_mnemonic);
|
||||
|
||||
void
|
||||
hig_workarea_finish (GtkWidget * table,
|
||||
int * row);
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
||||
enum
|
||||
{
|
||||
GUI_PAD_SMALL = 3,
|
||||
GUI_PAD = 6,
|
||||
GUI_PAD_BIG = 12,
|
||||
GUI_PAD_LARGE = 12
|
||||
};
|
||||
|
||||
#endif /* __HIG_H__ */
|
||||
+3
-1
@@ -40,6 +40,7 @@
|
||||
#include "dialogs.h"
|
||||
#include "ipc.h"
|
||||
#include "msgwin.h"
|
||||
#include "torrent-inspector.h"
|
||||
#include "tr_cell_renderer_progress.h"
|
||||
#include "tr_core.h"
|
||||
#include "tr_icon.h"
|
||||
@@ -682,6 +683,7 @@ gotdrag(GtkWidget *widget SHUTUP, GdkDragContext *dc, gint x SHUTUP,
|
||||
action = toraddaction( tr_prefs_get( PREF_ID_ADDSTD ) );
|
||||
tr_core_add_list( data->core, paths, action, FALSE );
|
||||
tr_core_torrents_added( data->core );
|
||||
g_list_free(paths);
|
||||
}
|
||||
freestrlist(freeables);
|
||||
g_free(files);
|
||||
@@ -1012,7 +1014,7 @@ handleaction( struct cbdata * data, int act )
|
||||
changed = TRUE;
|
||||
break;
|
||||
case ACT_INFO:
|
||||
makeinfowind( data->wind, model, path, tor );
|
||||
gtk_widget_show (torrent_inspector_new (data->wind, tor));
|
||||
break;
|
||||
case ACT_OPEN:
|
||||
case ACT_PREF:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
/******************************************************************************
|
||||
* $Id:$
|
||||
*
|
||||
* Copyright (c) 2005-2007 Transmission authors and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef GTK_TORRENT_INSPECTOR_H
|
||||
#define GTK_TORRENT_INSPECTOR_H
|
||||
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include "tr_torrent.h"
|
||||
|
||||
GtkWidget* torrent_inspector_new ( GtkWindow * parent, TrTorrent * tor );
|
||||
|
||||
#endif /* TG_PREFS_H */
|
||||
@@ -739,6 +739,7 @@ tr_core_update( TrCore * self )
|
||||
gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
|
||||
st = tr_torrent_stat( tor );
|
||||
g_object_unref( tor );
|
||||
tr_torrent_check_seeding_cap ( tor );
|
||||
|
||||
/* XXX find out if setting the same data emits changed signal */
|
||||
gtk_list_store_set( GTK_LIST_STORE( self->model ), &iter,
|
||||
|
||||
+170
-18
@@ -147,6 +147,10 @@ tr_torrent_init(GTypeInstance *instance, gpointer g_class SHUTUP) {
|
||||
self->delfile = NULL;
|
||||
self->severed = FALSE;
|
||||
self->disposed = FALSE;
|
||||
self->ul_cap_enabled = FALSE;
|
||||
self->ul_cap = 0;
|
||||
self->dl_cap_enabled = FALSE;
|
||||
self->dl_cap = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -225,8 +229,8 @@ tr_torrent_dispose(GObject *obj) {
|
||||
tr_torrent_sever( self );
|
||||
}
|
||||
|
||||
if(NULL != self->delfile)
|
||||
g_free(self->delfile);
|
||||
g_free (self->delfile);
|
||||
g_free (self->dir);
|
||||
|
||||
/* Chain up to the parent class */
|
||||
parent->dispose(obj);
|
||||
@@ -317,16 +321,19 @@ tr_torrent_stop( TrTorrent * self )
|
||||
}
|
||||
|
||||
static TrTorrent *
|
||||
maketorrent( tr_torrent_t * handle, const char * dir, gboolean paused )
|
||||
maketorrent( tr_torrent_t * handle,
|
||||
const char * dir,
|
||||
gboolean paused )
|
||||
{
|
||||
TrTorrent * tor;
|
||||
|
||||
tr_torrentDisablePex( handle,
|
||||
!tr_prefs_get_bool_with_default( PREF_ID_PEX ) );
|
||||
|
||||
tor = g_object_new( TR_TORRENT_TYPE, "torrent-handle", handle,
|
||||
"download-directory", dir, NULL);
|
||||
|
||||
tor = g_object_new( TR_TORRENT_TYPE,
|
||||
"torrent-handle", handle,
|
||||
"download-directory", dir,
|
||||
NULL);
|
||||
g_object_set( tor, "paused", paused, NULL );
|
||||
|
||||
return tor;
|
||||
@@ -411,11 +418,18 @@ TrTorrent *
|
||||
tr_torrent_new_with_state( tr_handle_t * back, benc_val_t * state,
|
||||
gboolean forcedpause, char ** err )
|
||||
{
|
||||
TrTorrent * ret;
|
||||
tr_torrent_t * handle;
|
||||
int ii, errcode;
|
||||
benc_val_t *name, *data;
|
||||
char *torrent, *hash, *dir;
|
||||
gboolean paused;
|
||||
gboolean paused = FALSE;
|
||||
gboolean ul_cap_enabled = FALSE;
|
||||
gboolean dl_cap_enabled = FALSE;
|
||||
gboolean seeding_cap_enabled = FALSE;
|
||||
gint ul_cap = 0;
|
||||
gint dl_cap = 0;
|
||||
gdouble seeding_cap = 0.0;
|
||||
|
||||
*err = NULL;
|
||||
|
||||
@@ -430,15 +444,18 @@ tr_torrent_new_with_state( tr_handle_t * back, benc_val_t * state,
|
||||
data = state->val.l.vals + ii + 1;
|
||||
if(TYPE_STR == name->type &&
|
||||
(TYPE_STR == data->type || TYPE_INT == data->type)) {
|
||||
if(0 == strcmp("torrent", name->val.s.s))
|
||||
torrent = data->val.s.s;
|
||||
if(0 == strcmp("hash", name->val.s.s))
|
||||
hash = data->val.s.s;
|
||||
else if(0 == strcmp("dir", name->val.s.s))
|
||||
dir = data->val.s.s;
|
||||
else if(0 == strcmp("paused", name->val.s.s)) {
|
||||
paused = (data->val.i ? TRUE : FALSE);
|
||||
}
|
||||
char * key = name->val.s.s;
|
||||
char * val = data->val.s.s;
|
||||
if (!strcmp (key, "torrent")) torrent = val;
|
||||
else if (!strcmp (key, "hash")) hash = val;
|
||||
else if (!strcmp (key, "dir")) dir = val;
|
||||
else if (!strcmp (key, "paused")) paused = !!data->val.i;
|
||||
else if (!strcmp (key, "ul-cap-speed")) ul_cap = data->val.i;
|
||||
else if (!strcmp (key, "ul-cap-enabled")) ul_cap_enabled = !!data->val.i;
|
||||
else if (!strcmp (key, "dl-cap-speed")) dl_cap = data->val.i;
|
||||
else if (!strcmp (key, "dl-cap-enabled")) dl_cap_enabled = !!data->val.i;
|
||||
else if (!strcmp (key, "seeding-cap-ratio")) seeding_cap = (data->val.i / 100.0);
|
||||
else if (!strcmp (key, "seeding-cap-enabled")) seeding_cap_enabled = !!data->val.i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,7 +484,14 @@ tr_torrent_new_with_state( tr_handle_t * back, benc_val_t * state,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maketorrent( handle, dir, paused || forcedpause );
|
||||
ret = maketorrent( handle, dir, paused || forcedpause );
|
||||
ret->ul_cap = ul_cap;
|
||||
ret->ul_cap_enabled = ul_cap_enabled;
|
||||
ret->dl_cap = dl_cap;
|
||||
ret->dl_cap_enabled = dl_cap_enabled;
|
||||
ret->seeding_cap = seeding_cap;
|
||||
ret->seeding_cap_enabled = seeding_cap_enabled;
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -503,7 +527,22 @@ tr_torrent_get_state( TrTorrent * tor, benc_val_t * state )
|
||||
tr_bencInitStr( tr_bencDictAdd( state, "dir" ),
|
||||
tr_torrentGetFolder( tor->handle ), -1, 1 );
|
||||
tr_bencInitInt( tr_bencDictAdd( state, "paused" ),
|
||||
( tr_torrent_paused( tor ) ? 1 : 0 ) );
|
||||
tr_torrent_paused( tor ) ? 1 : 0 );
|
||||
|
||||
tr_bencInitInt( tr_bencDictAdd( state, "ul-cap-speed" ),
|
||||
tor->ul_cap );
|
||||
tr_bencInitInt( tr_bencDictAdd( state, "ul-cap-enabled" ),
|
||||
tor->ul_cap_enabled ? 1 : 0 );
|
||||
|
||||
tr_bencInitInt( tr_bencDictAdd( state, "dl-cap-speed" ),
|
||||
tor->dl_cap );
|
||||
tr_bencInitInt( tr_bencDictAdd( state, "dl-cap-enabled" ),
|
||||
tor->dl_cap_enabled ? 1 : 0);
|
||||
|
||||
tr_bencInitInt( tr_bencDictAdd( state, "seeding-cap-ratio" ),
|
||||
(int)(tor->dl_cap * 100.0)); /* two decimal places */
|
||||
tr_bencInitInt( tr_bencDictAdd( state, "seeding-cap-enabled" ),
|
||||
tor->seeding_cap_enabled ? 1 : 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -543,3 +582,116 @@ tr_torrent_paused(TrTorrent *tor) {
|
||||
|
||||
return (TR_STATUS_INACTIVE & st->status ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
extern void tr_setUseCustomUpload( tr_torrent_t * tor, int limit );
|
||||
extern void tr_setUseCustomDownload( tr_torrent_t * tor, int limit );
|
||||
|
||||
|
||||
static void refresh_upload_cap ( TrTorrent *gtor ) {
|
||||
const int cap = gtor->ul_cap_enabled ? gtor->ul_cap : -1;
|
||||
g_message ("setting upload cap to %d...", cap);
|
||||
tr_setUseCustomUpload( gtor->handle, gtor->ul_cap_enabled );
|
||||
tr_setUploadLimit( gtor->handle, cap );
|
||||
}
|
||||
void
|
||||
tr_torrent_set_upload_cap_speed ( TrTorrent *gtor, int KiB_sec ) {
|
||||
gtor->ul_cap = KiB_sec;
|
||||
refresh_upload_cap ( gtor );
|
||||
}
|
||||
void
|
||||
tr_torrent_set_upload_cap_enabled ( TrTorrent *gtor, gboolean b ) {
|
||||
gtor->ul_cap_enabled = b;
|
||||
refresh_upload_cap ( gtor );
|
||||
}
|
||||
|
||||
static void refresh_download_cap ( TrTorrent *gtor ) {
|
||||
const int cap = gtor->dl_cap_enabled ? gtor->dl_cap : -1;
|
||||
tr_setUseCustomDownload( gtor->handle, gtor->dl_cap_enabled );
|
||||
tr_setDownloadLimit( gtor->handle, cap );
|
||||
}
|
||||
void
|
||||
tr_torrent_set_download_cap_speed ( TrTorrent *gtor, int KiB_sec ) {
|
||||
gtor->dl_cap = KiB_sec;
|
||||
refresh_download_cap( gtor );
|
||||
}
|
||||
void
|
||||
tr_torrent_set_download_cap_enabled ( TrTorrent *gtor, gboolean b ) {
|
||||
gtor->dl_cap_enabled = b;
|
||||
refresh_download_cap( gtor );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrent_check_seeding_cap ( TrTorrent *gtor) {
|
||||
tr_stat_t * st = tr_torrent_stat( gtor );
|
||||
if ((gtor->seeding_cap_enabled) && (st->ratio >= gtor->seeding_cap))
|
||||
tr_torrent_stop (gtor);
|
||||
}
|
||||
void
|
||||
tr_torrent_set_seeding_cap_ratio ( TrTorrent *gtor, gdouble ratio ) {
|
||||
gtor->seeding_cap = ratio;
|
||||
tr_torrent_check_seeding_cap (gtor);
|
||||
}
|
||||
void
|
||||
tr_torrent_set_seeding_cap_enabled ( TrTorrent *gtor, gboolean b ) {
|
||||
if ((gtor->seeding_cap_enabled = b))
|
||||
tr_torrent_check_seeding_cap (gtor);
|
||||
}
|
||||
|
||||
char *
|
||||
tr_torrent_status_str ( TrTorrent * gtor )
|
||||
{
|
||||
char * top = 0;
|
||||
|
||||
tr_stat_t * st = tr_torrent_stat( gtor );
|
||||
|
||||
const int tpeers = MAX (st->peersTotal, 0);
|
||||
const int upeers = MAX (st->peersUploading, 0);
|
||||
const int eta = st->eta;
|
||||
const double prog = st->progress * 100.0; /* [0...100] */
|
||||
const int status = st->status;
|
||||
|
||||
if( TR_STATUS_CHECK_WAIT & status )
|
||||
{
|
||||
top = g_strdup_printf( _("Waiting to check existing files (%.1f%%)"), prog );
|
||||
}
|
||||
else if( TR_STATUS_CHECK & status )
|
||||
{
|
||||
top = g_strdup_printf( _("Checking existing files (%.1f%%)"), prog );
|
||||
}
|
||||
else if( TR_STATUS_DOWNLOAD & status )
|
||||
{
|
||||
if( 0 > eta )
|
||||
{
|
||||
top = g_strdup_printf( _("Stalled (%.1f%%)"), prog );
|
||||
}
|
||||
else
|
||||
{
|
||||
char * timestr = readabletime(eta);
|
||||
top = g_strdup_printf( _("Finishing in %s (%.1f%%)"),
|
||||
timestr, prog );
|
||||
g_free(timestr);
|
||||
}
|
||||
}
|
||||
else if(TR_STATUS_SEED & status)
|
||||
{
|
||||
top = g_strdup_printf(
|
||||
ngettext( "Seeding, uploading to %d of %d peer",
|
||||
"Seeding, uploading to %d of %d peers", tpeers ),
|
||||
upeers, tpeers );
|
||||
}
|
||||
else if( TR_STATUS_STOPPING & status )
|
||||
{
|
||||
top = g_strdup( _("Stopping...") );
|
||||
}
|
||||
else if( TR_STATUS_PAUSE & status )
|
||||
{
|
||||
top = g_strdup_printf( _("Stopped (%.1f%%)"), prog );
|
||||
}
|
||||
else
|
||||
{
|
||||
top = g_strdup( "" );
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
@@ -58,8 +58,16 @@ struct _TrTorrent {
|
||||
tr_torrent_t *handle;
|
||||
char *dir;
|
||||
char *delfile;
|
||||
|
||||
/* FIXME: hm, are these heavyweight enough to deserve their own properties? */
|
||||
gboolean severed;
|
||||
gboolean disposed;
|
||||
gboolean ul_cap_enabled;
|
||||
gboolean dl_cap_enabled;
|
||||
gboolean seeding_cap_enabled;
|
||||
gint ul_cap; /* KiB/sec */
|
||||
gint dl_cap; /* KiB/sec */
|
||||
gdouble seeding_cap; /* ratio to stop seeding at */
|
||||
};
|
||||
|
||||
struct _TrTorrentClass {
|
||||
@@ -84,6 +92,26 @@ tr_torrent_start( TrTorrent * tor );
|
||||
void
|
||||
tr_torrent_stop( TrTorrent * tor );
|
||||
|
||||
char*
|
||||
tr_torrent_status_str ( TrTorrent * tor );
|
||||
|
||||
void
|
||||
tr_torrent_set_upload_cap_speed ( TrTorrent*, int KiB_sec );
|
||||
void
|
||||
tr_torrent_set_upload_cap_enabled ( TrTorrent*, gboolean );
|
||||
|
||||
void
|
||||
tr_torrent_set_download_cap_speed ( TrTorrent*, int KiB_sec );
|
||||
void
|
||||
tr_torrent_set_download_cap_enabled ( TrTorrent*, gboolean );
|
||||
|
||||
void
|
||||
tr_torrent_check_seeding_cap ( TrTorrent* );
|
||||
void
|
||||
tr_torrent_set_seeding_cap_ratio ( TrTorrent*, gdouble ratio );
|
||||
void
|
||||
tr_torrent_set_seeding_cap_enabled ( TrTorrent*, gboolean );
|
||||
|
||||
#ifdef TR_WANT_TORRENT_PRIVATE
|
||||
|
||||
TrTorrent *
|
||||
|
||||
+14
-54
@@ -351,9 +351,9 @@ tr_window_update( TrWindow * self, float downspeed, float upspeed )
|
||||
}
|
||||
|
||||
/* update the status bar */
|
||||
downstr = readablesize( downspeed * 1024.0 );
|
||||
upstr = readablesize( upspeed * 1024.0 );
|
||||
str = g_strdup_printf( _(" Total DL: %s/s Total UL: %s/s"),
|
||||
downstr = readablespeed ( downspeed );
|
||||
upstr = readablespeed ( upspeed );
|
||||
str = g_strdup_printf( _(" Total DL: %s Total UL: %s"),
|
||||
downstr, upstr );
|
||||
g_free( downstr );
|
||||
g_free( upstr );
|
||||
@@ -491,67 +491,26 @@ static void
|
||||
formatname( GtkTreeViewColumn * col SHUTUP, GtkCellRenderer * rend,
|
||||
GtkTreeModel * model, GtkTreeIter * iter, gpointer data SHUTUP )
|
||||
{
|
||||
char * name, * mb, * terr, * str, * top, * bottom, * timestr;
|
||||
TrTorrent * gtor;
|
||||
char * name, * mb, * str, * top, * bottom;
|
||||
guint64 size;
|
||||
gfloat prog;
|
||||
int status, err, eta, tpeers, upeers, dpeers;
|
||||
|
||||
gtk_tree_model_get( model, iter, MC_NAME, &name, MC_STAT, &status,
|
||||
MC_ERR, &err, MC_SIZE, &size, MC_PROG, &prog,
|
||||
MC_ERR, &err, MC_SIZE, &size,
|
||||
MC_ETA, &eta, MC_PEERS, &tpeers, MC_UPEERS, &upeers,
|
||||
MC_DPEERS, &dpeers, -1 );
|
||||
MC_DPEERS, &dpeers, MC_TORRENT, >or, -1 );
|
||||
|
||||
tpeers = MAX( tpeers, 0 );
|
||||
upeers = MAX( upeers, 0 );
|
||||
dpeers = MAX( dpeers, 0 );
|
||||
mb = readablesize(size);
|
||||
prog *= 100;
|
||||
|
||||
if( TR_STATUS_CHECK_WAIT & status )
|
||||
{
|
||||
top = g_strdup_printf( _("Waiting to check existing files (%.1f%%)"), prog );
|
||||
}
|
||||
else if( TR_STATUS_CHECK & status )
|
||||
{
|
||||
top = g_strdup_printf( _("Checking existing files (%.1f%%)"), prog );
|
||||
}
|
||||
else if( TR_STATUS_DOWNLOAD & status )
|
||||
{
|
||||
if( 0 > eta )
|
||||
{
|
||||
top = g_strdup_printf( _("Stalled (%.1f%%)"), prog );
|
||||
}
|
||||
else
|
||||
{
|
||||
timestr = readabletime(eta);
|
||||
top = g_strdup_printf( _("Finishing in %s (%.1f%%)"),
|
||||
timestr, prog );
|
||||
g_free(timestr);
|
||||
}
|
||||
}
|
||||
else if(TR_STATUS_SEED & status)
|
||||
{
|
||||
top = g_strdup_printf(
|
||||
ngettext( "Seeding, uploading to %d of %d peer",
|
||||
"Seeding, uploading to %d of %d peers", tpeers ),
|
||||
dpeers, tpeers );
|
||||
}
|
||||
else if( TR_STATUS_STOPPING & status )
|
||||
{
|
||||
top = g_strdup( _("Stopping...") );
|
||||
}
|
||||
else if( TR_STATUS_PAUSE & status )
|
||||
{
|
||||
top = g_strdup_printf( _("Stopped (%.1f%%)"), prog );
|
||||
}
|
||||
else
|
||||
{
|
||||
top = g_strdup( "" );
|
||||
g_assert_not_reached();
|
||||
}
|
||||
top = tr_torrent_status_str ( gtor );
|
||||
|
||||
if( TR_OK != err )
|
||||
{
|
||||
char * terr;
|
||||
gtk_tree_model_get( model, iter, MC_TERR, &terr, -1 );
|
||||
bottom = g_strconcat( _("Error: "), terr, NULL );
|
||||
g_free( terr );
|
||||
@@ -576,6 +535,7 @@ formatname( GtkTreeViewColumn * col SHUTUP, GtkCellRenderer * rend,
|
||||
g_free( str );
|
||||
g_free( top );
|
||||
g_free( bottom );
|
||||
g_object_unref( gtor );
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -591,16 +551,16 @@ formatprog( GtkTreeViewColumn * col SHUTUP, GtkCellRenderer * rend,
|
||||
prog = MAX( prog, 0.0 );
|
||||
prog = MIN( prog, 1.0 );
|
||||
|
||||
ulstr = readablesize( ul * 1024.0 );
|
||||
ulstr = readablespeed (ul);
|
||||
if( 1.0 == prog )
|
||||
{
|
||||
dlstr = ratiostr( down, up );
|
||||
str = g_strdup_printf( _("Ratio: %s\nUL: %s/s"), dlstr, ulstr );
|
||||
str = g_strdup_printf( _("Ratio: %s\nUL: %s"), dlstr, ulstr );
|
||||
}
|
||||
else
|
||||
{
|
||||
dlstr = readablesize( dl * 1024.0 );
|
||||
str = g_strdup_printf( _("DL: %s/s\nUL: %s/s"), dlstr, ulstr );
|
||||
dlstr = readablespeed( dl );
|
||||
str = g_strdup_printf( _("DL: %s\nUL: %s"), dlstr, ulstr );
|
||||
}
|
||||
marked = g_markup_printf_escaped( "<small>%s</small>", str );
|
||||
g_object_set( rend, "markup", str, "progress", prog, NULL );
|
||||
|
||||
+39
-42
@@ -81,6 +81,17 @@ readablesize(guint64 size) {
|
||||
gettext(sizestrs[ii]));
|
||||
}
|
||||
|
||||
char *
|
||||
readablespeed (double KiBps)
|
||||
{
|
||||
const guint64 bps = KiBps * 1024;
|
||||
char * str = readablesize (bps);
|
||||
char * ret = g_strdup_printf ("%s/s", str);
|
||||
g_free (str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define SECONDS(s) ((s) % 60)
|
||||
#define MINUTES(s) ((s) / 60 % 60)
|
||||
#define HOURS(s) ((s) / 60 / 60 % 24)
|
||||
@@ -110,6 +121,16 @@ readabletime(int secs) {
|
||||
DAYS(secs), ngettext("hour", "hours", DAYS(secs)));
|
||||
}
|
||||
|
||||
char *
|
||||
rfc822date (guint64 epoch_msec)
|
||||
{
|
||||
const time_t secs = epoch_msec / 1000;
|
||||
const struct tm tm = *localtime (&secs);
|
||||
char buf[128];
|
||||
strftime (buf, sizeof(buf), "%a, %d %b %Y %T %Z", &tm);
|
||||
return g_strdup (buf);
|
||||
}
|
||||
|
||||
char *
|
||||
ratiostr(guint64 down, guint64 up) {
|
||||
double ratio;
|
||||
@@ -167,37 +188,23 @@ dupstrlist( GList * list )
|
||||
}
|
||||
|
||||
char *
|
||||
joinstrlist(GList *list, char *sep) {
|
||||
GList *ii;
|
||||
int len;
|
||||
char *ret, *dest;
|
||||
|
||||
if(0 > (len = strlen(sep) * (g_list_length(list) - 1)))
|
||||
return NULL;
|
||||
|
||||
for(ii = g_list_first(list); NULL != ii; ii = ii->next)
|
||||
len += strlen(ii->data);
|
||||
|
||||
dest = ret = g_new(char, len + 1);
|
||||
|
||||
for(ii = g_list_first(list); NULL != ii; ii = ii->next) {
|
||||
dest = g_stpcpy(dest, ii->data);
|
||||
if(NULL != ii->next)
|
||||
dest = g_stpcpy(dest, sep);
|
||||
joinstrlist(GList *list, char *sep)
|
||||
{
|
||||
GList *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 ret;
|
||||
return g_string_free (gstr, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
freestrlist(GList *list) {
|
||||
GList *ii;
|
||||
|
||||
if(NULL != list) {
|
||||
for(ii = g_list_first(list); NULL != ii; ii = ii->next)
|
||||
g_free(ii->data);
|
||||
g_list_free(list);
|
||||
}
|
||||
freestrlist(GList *list)
|
||||
{
|
||||
g_list_foreach (list, (GFunc)g_free, NULL);
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -303,22 +310,12 @@ const char *
|
||||
getdownloaddir( void )
|
||||
{
|
||||
static char * wd = NULL;
|
||||
const char * dir;
|
||||
|
||||
dir = tr_prefs_get( PREF_ID_DIR );
|
||||
if( NULL == dir )
|
||||
{
|
||||
if( NULL == wd )
|
||||
{
|
||||
wd = g_new( char, MAX_PATH_LENGTH + 1 );
|
||||
if( NULL == getcwd( wd, MAX_PATH_LENGTH + 1 ) )
|
||||
{
|
||||
snprintf( wd, MAX_PATH_LENGTH + 1, "." );
|
||||
}
|
||||
}
|
||||
dir = wd;
|
||||
const char * dir = tr_prefs_get( PREF_ID_DIR );
|
||||
if (NULL == dir) {
|
||||
if (NULL == wd)
|
||||
wd = g_get_current_dir(),
|
||||
dir = wd;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -31,15 +31,17 @@
|
||||
/* macro to shut up "unused parameter" warnings */
|
||||
#ifdef __GNUC__
|
||||
#define SHUTUP __attribute__((unused))
|
||||
#define UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define SHUTUP
|
||||
#define UNUSED
|
||||
#endif
|
||||
|
||||
/* XXX this shouldn't be here */
|
||||
enum tr_torrent_action { TR_TOR_LEAVE, TR_TOR_COPY, TR_TOR_MOVE };
|
||||
|
||||
/* return number of items in array */
|
||||
#define ALEN( a ) ( ( signed )( sizeof(a) / sizeof( (a)[0] ) ) )
|
||||
#define ALEN(a) ((signed)G_N_ELEMENTS(a))
|
||||
|
||||
/* used for a callback function with a data parameter */
|
||||
typedef void (*callbackfunc_t)(void*);
|
||||
@@ -72,11 +74,20 @@ strbool(const char *str);
|
||||
char *
|
||||
readablesize(guint64 size);
|
||||
|
||||
/* return a human-readable string for the transfer rate given in bytes.
|
||||
the string must be g_free()d */
|
||||
char *
|
||||
readablespeed (double KiBps);
|
||||
|
||||
|
||||
/* return a human-readable string for the time given in seconds.
|
||||
the string must be g_free()d */
|
||||
char *
|
||||
readabletime(int secs);
|
||||
|
||||
char *
|
||||
rfc822date (guint64 epoch_msec);
|
||||
|
||||
/* returns a string representing the download ratio.
|
||||
the string must be g_free()d */
|
||||
char *
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define TR_BENCODE_H 1
|
||||
|
||||
#include <stdint.h> /* for int64_t */
|
||||
#include <string.h> /* for memset */
|
||||
|
||||
typedef struct benc_val_s
|
||||
{
|
||||
|
||||
@@ -323,5 +323,6 @@ parseUTPex( tr_torrent_t * tor, tr_peer_t * peer, uint8_t * buf, int len )
|
||||
peer_dbg( "GET extended-pex, no peers" );
|
||||
}
|
||||
|
||||
tr_bencFree( &val );
|
||||
return TR_OK;
|
||||
}
|
||||
|
||||
@@ -238,6 +238,8 @@ void tr_threadJoin( tr_thread_t * t )
|
||||
#endif
|
||||
tr_dbg( "Thread '%s' joined", t->name );
|
||||
free( t->name );
|
||||
t->name = NULL;
|
||||
t->func = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ void tr_condWait( tr_cond_t *, tr_lock_t * );
|
||||
void tr_condSignal( tr_cond_t * );
|
||||
void tr_condClose( tr_cond_t * );
|
||||
|
||||
struct in_addr; /* forward declaration to calm gcc down */
|
||||
int
|
||||
tr_getDefaultRoute( struct in_addr * addr );
|
||||
|
||||
|
||||
+11
-13
@@ -189,6 +189,7 @@ static tr_torrent_t * torrentRealInit( tr_handle_t * h, tr_torrent_t * tor,
|
||||
tor->blockSize;
|
||||
tor->completion = tr_cpInit( tor );
|
||||
|
||||
tor->thread = THREAD_EMPTY;
|
||||
tr_lockInit( &tor->lock );
|
||||
tr_condInit( &tor->cond );
|
||||
|
||||
@@ -239,7 +240,7 @@ void tr_torrentSetFolder( tr_torrent_t * tor, const char * path )
|
||||
}
|
||||
}
|
||||
|
||||
char * tr_torrentGetFolder( tr_torrent_t * tor )
|
||||
const char * tr_torrentGetFolder( tr_torrent_t * tor )
|
||||
{
|
||||
return tor->destination;
|
||||
}
|
||||
@@ -263,11 +264,8 @@ int tr_torrentDuplicateDownload( tr_torrent_t * tor )
|
||||
|
||||
void tr_torrentStart( tr_torrent_t * tor )
|
||||
{
|
||||
if( tor->status & ( TR_STATUS_STOPPING | TR_STATUS_STOPPED ) )
|
||||
{
|
||||
/* Join the thread first */
|
||||
torrentReallyStop( tor );
|
||||
}
|
||||
/* Join the thread first */
|
||||
torrentReallyStop( tor );
|
||||
|
||||
/* Don't start if a torrent with the same name and destination is already active */
|
||||
if( tr_torrentDuplicateDownload( tor ) )
|
||||
@@ -335,8 +333,11 @@ static void torrentReallyStop( tr_torrent_t * tor )
|
||||
tor->die = 1;
|
||||
tr_threadJoin( &tor->thread );
|
||||
|
||||
tr_trackerClose( tor->tracker );
|
||||
tor->tracker = NULL;
|
||||
if( tor->tracker )
|
||||
{
|
||||
tr_trackerClose( tor->tracker );
|
||||
tor->tracker = NULL;
|
||||
}
|
||||
|
||||
tr_lockLock( &tor->lock );
|
||||
for( i = 0; i < tor->peerCount; i++ )
|
||||
@@ -679,11 +680,8 @@ void tr_torrentClose( tr_torrent_t * tor )
|
||||
tr_handle_t * h = tor->handle;
|
||||
tr_info_t * inf = &tor->info;
|
||||
|
||||
if( tor->status & ( TR_STATUS_STOPPING | TR_STATUS_STOPPED ) )
|
||||
{
|
||||
/* Join the thread first */
|
||||
torrentReallyStop( tor );
|
||||
}
|
||||
/* Join the thread first */
|
||||
torrentReallyStop( tor );
|
||||
|
||||
tr_sharedLock( h->shared );
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ void tr_close( tr_handle_t * h )
|
||||
|
||||
tr_sharedClose( h->shared );
|
||||
tr_fdClose();
|
||||
free( h->tag );
|
||||
free( h );
|
||||
|
||||
tr_netResolveThreadClose();
|
||||
|
||||
@@ -270,7 +270,7 @@ tr_info_t * tr_torrentInfo( tr_torrent_t * );
|
||||
int tr_torrentScrape( tr_torrent_t *, int * s, int * l, int * d );
|
||||
|
||||
void tr_torrentSetFolder( tr_torrent_t *, const char * );
|
||||
char * tr_torrentGetFolder( tr_torrent_t * );
|
||||
const char * tr_torrentGetFolder( tr_torrent_t * );
|
||||
|
||||
int tr_torrentDuplicateDownload( tr_torrent_t * tor );
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
include ../mk/config.mk
|
||||
include ../mk/common.mk
|
||||
|
||||
SRCS = conf.c dialogs.c io.c ipc.c main.c msgwin.c \
|
||||
SRCS = conf.c dialogs.c hig.c io.c ipc.c main.c msgwin.c \
|
||||
torrent-inspector.c \
|
||||
tr_cell_renderer_progress.c tr_core.c tr_icon.c tr_prefs.c \
|
||||
tr_torrent.c tr_window.c util.c
|
||||
OBJS = $(SRCS:%.c=%.o)
|
||||
|
||||
Reference in New Issue
Block a user