diff --git a/gtk/actions.c b/gtk/actions.c index d352d239e..cd2ab98db 100644 --- a/gtk/actions.c +++ b/gtk/actions.c @@ -87,7 +87,7 @@ toggle_pref_cb( GtkToggleAction * action, static GtkToggleActionEntry pref_toggle_entries[] = { - { "alt-speed-enabled", NULL, N_( "Speed _Limit Mode" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE }, + { "alt-speed-enabled", NULL, N_( "Temporary Speed _Limits" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE }, { "minimal-view", NULL, N_( "_Minimal View" ), "M", NULL, G_CALLBACK( toggle_pref_cb ), FALSE }, { "sort-reversed", NULL, N_( "_Reverse Sort Order" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE }, { "show-filterbar", NULL, N_( "_Filterbar" ), NULL, NULL, G_CALLBACK( toggle_pref_cb ), FALSE }, diff --git a/gtk/details.c b/gtk/details.c index cf574adf7..2407ab3b4 100644 --- a/gtk/details.c +++ b/gtk/details.c @@ -62,25 +62,20 @@ struct DetailsImpl guint seedCustomSpinTag; guint maxPeersSpinTag; + GtkWidget * size_lb; GtkWidget * state_lb; - GtkWidget * progress_lb; GtkWidget * have_lb; GtkWidget * dl_lb; GtkWidget * ul_lb; - GtkWidget * failed_lb; GtkWidget * ratio_lb; GtkWidget * error_lb; - GtkWidget * swarm_lb; - GtkWidget * date_added_lb; + GtkWidget * date_started_lb; GtkWidget * last_activity_lb; - GtkWidget * pieces_lb; GtkWidget * hash_lb; GtkWidget * privacy_lb; - GtkWidget * creator_lb; - GtkWidget * date_created_lb; + GtkWidget * origin_lb; GtkWidget * destination_lb; - GtkWidget * torrentfile_lb; GtkTextBuffer * comment_buffer; GHashTable * peer_hash; @@ -106,7 +101,6 @@ struct DetailsImpl GSList * ids; TrCore * core; guint periodic_refresh_tag; - guint prefs_changed_tag; }; static tr_torrent** @@ -448,33 +442,6 @@ max_peers_spun_cb( GtkSpinButton * s, struct DetailsImpl * di ) torrent_set_int( di, "peer-limit", gtk_spin_button_get_value( s ) ); } -static char* -get_global_ratio_radiobutton_string( void ) -{ - char * s; - const gboolean b = pref_flag_get( TR_PREFS_KEY_RATIO_ENABLED ); - const double d = pref_double_get( TR_PREFS_KEY_RATIO ); - - if( b ) - s = g_strdup_printf( _( "Use _Global setting (currently: stop seeding when a torrent's ratio reaches %.2f)" ), d ); - else - s = g_strdup( _( "Use _Global setting (currently: seed regardless of ratio)" ) ); - - return s; -} - -static void -prefsChanged( TrCore * core UNUSED, const char * key, gpointer rb ) -{ - if( !strcmp( key, TR_PREFS_KEY_RATIO_ENABLED ) || - !strcmp( key, TR_PREFS_KEY_RATIO ) ) - { - char * s = get_global_ratio_radiobutton_string( ); - gtk_button_set_label( GTK_BUTTON( rb ), s ); - g_free( s ); - } -} - static void onPriorityChanged( GtkComboBox * w, struct DetailsImpl * di ) { @@ -569,20 +536,17 @@ options_page_new( struct DetailsImpl * d ) d->upLimitSpin = w; w = new_priority_combo( d ); - hig_workarea_add_row( t, &row, _( "_Bandwidth priority:" ), w, NULL ); + hig_workarea_add_row( t, &row, _( "Torrent _priority:" ), w, NULL ); d->bandwidthCombo = w; hig_workarea_add_section_divider( t, &row ); hig_workarea_add_section_title( t, &row, _( "Seed-Until Ratio" ) ); group = NULL; - s = get_global_ratio_radiobutton_string( ); + s = _( "Use _global setting" ); w = gtk_radio_button_new_with_mnemonic( group, s ); - tag = g_signal_connect( d->core, "prefs-changed", G_CALLBACK( prefsChanged ), w ); - d->prefs_changed_tag = tag; group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( w ) ); hig_workarea_add_wide_control( t, &row, w ); - g_free( s ); g_object_set_data( G_OBJECT( w ), RATIO_KEY, GINT_TO_POINTER( TR_RATIOLIMIT_GLOBAL ) ); tag = g_signal_connect( w, "toggled", G_CALLBACK( ratio_mode_changed_cb ), d ); d->seedGlobalRadio = w; @@ -597,7 +561,8 @@ options_page_new( struct DetailsImpl * d ) d->seedForeverRadioTag = tag; h = gtk_hbox_new( FALSE, GUI_PAD ); - w = gtk_radio_button_new_with_mnemonic( group, _( "_Stop seeding when a torrent's ratio reaches" ) ); + s = _( "_Seed torrent until its ratio reaches:" ); + w = gtk_radio_button_new_with_mnemonic( group, s ); d->seedCustomRadio = w; g_object_set_data( G_OBJECT( w ), RATIO_KEY, GINT_TO_POINTER( TR_RATIOLIMIT_SINGLE ) ); tag = g_signal_connect( w, "toggled", G_CALLBACK( ratio_mode_changed_cb ), d ); @@ -627,7 +592,7 @@ options_page_new( struct DetailsImpl * d ) /**** ***** -***** ACTIVITY TAB +***** INFO TAB ***** ****/ @@ -646,7 +611,7 @@ static const char * activityString( int activity ) } static void -refreshActivity( struct DetailsImpl * di, tr_torrent ** torrents, int n ) +refreshInfo( struct DetailsImpl * di, tr_torrent ** torrents, int n ) { int i; const char * str; @@ -654,287 +619,11 @@ refreshActivity( struct DetailsImpl * di, tr_torrent ** torrents, int n ) const char * mixed = _( "Mixed" ); char buf[512]; const tr_stat ** stats = g_new( const tr_stat*, n ); - for( i=0; iactivity; - for( i=1; iactivity ) - break; - if( i==n ) - str = activityString( baseline ); - else - str = mixed; - } - gtk_label_set_text( GTK_LABEL( di->state_lb ), str ); - - - /* progress_lb */ - if( n <= 0 ) - str = none; - else { - double sizeWhenDone = 0; - double leftUntilDone = 0; - for( i=0; isizeWhenDone; - leftUntilDone += stats[i]->leftUntilDone; - } - g_snprintf( buf, sizeof( buf ), _( "%.1f%%" ), 100.0*((sizeWhenDone-leftUntilDone)/sizeWhenDone) ); - str = buf; - } - gtk_label_set_text( GTK_LABEL( di->progress_lb ), str ); - - - /* have_lb */ - if( n <= 0 ) - str = none; - else { - char buf1[128]; - char buf2[128]; - double haveUnchecked = 0; - double haveValid = 0; - double verifiedPieces = 0; - for( i=0; ihaveValid; - haveUnchecked += stats[i]->haveUnchecked; - haveValid += v; - verifiedPieces += v / tr_torrentInfo(torrents[i])->pieceSize; - } - tr_strlsize( buf1, haveValid + haveUnchecked, sizeof( buf1 ) ); - tr_strlsize( buf2, haveValid, sizeof( buf2 ) ); - i = (int) ceil( verifiedPieces ); - g_snprintf( buf, sizeof( buf ), ngettext( "%1$s (%2$s verified in %3$d piece)", - "%1$s (%2$s verified in %3$d pieces)", - verifiedPieces ), - buf1, buf2, i ); - str = buf; - } - gtk_label_set_text( GTK_LABEL( di->have_lb ), str ); - - - /* dl_lb */ - if( n <= 0 ) - str = none; - else { - uint64_t sum = 0; - for( i=0; idownloadedEver; - str = tr_strlsize( buf, sum, sizeof( buf ) ); - } - gtk_label_set_text( GTK_LABEL( di->dl_lb ), str ); - - - /* ul_lb */ - if( n <= 0 ) - str = none; - else { - uint64_t sum = 0; - for( i=0; iuploadedEver; - str = tr_strlsize( buf, sum, sizeof( buf ) ); - } - gtk_label_set_text( GTK_LABEL( di->ul_lb ), str ); - - - /* corrupt ever */ - if( n <= 0 ) - str = none; - else { - uint64_t sum = 0; - for( i=0; icorruptEver; - str = tr_strlsize( buf, sum, sizeof( buf ) ); - } - gtk_label_set_text( GTK_LABEL( di->failed_lb ), str ); - - - /* ratio */ - if( n <= 0 ) - str = none; - else { - uint64_t up = 0; - uint64_t down = 0; - for( i=0; iuploadedEver; - down += stats[i]->downloadedEver; - } - str = tr_strlratio( buf, tr_getRatio( up, down ), sizeof( buf ) ); - } - gtk_label_set_text( GTK_LABEL( di->ratio_lb ), str ); - - - /* swarmspeed */ - if( n <= 0 ) - str = none; - else { - double swarmSpeed = 0; - for( i=0; iswarmSpeed; - str = tr_strlspeed( buf, swarmSpeed, sizeof( buf ) ); - } - gtk_label_set_text( GTK_LABEL( di->swarm_lb ), str ); - - - /* error */ - if( n <= 0 ) - str = none; - else { - const char * baseline = stats[0]->errorString; - for( i=1; ierrorString ) ) - break; - if( i==n ) - str = baseline; - else - str = mixed; - } - if( !str || !*str ) - str = none; - gtk_label_set_text( GTK_LABEL( di->error_lb ), str ); - - - /* date added */ - if( n <= 0 ) - str = none; - else { - const time_t baseline = stats[0]->addedDate; - for( i=1; iaddedDate ) - break; - if( i==n ) - str = gtr_localtime2( buf, baseline, sizeof( buf ) ); - else - str = mixed; - } - gtk_label_set_text( GTK_LABEL( di->date_added_lb ), str ); - - - /* activity date */ - if( n <= 0 ) - str = none; - else { - const time_t baseline = stats[0]->activityDate; - for( i=1; iactivityDate ) - break; - if( i==n ) - str = gtr_localtime2( buf, baseline, sizeof( buf ) ); - else - str = mixed; - } - gtk_label_set_text( GTK_LABEL( di->last_activity_lb ), str ); - - g_free( stats ); -} - -static GtkWidget* -activity_page_new( struct DetailsImpl * di ) -{ - int row = 0; - GtkWidget * l; - GtkWidget * t = hig_workarea_create( ); - - hig_workarea_add_section_title( t, &row, _( "Transfer" ) ); - - l = di->state_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "State:" ), l, NULL ); - - l = di->progress_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Progress:" ), l, NULL ); - - l = di->have_lb = gtk_label_new( NULL ); - /* "Have" refers to how much of the torrent we have */ - hig_workarea_add_row( t, &row, _( "Have:" ), l, NULL ); - - l = di->dl_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Downloaded:" ), l, NULL ); - - l = di->ul_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Uploaded:" ), l, NULL ); - - /* how much downloaded data was corrupt */ - l = di->failed_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Failed DL:" ), l, NULL ); - - l = di->ratio_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Ratio:" ), l, NULL ); - - l = di->swarm_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Swarm speed:" ), l, NULL ); - - l = di->error_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Error:" ), l, NULL ); - - hig_workarea_add_section_divider( t, &row ); - hig_workarea_add_section_title( t, &row, _( "Dates" ) ); - - l = di->date_added_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Started at:" ), l, NULL ); - - l = di->last_activity_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Last activity at:" ), l, NULL ); - - hig_workarea_add_section_divider( t, &row ); - hig_workarea_finish( t, &row ); - return t; -} - -/**** -***** -***** INFO TAB -***** -****/ - -static void -refreshInfo( struct DetailsImpl * di, tr_torrent ** torrents, int n ) -{ - int i; - char buf[128]; - const char * str; - const char * none = _( "None" ); - const char * mixed = _( "Mixed" ); - const char * unknown = _( "Unknown" ); const tr_info ** infos = g_new( const tr_info*, n ); - - /* info */ - for( i=0; ipieceSize; - for( i=0; ipieceCount; - g_snprintf( buf, sizeof( buf ), - ngettext( "%'d Piece", "%'d Pieces", sum ), sum ); - for( i=1; ipieceSize ) - break; - if( i==n ) { - char tmp1[64]; - char tmp2[64]; - g_strlcpy( tmp1, buf, sizeof( tmp1 ) ); - tr_strlsize( tmp2, baseline, sizeof( tmp2 ) ); - g_snprintf( buf, sizeof( buf ), _( "%1$s @ %2$s" ), tmp1, tmp2 ); - } - str = buf; } - gtk_label_set_text( GTK_LABEL( di->pieces_lb ), str ); - - - /* hash_lb */ - if( n<=0 ) - str = none; - else if ( n==1 ) - str = infos[0]->hashString; - else - str = mixed; - gtk_label_set_text( GTK_LABEL( di->hash_lb ), str ); - /* privacy_lb */ if( n<=0 ) @@ -954,6 +643,33 @@ refreshInfo( struct DetailsImpl * di, tr_torrent ** torrents, int n ) gtk_label_set_text( GTK_LABEL( di->privacy_lb ), str ); + /* origin_lb */ + if( n<=0 ) + str = none; + else { + char datestr[64]; + const char * creator = infos[0]->creator ? infos[0]->creator : ""; + const time_t date = infos[0]->dateCreated; + gboolean mixed_creator = FALSE; + gboolean mixed_date = FALSE; + gtr_localtime2( datestr, date, sizeof( datestr ) ); + for( i=1; icreator ? infos[i]->creator : "" ); + mixed_date |= ( date != infos[i]->dateCreated ); + } + if( mixed_date && mixed_creator ) + str = mixed; + else if( mixed_date ) + g_snprintf( buf, sizeof( buf ), _( "Created by %1$s" ), creator ); + else if( mixed_creator || !*creator ) + g_snprintf( buf, sizeof( buf ), _( "Created on %1$s" ), datestr ); + else + g_snprintf( buf, sizeof( buf ), _( "Created by %1$s on %2$s" ), creator, datestr ); + str = buf; + } + gtk_label_set_text( GTK_LABEL( di->origin_lb ), str ); + + /* comment_buffer */ if( n<=0 ) str = ""; @@ -969,41 +685,6 @@ refreshInfo( struct DetailsImpl * di, tr_torrent ** torrents, int n ) } gtk_text_buffer_set_text( di->comment_buffer, str, -1 ); - - /* creator_lb */ - if( n<=0 ) - str = none; - else { - const char * baseline = infos[0]->creator ? infos[0]->creator : ""; - for( i=1; icreator ? infos[i]->creator : "" ) ) - break; - if( i==n ) - str = baseline; - else - str = mixed; - } - if( !str || !*str ) - str = unknown; - gtk_label_set_text( GTK_LABEL( di->creator_lb ), str ); - - - /* date_created_lb */ - if( n<=0 ) - str = none; - else { - const time_t baseline = infos[0]->dateCreated; - for( i=1; idateCreated ) - break; - if( i==n ) - str = gtr_localtime2( buf, baseline, sizeof( buf ) ); - else - str = mixed; - } - gtk_label_set_text( GTK_LABEL( di->date_created_lb ), str ); - - /* destination_lb */ if( n<=0 ) str = none; @@ -1019,16 +700,211 @@ refreshInfo( struct DetailsImpl * di, tr_torrent ** torrents, int n ) } gtk_label_set_text( GTK_LABEL( di->destination_lb ), str ); + /* state_lb */ + if( n <= 0 ) + str = none; + else { + const int baseline = stats[0]->activity; + for( i=1; iactivity ) + break; + if( i==n ) + str = activityString( baseline ); + else + str = mixed; + } + gtk_label_set_text( GTK_LABEL( di->state_lb ), str ); - /* torrentfile_lb */ + + /* date started */ + if( n <= 0 ) + str = none; + else { + const time_t baseline = stats[0]->startDate; + for( i=1; istartDate ) + break; + if( i!=n ) + str = mixed; + else if( ( baseline<=0 ) || ( stats[0]->activity == TR_STATUS_STOPPED ) ) + str = activityString( TR_STATUS_STOPPED ); + else + str = tr_strltime( buf, time(NULL)-baseline, sizeof( buf ) ); + } + gtk_label_set_text( GTK_LABEL( di->date_started_lb ), str ); + + + /* size_lb */ + { + char sizebuf[128]; + uint64_t size = 0; + int pieces = 0; + int32_t pieceSize = 0; + for( i=0; itotalSize; + pieces += infos[i]->pieceCount; + if( !pieceSize ) + pieceSize = infos[i]->pieceSize; + else if( pieceSize != (int)infos[i]->pieceSize ) + pieceSize = -1; + } + tr_strlsize( sizebuf, size, sizeof( sizebuf ) ); + if( !size ) + str = none; + else if( pieceSize >= 0 ) { + char piecebuf[128]; + tr_strlsize( piecebuf, (uint64_t)pieceSize, sizeof( piecebuf ) ); + g_snprintf( buf, sizeof( buf ), + ngettext( "%1$s (%2$'d piece @ %3$s)", + "%1$s (%2$'d pieces @ %3$s)", pieces ), + sizebuf, pieces, piecebuf ); + str = buf; + } else { + g_snprintf( buf, sizeof( buf ), + ngettext( "%1$s (%2$'d piece)", + "%1$s (%2$'d pieces)", pieces ), + sizebuf, pieces ); + str = buf; + } + gtk_label_set_text( GTK_LABEL( di->size_lb ), str ); + } + + + /* have_lb */ + if( n <= 0 ) + str = none; + else { + double sizeWhenDone = 0; + double leftUntilDone = 0; + double haveUnchecked = 0; + double haveValid = 0; + double verifiedPieces = 0; + for( i=0; ihaveValid; + haveUnchecked += stats[i]->haveUnchecked; + haveValid += v; + verifiedPieces += v / tr_torrentInfo(torrents[i])->pieceSize; + sizeWhenDone += stats[i]->sizeWhenDone; + leftUntilDone += stats[i]->leftUntilDone; + } + if( !haveValid && !haveUnchecked ) + str = none; + else { + char pct[16], ver[64]; + double n = 100.0 * ( sizeWhenDone - leftUntilDone ); + g_snprintf( pct, sizeof( pct ), _( "%.1f%%" ), n/sizeWhenDone ); + tr_strlsize( ver, haveValid, sizeof( ver ) ); + if( !haveUnchecked ) + g_snprintf( buf, sizeof(buf), _( "%1$s (%2$s verified)" ), pct, ver ); + else { + char u[64]; + tr_strlsize( u, haveUnchecked, sizeof( u ) ); + g_snprintf( buf, sizeof(buf), _( "%1$s (%2$s verified, %3$s unverified)" ), pct, ver, u ); + } + str = buf; + } + } + gtk_label_set_text( GTK_LABEL( di->have_lb ), str ); + + + /* dl_lb */ + if( n <= 0 ) + str = none; + else { + char dbuf[64], fbuf[64]; + uint64_t d=0, f=0; + for( i=0; idownloadedEver; + f += stats[i]->corruptEver; + } + tr_strlsize( dbuf, d, sizeof( dbuf ) ); + tr_strlsize( fbuf, f, sizeof( fbuf ) ); + if( f ) + g_snprintf( buf, sizeof( buf ), _( "%1$s (+%2$s corrupt)" ), dbuf, fbuf ); + else + tr_strlcpy( buf, dbuf, sizeof( buf ) ); + str = buf; + } + gtk_label_set_text( GTK_LABEL( di->dl_lb ), str ); + + + /* ul_lb */ + if( n <= 0 ) + str = none; + else { + uint64_t sum = 0; + for( i=0; iuploadedEver; + str = tr_strlsize( buf, sum, sizeof( buf ) ); + } + gtk_label_set_text( GTK_LABEL( di->ul_lb ), str ); + + + /* ratio */ + if( n <= 0 ) + str = none; + else { + uint64_t up = 0; + uint64_t down = 0; + for( i=0; iuploadedEver; + down += stats[i]->downloadedEver; + } + str = tr_strlratio( buf, tr_getRatio( up, down ), sizeof( buf ) ); + } + gtk_label_set_text( GTK_LABEL( di->ratio_lb ), str ); + + /* hash_lb */ if( n<=0 ) str = none; - else if( n==1 ) - str = infos[0]->torrent; + else if ( n==1 ) + str = infos[0]->hashString; else str = mixed; - gtk_label_set_text( GTK_LABEL( di->torrentfile_lb ), str ); + gtk_label_set_text( GTK_LABEL( di->hash_lb ), str ); + /* error */ + if( n <= 0 ) + str = none; + else { + const char * baseline = stats[0]->errorString; + for( i=1; ierrorString ) ) + break; + if( i==n ) + str = baseline; + else + str = mixed; + } + if( !str || !*str ) + str = none; + gtk_label_set_text( GTK_LABEL( di->error_lb ), str ); + + + /* activity date */ + if( n <= 0 ) + str = none; + else { + time_t latest = 0; + for( i=0; iactivityDate ) + latest = stats[i]->activityDate; + if( latest <= 0 ) + str = none; + else { + const int period = time( NULL ) - latest; + if( period < 5 ) + tr_strlcpy( buf, _( "Active now" ), sizeof( buf ) ); + else { + char tbuf[128]; + tr_strltime( tbuf, period, sizeof( tbuf ) ); + g_snprintf( buf, sizeof( buf ), _( "%1$s ago" ), tbuf ); + } + str = buf; + } + } + gtk_label_set_text( GTK_LABEL( di->last_activity_lb ), str ); + + g_free( stats ); g_free( infos ); } @@ -1040,11 +916,54 @@ info_page_new( struct DetailsImpl * di ) GtkWidget *l, *w, *fr, *sw; GtkWidget *t = hig_workarea_create( ); + hig_workarea_add_section_title( t, &row, _( "Activity" ) ); + + /* size */ + l = di->size_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Torrent size:" ), l, NULL ); + + /* have */ + l = di->have_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Have:" ), l, NULL ); + + /* downloaded */ + l = di->dl_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Downloaded:" ), l, NULL ); + + /* uploaded */ + l = di->ul_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Uploaded:" ), l, NULL ); + + /* ratio */ + l = di->ratio_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Ratio:" ), l, NULL ); + + /* state */ + l = di->state_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "State:" ), l, NULL ); + + /* running for */ + l = di->date_started_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Running time:" ), l, NULL ); + + /* last activity */ + l = di->last_activity_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Last activity:" ), l, NULL ); + + /* error */ + l = di->error_lb = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Error:" ), l, NULL ); + + + hig_workarea_add_section_divider( t, &row ); hig_workarea_add_section_title( t, &row, _( "Details" ) ); - /* pieces */ - l = di->pieces_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Pieces:" ), l, NULL ); + /* destination */ + l = g_object_new( GTK_TYPE_LABEL, "selectable", TRUE, + "ellipsize", PANGO_ELLIPSIZE_END, + NULL ); + hig_workarea_add_row( t, &row, _( "Location:" ), l, NULL ); + di->destination_lb = l; /* hash */ l = g_object_new( GTK_TYPE_LABEL, "selectable", TRUE, @@ -1058,10 +977,15 @@ info_page_new( struct DetailsImpl * di ) hig_workarea_add_row( t, &row, _( "Privacy:" ), l, NULL ); di->privacy_lb = l; + /* origins */ + l = gtk_label_new( NULL ); + hig_workarea_add_row( t, &row, _( "Origin:" ), l, NULL ); + di->origin_lb = l; + /* comment */ b = di->comment_buffer = gtk_text_buffer_new( NULL ); w = gtk_text_view_new_with_buffer( b ); - gtk_widget_set_size_request( w, 0u, 100u ); + gtk_widget_set_size_request( w, 350u, 50u ); gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW( w ), GTK_WRAP_WORD ); gtk_text_view_set_editable( GTK_TEXT_VIEW( w ), FALSE ); sw = gtk_scrolled_window_new( NULL, NULL ); @@ -1076,29 +1000,8 @@ info_page_new( struct DetailsImpl * di ) gtk_misc_set_alignment( GTK_MISC( w ), 0.0f, 0.0f ); hig_workarea_add_section_divider( t, &row ); - hig_workarea_add_section_title( t, &row, _( "Origins" ) ); - - l = di->creator_lb = gtk_label_new( NULL ); - gtk_label_set_ellipsize( GTK_LABEL( l ), PANGO_ELLIPSIZE_END ); - hig_workarea_add_row( t, &row, _( "Creator:" ), l, NULL ); - - l = di->date_created_lb = gtk_label_new( NULL ); - hig_workarea_add_row( t, &row, _( "Date:" ), l, NULL ); - - hig_workarea_add_section_divider( t, &row ); - hig_workarea_add_section_title( t, &row, _( "Location" ) ); - - l = g_object_new( GTK_TYPE_LABEL, "selectable", TRUE, - "ellipsize", PANGO_ELLIPSIZE_END, - NULL ); - hig_workarea_add_row( t, &row, _( "Destination:" ), l, NULL ); - di->destination_lb = l; - - l = g_object_new( GTK_TYPE_LABEL, "selectable", TRUE, - "ellipsize", PANGO_ELLIPSIZE_END, - NULL ); - hig_workarea_add_row( t, &row, _( "Torrent file:" ), l, NULL ); - di->torrentfile_lb = l; + hig_workarea_finish( t, &row ); + return t; hig_workarea_finish( t, &row ); return t; @@ -1961,7 +1864,6 @@ refresh( struct DetailsImpl * di ) refreshPeers( di, torrents, n ); refreshTracker( di, torrents, n ); refreshOptions( di, torrents, n ); - refreshActivity( di, torrents, n ); g_free( torrents ); } @@ -1977,7 +1879,6 @@ static void details_free( gpointer gdata ) { struct DetailsImpl * data = gdata; - g_signal_handler_disconnect( data->core, data->prefs_changed_tag ); g_source_remove( data->periodic_refresh_tag ); g_hash_table_destroy( data->webseed_hash ); g_slist_free( data->ids ); @@ -2012,8 +1913,8 @@ torrent_inspector_new( GtkWindow * parent, TrCore * core ) n = gtk_notebook_new( ); gtk_container_set_border_width( GTK_CONTAINER( n ), GUI_PAD ); - w = activity_page_new( di ); - l = gtk_label_new( _( "Activity" ) ); + w = info_page_new( di ); + l = gtk_label_new( _( "Information" ) ); gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, l ); w = peer_page_new( di ); @@ -2024,10 +1925,6 @@ torrent_inspector_new( GtkWindow * parent, TrCore * core ) l = gtk_label_new( _( "Tracker" ) ); gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, l ); - w = info_page_new( di ); - l = gtk_label_new( _( "Information" ) ); - gtk_notebook_append_page( GTK_NOTEBOOK( n ), w, l ); - w = file_list_new( core, 0 ); gtk_container_set_border_width( GTK_CONTAINER( w ), GUI_PAD_BIG ); l = gtk_label_new( _( "Files" ) ); diff --git a/gtk/file-list.c b/gtk/file-list.c index fe9eac12e..8b5e4912b 100644 --- a/gtk/file-list.c +++ b/gtk/file-list.c @@ -730,20 +730,20 @@ file_list_new( TrCore * core, int torrentId ) title = _( "Progress" ); pango_layout = gtk_widget_create_pango_layout( view, title ); pango_layout_get_pixel_size( pango_layout, &width, NULL ); - width += GUI_PAD * 2; + width += 30; /* room for the sort indicator */ g_object_unref( G_OBJECT( pango_layout ) ); rend = gtk_cell_renderer_progress_new( ); col = gtk_tree_view_column_new_with_attributes( title, rend, "value", FC_PROG, NULL ); gtk_tree_view_column_set_fixed_width( col, width ); gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_FIXED ); gtk_tree_view_column_set_sort_column_id( col, FC_PROG ); - gtk_tree_view_append_column ( tree_view, col ); + gtk_tree_view_append_column( tree_view, col ); /* add "enabled" column */ title = _( "Download" ); pango_layout = gtk_widget_create_pango_layout( view, title ); pango_layout_get_pixel_size( pango_layout, &width, NULL ); - width += GUI_PAD * 2; + width += 30; /* room for the sort indicator */ g_object_unref( G_OBJECT( pango_layout ) ); rend = gtk_cell_renderer_toggle_new( ); col = gtk_tree_view_column_new_with_attributes( title, rend, NULL ); @@ -751,13 +751,13 @@ file_list_new( TrCore * core, int torrentId ) gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_FIXED ); gtk_tree_view_column_set_cell_data_func( col, rend, renderDownload, NULL, NULL ); gtk_tree_view_column_set_sort_column_id( col, FC_ENABLED ); - gtk_tree_view_append_column ( tree_view, col ); + gtk_tree_view_append_column( tree_view, col ); /* add priority column */ title = _( "Priority" ); pango_layout = gtk_widget_create_pango_layout( view, title ); pango_layout_get_pixel_size( pango_layout, &width, NULL ); - width += GUI_PAD * 2; + width += 30; /* room for the sort indicator */ g_object_unref( G_OBJECT( pango_layout ) ); rend = gtk_cell_renderer_text_new( ); g_object_set( rend, "xalign", (gfloat)0.5, "yalign", (gfloat)0.5, NULL ); @@ -766,7 +766,7 @@ file_list_new( TrCore * core, int torrentId ) gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_FIXED ); gtk_tree_view_column_set_sort_column_id( col, FC_PRIORITY ); gtk_tree_view_column_set_cell_data_func( col, rend, renderPriority, NULL, NULL ); - gtk_tree_view_append_column ( tree_view, col ); + gtk_tree_view_append_column( tree_view, col ); /* create the scrolled window and stick the view in it */ scroll = gtk_scrolled_window_new( NULL, NULL ); diff --git a/gtk/tr-prefs.c b/gtk/tr-prefs.c index bd9428aaa..4df3a54fb 100644 --- a/gtk/tr-prefs.c +++ b/gtk/tr-prefs.c @@ -308,7 +308,7 @@ torrentPage( GObject * core ) hig_workarea_add_section_divider( t, &row ); hig_workarea_add_section_title( t, &row, _( "Limits" ) ); - s = _( "_Stop seeding torrents at ratio:" ); + s = _( "_Seed torrent until its ratio reaches:" ); w = new_check_button( s, TR_PREFS_KEY_RATIO_ENABLED, core ); w2 = new_spin_button_double( TR_PREFS_KEY_RATIO, core, 0, INT_MAX, .05 ); gtk_widget_set_sensitive( GTK_WIDGET( w2 ), pref_flag_get( TR_PREFS_KEY_RATIO_ENABLED ) ); @@ -332,17 +332,17 @@ desktopPage( GObject * core ) GtkWidget * w; t = hig_workarea_create( ); - hig_workarea_add_section_title( t, &row, _( "Options" ) ); + hig_workarea_add_section_title( t, &row, _( "Desktop" ) ); - s = _( "Inhibit desktop _hibernation when torrents are active" ); + s = _( "Inhibit _hibernation when torrents are active" ); w = new_check_button( s, PREF_KEY_INHIBIT_HIBERNATION, core ); hig_workarea_add_wide_control( t, &row, w ); - s = _( "Show _icon in the desktop Notification Area" ); + s = _( "Show Transmission in the system _tray" ); w = new_check_button( s, PREF_KEY_SHOW_TRAY_ICON, core ); hig_workarea_add_wide_control( t, &row, w ); - s = _( "Show desktop _notifications" ); + s = _( "Show popup _notifications" ); w = new_check_button( s, PREF_KEY_SHOW_DESKTOP_NOTIFICATION, core ); hig_workarea_add_wide_control( t, &row, w ); @@ -455,9 +455,9 @@ new_encryption_combo( GObject * core, const char * key ) int value; const char * text; } items[] = { - { TR_CLEAR_PREFERRED, N_( "Plaintext Preferred" ) }, - { TR_ENCRYPTION_PREFERRED, N_( "Encryption Preferred" ) }, - { TR_ENCRYPTION_REQUIRED, N_( "Encryption Required" ) } + { TR_CLEAR_PREFERRED, N_( "Plaintext preferred" ) }, + { TR_ENCRYPTION_PREFERRED, N_( "Encryption preferred" ) }, + { TR_ENCRYPTION_REQUIRED, N_( "Encryption required" ) } }; /* build a store for encryption */ @@ -523,14 +523,6 @@ peerPage( GObject * core ) g_signal_connect( data->check, "toggled", G_CALLBACK( target_cb ), w ); target_cb( data->check, w ); - hig_workarea_add_section_divider( t, &row ); - hig_workarea_add_section_title( t, &row, _( "Limits" ) ); - - w = new_spin_button( TR_PREFS_KEY_PEER_LIMIT_GLOBAL, core, 1, 3000, 5 ); - hig_workarea_add_row( t, &row, _( "Maximum peers _overall:" ), w, NULL ); - w = new_spin_button( TR_PREFS_KEY_PEER_LIMIT_TORRENT, core, 1, 300, 5 ); - hig_workarea_add_row( t, &row, _( "Maximum peers per _torrent:" ), w, NULL ); - hig_workarea_add_section_divider( t, &row ); hig_workarea_add_section_title ( t, &row, _( "Privacy" ) ); @@ -552,6 +544,14 @@ peerPage( GObject * core ) hig_workarea_add_wide_control( t, &row, w ); #endif + hig_workarea_add_section_divider( t, &row ); + hig_workarea_add_section_title( t, &row, _( "Limits" ) ); + + w = new_spin_button( TR_PREFS_KEY_PEER_LIMIT_TORRENT, core, 1, 300, 5 ); + hig_workarea_add_row( t, &row, _( "Maximum peers per _torrent:" ), w, NULL ); + w = new_spin_button( TR_PREFS_KEY_PEER_LIMIT_GLOBAL, core, 1, 3000, 5 ); + hig_workarea_add_row( t, &row, _( "Maximum peers _overall:" ), w, NULL ); + hig_workarea_finish( t, &row ); g_object_weak_ref( G_OBJECT( t ), peerPageDestroyed, data ); return t; @@ -780,7 +780,7 @@ webPage( GObject * core ) page->widgets = g_slist_append( page->widgets, w ); /* require authentication */ - s = _( "_Require username" ); + s = _( "Use _authentication" ); w = new_check_button( s, TR_PREFS_KEY_RPC_AUTH_REQUIRED, core ); hig_workarea_add_wide_control( t, &row, w ); page->auth_tb = GTK_TOGGLE_BUTTON( w ); @@ -803,7 +803,7 @@ webPage( GObject * core ) page->auth_widgets = g_slist_append( page->auth_widgets, w ); /* require authentication */ - s = _( "Only allow the following IP _addresses to connect:" ); + s = _( "Only allow these IP _addresses to connect:" ); w = new_check_button( s, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, core ); hig_workarea_add_wide_control( t, &row, w ); page->whitelist_tb = GTK_TOGGLE_BUTTON( w ); @@ -966,7 +966,7 @@ trackerPage( GObject * core ) page->core = TR_CORE( core ); t = hig_workarea_create( ); - hig_workarea_add_section_title ( t, &row, _( "Tracker Proxy" ) ); + hig_workarea_add_section_title ( t, &row, _( "Tracker" ) ); s = _( "Connect to tracker via a pro_xy" ); w = new_check_button( s, TR_PREFS_KEY_PROXY_ENABLED, core ); @@ -997,7 +997,7 @@ trackerPage( GObject * core ) w = hig_workarea_add_row( t, &row, s, w, NULL ); page->proxy_widgets = g_slist_append( page->proxy_widgets, w ); - s = _( "_Authentication is required" ); + s = _( "Use _authentication" ); w = new_check_button( s, TR_PREFS_KEY_PROXY_AUTH_ENABLED, core ); g_signal_connect( w, "toggled", G_CALLBACK( onProxyToggled ), page ); hig_workarea_add_wide_control( t, &row, w ); @@ -1182,7 +1182,7 @@ bandwidthPage( GObject * core ) page->core = TR_CORE( core ); t = hig_workarea_create( ); - hig_workarea_add_section_title( t, &row, _( "Global Bandwidth Limits" ) ); + hig_workarea_add_section_title( t, &row, _( "Speed Limits" ) ); s = _( "Limit _download speed (KB/s):" ); w = new_check_button( s, TR_PREFS_KEY_DSPEED_ENABLED, core ); @@ -1202,13 +1202,20 @@ bandwidthPage( GObject * core ) h = gtk_hbox_new( FALSE, GUI_PAD ); w = gtk_image_new_from_stock( "alt-speed-off", -1 ); gtk_box_pack_start( GTK_BOX( h ), w, FALSE, FALSE, 0 ); - g_snprintf( buf, sizeof( buf ), "%s", _( "Speed Limit Mode" ) ); + g_snprintf( buf, sizeof( buf ), "%s", _( "Temporary Speed Limits" ) ); w = gtk_label_new( buf ); gtk_misc_set_alignment( GTK_MISC( w ), 0.0f, 0.5f ); gtk_label_set_use_markup( GTK_LABEL( w ), TRUE ); gtk_box_pack_start( GTK_BOX( h ), w, FALSE, FALSE, 0 ); hig_workarea_add_section_title_widget( t, &row, h ); + s = _( "Override normal speed limits manually or at scheduled times" ); + g_snprintf( buf, sizeof( buf ), "%s", s ); + w = gtk_label_new( buf ); + gtk_label_set_use_markup( GTK_LABEL( w ), TRUE ); + gtk_misc_set_alignment( GTK_MISC( w ), 0.5f, 0.5f ); + hig_workarea_add_wide_control( t, &row, w ); + s = _( "Limit do_wnload speed (KB/s):" ); w = new_spin_button( TR_PREFS_KEY_ALT_SPEED_DOWN, core, 0, INT_MAX, 5 ); hig_workarea_add_row( t, &row, s, w, NULL ); @@ -1217,13 +1224,7 @@ bandwidthPage( GObject * core ) w = new_spin_button( TR_PREFS_KEY_ALT_SPEED_UP, core, 0, INT_MAX, 5 ); hig_workarea_add_row( t, &row, s, w, NULL ); - g_snprintf( buf, sizeof( buf ), "%s", _( "When enabled, Speed Limit Mode overrides the Global Bandwidth Limits" ) ); - w = gtk_label_new( buf ); - gtk_label_set_use_markup( GTK_LABEL( w ), TRUE ); - gtk_misc_set_alignment( GTK_MISC( w ), 0.5f, 0.5f ); - hig_workarea_add_wide_control( t, &row, w ); - - s = _( "Use Speed Limit Mode _between:" ); + s = _( "_Scheduled use:" ); h = gtk_hbox_new( FALSE, 0 ); w2 = new_time_combo( core, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN ); page->sched_widgets = g_slist_append( page->sched_widgets, w2 ); @@ -1343,14 +1344,14 @@ networkPage( GObject * core ) data->prefsTag = g_signal_connect( TR_CORE( core ), "prefs-changed", G_CALLBACK( onCorePrefsChanged ), data ); g_object_weak_ref( G_OBJECT( t ), networkPageDestroyed, data ); - s = _( "_Randomize the port every launch" ); - w = new_check_button( s, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, core ); - hig_workarea_add_wide_control( t, &row, w ); - s = _( "Use UPnP or NAT-PMP port _forwarding from my router" ); w = new_check_button( s, TR_PREFS_KEY_PORT_FORWARDING, core ); hig_workarea_add_wide_control( t, &row, w ); + s = _( "Pick a _random port every time Transmission is started" ); + w = new_check_button( s, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, core ); + hig_workarea_add_wide_control( t, &row, w ); + hig_workarea_finish( t, &row ); return t; } @@ -1400,7 +1401,7 @@ tr_prefs_dialog_new( GObject * core, gtk_label_new ( _( "Web" ) ) ); gtk_notebook_append_page( GTK_NOTEBOOK( n ), trackerPage( core ), - gtk_label_new ( _( "Trackers" ) ) ); + gtk_label_new ( _( "Proxy" ) ) ); g_signal_connect( d, "response", G_CALLBACK( response_cb ), core ); gtk_box_pack_start( GTK_BOX( GTK_DIALOG( d )->vbox ), n, TRUE, TRUE, 0 ); diff --git a/gtk/tr-window.c b/gtk/tr-window.c index e23396a0b..143470bba 100644 --- a/gtk/tr-window.c +++ b/gtk/tr-window.c @@ -333,8 +333,8 @@ syncAltSpeedButton( PrivateData * p ) gtk_button_set_image( GTK_BUTTON( w ), p->alt_speed_image[b?1:0] ); gtk_button_set_alignment( GTK_BUTTON( w ), 0.5, 0.5 ); - tip = b ? _( "Click to disable Speed Limit Mode" ) - : _( "Click to enable Speed Limit Mode" ); + tip = b ? _( "Click to disable Temporary Speed Limits" ) + : _( "Click to enable Temporary Speed Limits" ); gtr_widget_set_tooltip_text( w, tip ); } diff --git a/qt/details.cc b/qt/details.cc index 924b265ea..262421bd4 100644 --- a/qt/details.cc +++ b/qt/details.cc @@ -130,14 +130,12 @@ Details :: Details( Session& session, TorrentModel& model, QWidget * parent ): QTabWidget * t = new QTabWidget( this ); QWidget * w; - t->addTab( w = createActivityTab( ), tr( "Activity" ) ); + t->addTab( w = createInfoTab( ), tr( "Information" ) ); myWidgets << w; t->addTab( w = createPeersTab( ), tr( "Peers" ) ); myWidgets << w; t->addTab( w = createTrackerTab( ), tr( "Tracker" ) ); myWidgets << w; - t->addTab( w = createInfoTab( ), tr( "Information" ) ); - myWidgets << w; t->addTab( w = createFilesTab( ), tr( "Files" ) ); myWidgets << w; t->addTab( w = createOptionsTab( ), tr( "Options" ) ); @@ -250,69 +248,89 @@ Details :: refresh( ) } myStateLabel->setText( string ); - // myProgressLabel - if( torrents.empty( ) ) - string = tr( "None" ); - else { - double sizeWhenDone = 0; - double leftUntilDone = 0; - foreach( const Torrent * t, torrents ) { - sizeWhenDone += t->sizeWhenDone( ); - leftUntilDone += t->leftUntilDone( ); - } - string = locale.toString( 100.0*((sizeWhenDone-leftUntilDone)/sizeWhenDone), 'f', 2 ); - } - myProgressLabel->setText( string ); - // myHaveLabel + double sizeWhenDone = 0; + double leftUntilDone = 0; int64_t haveTotal = 0; int64_t haveVerified = 0; + int64_t haveUnverified = 0; int64_t verifiedPieces = 0; foreach( const Torrent * t, torrents ) { haveTotal += t->haveTotal( ); + haveUnverified += t->haveUnverified( ); const uint64_t v = t->haveVerified( ); haveVerified += v; verifiedPieces += v / t->pieceSize( ); + sizeWhenDone += t->sizeWhenDone( ); + leftUntilDone += t->leftUntilDone( ); } - myHaveLabel->setText( tr( "%1 (%2 verified in %L3 pieces)" ) - .arg( Utils::sizeToString( haveTotal ) ) - .arg( Utils::sizeToString( haveVerified ) ) - .arg( verifiedPieces ) ); + if( !haveVerified && !haveUnverified ) + string = none; + else { + QString pct = locale.toString( 100.0*((sizeWhenDone-leftUntilDone)/sizeWhenDone), 'f', 2 ); + if( !haveUnverified ) + string = tr( "%1 (%2 verified)" ) + .arg( pct ) + .arg( Utils :: sizeToString( haveVerified ) ); + else + string = tr( "%1 (%2 verified, %3 unverified)" ) + .arg( pct ) + .arg( Utils :: sizeToString( haveVerified ) ) + .arg( Utils :: sizeToString( haveUnverified ) ); + } + myHaveLabel->setText( string ); - int64_t sum = 0; - foreach( const Torrent * t, torrents ) sum += t->downloadedEver( ); - myDownloadedLabel->setText( Utils::sizeToString( sum ) ); + // myDownloadedLabel + if( torrents.empty( ) ) + string = none; + else { + uint64_t d=0, f=0; + foreach( const Torrent * t, torrents ) { + d += t->downloadedEver( ); + f += t->failedEver( ); + } + const QString dstr = Utils::sizeToString( d ); + const QString fstr = Utils::sizeToString( f ); + if( f ) + string = tr( "%1 (+%2s corrupt)" ).arg( dstr ).arg( fstr ); + else + string = dstr; + } + myDownloadedLabel->setText( string ); - sum = 0; + uint64_t sum = 0; foreach( const Torrent * t, torrents ) sum += t->uploadedEver( ); myUploadedLabel->setText( Utils::sizeToString( sum ) ); - sum = 0; - foreach( const Torrent *t, torrents ) sum += t->failedEver( ); - myFailedLabel->setText( Utils::sizeToString( sum ) ); - double d = 0; foreach( const Torrent *t, torrents ) d += t->ratio( ); myRatioLabel->setText( Utils :: ratioToString( d / n ) ); - Speed speed; - foreach( const Torrent *t, torrents ) speed += t->swarmSpeed( ); - mySwarmSpeedLabel->setText( Utils::speedToString( speed ) ); + const QDateTime qdt_now = QDateTime::currentDateTime( ); + // myRunTimeLabel if( torrents.empty( ) ) string = none; else { - string = torrents[0]->dateAdded().toString(); + bool allPaused = true; + QDateTime baseline = torrents[0]->lastStarted( ); foreach( const Torrent * t, torrents ) { - if( string != t->dateAdded().toString() ) { - string = mixed; - break; - } + if( baseline != t->lastStarted( ) ) + baseline = QDateTime( ); + if( !t->isPaused( ) ) + allPaused = false; } + if( allPaused ) + string = tr( "Stopped" ); + else if( baseline.isNull( ) ) + string = mixed; + else + string = Utils::timeToString( baseline.secsTo( qdt_now ) ); } - myAddedDateLabel->setText( string ); + myRunTimeLabel->setText( string ); + // myLastActivityLabel if( torrents.empty( ) ) string = none; else { @@ -322,9 +340,13 @@ Details :: refresh( ) if( latest < dt ) latest = dt; } - string = latest.toString( ); + const int seconds = latest.secsTo( qdt_now ); + if( seconds < 5 ) + string = tr( "Active now" ); + else + string = tr( "%1 ago" ).arg( Utils::timeToString( seconds ) ); } - myActivityLabel->setText( string ); + myLastActivityLabel->setText( string ); if( torrents.empty( ) ) @@ -338,6 +360,8 @@ Details :: refresh( ) } } } + if( string.isEmpty( ) ) + string = none; myErrorLabel->setText( string ); @@ -345,24 +369,30 @@ Details :: refresh( ) /// information tab /// - // myPiecesLabel + // mySizeLabel if( torrents.empty( ) ) string = none; else { - int64_t pieceCount = 0; - uint64_t baseSize = torrents[0]->pieceSize( ); + int pieces = 0; + uint64_t size = 0; + uint32_t pieceSize = torrents[0]->pieceSize( ); foreach( const Torrent * t, torrents ) { - pieceCount += t->pieceCount( ); - if( baseSize != t->pieceSize( ) ) - baseSize = 0; + pieces += t->pieceCount( ); + size += t->totalSize( ); + if( pieceSize != t->pieceSize( ) ) + pieceSize = 0; } - if( !baseSize ) // mixed piece size - string = tr( "%L1 Pieces" ).arg( pieceCount ); + if( !size ) + string = none; + else if( pieceSize > 0 ) + string = tr( "%1 (%Ln pieces @ %2)", "", pieces ) + .arg( Utils::sizeToString( size ) ) + .arg( Utils::sizeToString( pieceSize ) ); else - string = tr( "%L1 Pieces @ %2" ).arg( pieceCount ) - .arg( Utils::sizeToString( baseSize ) ); + string = tr( "%1 (%Ln pieces)", "", pieces ) + .arg( Utils::sizeToString( size ) ); } - myPiecesLabel->setText( string ); + mySizeLabel->setText( string ); // myHashLabel if( torrents.empty( ) ) @@ -383,7 +413,7 @@ Details :: refresh( ) string = none; else { bool b = torrents[0]->isPrivate( ); - string = b ? tr( "Private to this tracker -- PEX disabled" ) + string = b ? tr( "Private to this tracker -- DHT and PEX disabled" ) : tr( "Public torrent" ); foreach( const Torrent * t, torrents ) { if( b != t->isPrivate( ) ) { @@ -408,35 +438,30 @@ Details :: refresh( ) } myCommentBrowser->setText( string ); - // myCreatorLabel + // myOriginLabel if( torrents.empty( ) ) string = none; else { - string = torrents[0]->creator( ); + bool mixed_creator=false, mixed_date=false; + const QString creator = torrents[0]->creator(); + const QString date = torrents[0]->dateCreated().toString(); foreach( const Torrent * t, torrents ) { - if( string != t->creator( ) ) { - string = mixed; - break; - } + mixed_creator |= ( creator != t->creator() ); + mixed_date |= ( date != t->dateCreated().toString() ); } + if( mixed_creator && mixed_date ) + string = mixed; + else if( mixed_date ) + string = tr( "Created by %1" ).arg( creator ); + else if( mixed_creator || creator.isEmpty( ) ) + string = tr( "Created on %1" ).arg( date ); + else + string = tr( "Created by %1 on %2" ).arg( creator ).arg( date ); } - myCreatorLabel->setText( string.isEmpty() ? unknown : string ); - - // myDateCreatedLabel - if( torrents.empty( ) ) - string = none; - else { - string = torrents[0]->dateCreated().toString(); - foreach( const Torrent * t, torrents ) { - if( string != t->dateCreated().toString() ) { - string = mixed; - break; - } - } - } - myDateCreatedLabel->setText( string ); - - // myDestinationLabel + myOriginLabel->setText( string ); + + + // myLocationLabel if( torrents.empty( ) ) string = none; else { @@ -448,21 +473,8 @@ Details :: refresh( ) } } } - myDestinationLabel->setText( string ); + myLocationLabel->setText( string ); - // myTorrentFileLabel - if( torrents.empty( ) ) - string = none; - else { - string = torrents[0]->torrentFile( ); - foreach( const Torrent * t, torrents ) { - if( string != t->torrentFile( ) ) { - string = mixed; - break; - } - } - } - myTorrentFileLabel->setText( string ); /// /// Options Tab @@ -780,25 +792,33 @@ Details :: enableWhenChecked( QCheckBox * box, QWidget * w ) ***/ QWidget * -Details :: createActivityTab( ) +Details :: createInfoTab( ) { HIG * hig = new HIG( this ); hig->addSectionTitle( tr( "Transfer" ) ); - hig->addRow( tr( "State:" ), myStateLabel = new SqueezeLabel ); - hig->addRow( tr( "Progress:" ), myProgressLabel = new SqueezeLabel ); + hig->addRow( tr( "Torrent size:" ), mySizeLabel = new SqueezeLabel ); hig->addRow( tr( "Have:" ), myHaveLabel = new SqueezeLabel ); hig->addRow( tr( "Downloaded:" ), myDownloadedLabel = new SqueezeLabel ); hig->addRow( tr( "Uploaded:" ), myUploadedLabel = new SqueezeLabel ); - hig->addRow( tr( "Failed DL:" ), myFailedLabel = new SqueezeLabel ); hig->addRow( tr( "Ratio:" ), myRatioLabel = new SqueezeLabel ); - hig->addRow( tr( "Swarm Rate:" ), mySwarmSpeedLabel = new SqueezeLabel ); + hig->addRow( tr( "State:" ), myStateLabel = new SqueezeLabel ); + hig->addRow( tr( "Running time:" ), myRunTimeLabel = new SqueezeLabel ); + hig->addRow( tr( "Last activity:" ), myLastActivityLabel = new SqueezeLabel ); hig->addRow( tr( "Error:" ), myErrorLabel = new SqueezeLabel ); hig->addSectionDivider( ); - hig->addSectionTitle( tr( "Dates" ) ); - hig->addRow( tr( "Added on:" ), myAddedDateLabel = new SqueezeLabel ); - hig->addRow( tr( "Last activity on:" ), myActivityLabel = new SqueezeLabel ); + hig->addSectionDivider( ); + hig->addSectionTitle( tr( "Details" ) ); + hig->addRow( tr( "Location:" ), myLocationLabel = new SqueezeLabel ); + hig->addRow( tr( "Hash:" ), myHashLabel = new SqueezeLabel ); + hig->addRow( tr( "Privacy:" ), myPrivacyLabel = new SqueezeLabel ); + hig->addRow( tr( "Origin:" ), myOriginLabel = new SqueezeLabel ); + hig->addRow( tr( "Comment:" ), myCommentBrowser = new QTextBrowser ); + const int h = QFontMetrics(myCommentBrowser->font()).lineSpacing() * 4; + myCommentBrowser->setMinimumHeight( h ); + myCommentBrowser->setMaximumHeight( h ); + hig->finish( ); return hig; @@ -918,7 +938,7 @@ Details :: createOptionsTab( ) m->addItem( tr( "Normal" ), TR_PRI_NORMAL ); m->addItem( tr( "High" ), TR_PRI_HIGH ); connect( m, SIGNAL(currentIndexChanged(int)), this, SLOT(onBandwidthPriorityChanged(int))); - hig->addRow( tr( "&Bandwidth priority:" ), m ); + hig->addRow( tr( "Torrent &priority:" ), m ); myBandwidthPriorityCombo = m; @@ -939,7 +959,7 @@ Details :: createOptionsTab( ) h = new QHBoxLayout( ); h->setSpacing( HIG :: PAD ); - r = new QRadioButton( tr( "&Stop seeding when a torrent's ratio reaches" ) ); + r = new QRadioButton( tr( "&Seed torrent until its ratio reaches:" ) ); r->setProperty( RATIO_KEY, TR_RATIOLIMIT_SINGLE ); connect( r, SIGNAL(clicked(bool)), this, SLOT(onSeedUntilChanged(bool))); mySeedCustomRadio = r; @@ -969,38 +989,6 @@ Details :: createOptionsTab( ) **** ***/ -QWidget * -Details :: createInfoTab( ) -{ - HIG * hig = new HIG( ); - hig->addSectionTitle( tr( "Details" ) ); - hig->addRow( tr( "Pieces:" ), myPiecesLabel = new SqueezeLabel ); - hig->addRow( tr( "Hash:" ), myHashLabel = new SqueezeLabel ); - hig->addRow( tr( "Privacy:" ), myPrivacyLabel = new SqueezeLabel ); - hig->addRow( tr( "Comment:" ), myCommentBrowser = new QTextBrowser ); - hig->addSectionDivider( ); - hig->addSectionTitle( tr( "Origins" ) ); - hig->addRow( tr( "Creator:" ), myCreatorLabel = new SqueezeLabel ); - hig->addRow( tr( "Date:" ), myDateCreatedLabel = new SqueezeLabel ); - hig->addSectionDivider( ); - hig->addSectionTitle( tr( "Origins" ) ); - hig->addRow( tr( "Destination folder:" ), myDestinationLabel = new SqueezeLabel ); - hig->addRow( tr( "Torrent file:" ), myTorrentFileLabel = new SqueezeLabel ); - const int h = QFontMetrics(myCommentBrowser->font()).lineSpacing() * 4; - myTorrentFileLabel->setMinimumWidth( 300 ); - myTorrentFileLabel->setSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Preferred ); - - myCommentBrowser->setMinimumHeight( h ); - myCommentBrowser->setMaximumHeight( h ); - - hig->finish( ); - return hig; -} - -/*** -**** -***/ - QWidget * Details :: createTrackerTab( ) { diff --git a/qt/details.h b/qt/details.h index 1afcc436c..82e1a11bc 100644 --- a/qt/details.h +++ b/qt/details.h @@ -51,7 +51,6 @@ class Details: public QDialog void setIds( const QSet& ids ); private: - QWidget * createActivityTab( ); QWidget * createPeersTab( ); QWidget * createTrackerTab( ); QWidget * createInfoTab( ); @@ -71,16 +70,13 @@ class Details: public QDialog bool myHavePendingRefresh; QLabel * myStateLabel; - QLabel * myProgressLabel; QLabel * myHaveLabel; QLabel * myDownloadedLabel; QLabel * myUploadedLabel; - QLabel * myFailedLabel; QLabel * myRatioLabel; - QLabel * mySwarmSpeedLabel; QLabel * myErrorLabel; - QLabel * myAddedDateLabel; - QLabel * myActivityLabel; + QLabel * myRunTimeLabel; + QLabel * myLastActivityLabel; QCheckBox * mySessionLimitCheck; QCheckBox * mySingleDownCheck; @@ -94,13 +90,11 @@ class Details: public QDialog QSpinBox * myPeerLimitSpin; QComboBox * myBandwidthPriorityCombo; - QLabel * myPiecesLabel; + QLabel * mySizeLabel; QLabel * myHashLabel; QLabel * myPrivacyLabel; - QLabel * myCreatorLabel; - QLabel * myDateCreatedLabel; - QLabel * myDestinationLabel; - QLabel * myTorrentFileLabel; + QLabel * myOriginLabel; + QLabel * myLocationLabel; QTextBrowser * myCommentBrowser; QLabel * myTrackerLabel; diff --git a/qt/mainwin.cc b/qt/mainwin.cc index e69bd622f..ea91e7af9 100644 --- a/qt/mainwin.cc +++ b/qt/mainwin.cc @@ -1006,8 +1006,8 @@ TrMainWindow :: refreshPref( int key ) b = myPrefs.getBool( key ); myAltSpeedButton->setChecked( b ); myAltSpeedButton->setIcon( b ? mySpeedModeOnIcon : mySpeedModeOffIcon ); - myAltSpeedButton->setToolTip( b ? tr( "Click to disable Speed Limit Mode" ) - : tr( "Click to enable Speed Limit Mode" ) ); + myAltSpeedButton->setToolTip( b ? tr( "Click to disable Temporary Speed Limits" ) + : tr( "Click to enable Temporary Speed Limits" ) ); break; default: diff --git a/qt/prefs-dialog.cc b/qt/prefs-dialog.cc index b4e08a0f7..a9b27b2e0 100644 --- a/qt/prefs-dialog.cc +++ b/qt/prefs-dialog.cc @@ -201,7 +201,7 @@ PrefsDialog :: createTrackerTab( ) myProxyWidgets << l << r; l = hig->addRow( tr( "Proxy &port:" ), r = spinBoxNew( Prefs::PROXY_PORT, 1, 65535, 1 ) ); myProxyWidgets << l << r; - hig->addWideControl( l = checkBoxNew( tr( "Require &authentication" ), Prefs::PROXY_AUTH_ENABLED ) ); + hig->addWideControl( l = checkBoxNew( tr( "Use &authentication" ), Prefs::PROXY_AUTH_ENABLED ) ); myProxyWidgets << l; l = hig->addRow( tr( "&Username:" ), r = lineEditNew( Prefs::PROXY_USERNAME ) ); myProxyAuthWidgets << l << r; @@ -232,13 +232,13 @@ PrefsDialog :: createWebTab( Session& session ) hig->addRow( l, h, 0 ); l = hig->addRow( tr( "Listening &port:" ), w = spinBoxNew( Prefs::RPC_PORT, 0, 65535, 1 ) ); myWebWidgets << l << w; - hig->addWideControl( w = checkBoxNew( tr( "&Require username" ), Prefs::RPC_AUTH_REQUIRED ) ); + hig->addWideControl( w = checkBoxNew( tr( "Use &authentication" ), Prefs::RPC_AUTH_REQUIRED ) ); myWebWidgets << w; l = hig->addRow( tr( "&Username:" ), w = lineEditNew( Prefs::RPC_USERNAME ) ); myWebAuthWidgets << l << w; l = hig->addRow( tr( "Pass&word:" ), w = lineEditNew( Prefs::RPC_PASSWORD, QLineEdit::Password ) ); myWebAuthWidgets << l << w; - hig->addWideControl( w = checkBoxNew( tr( "Only allow the following IP &addresses to connect:" ), Prefs::RPC_WHITELIST_ENABLED ) ); + hig->addWideControl( w = checkBoxNew( tr( "Only allow these IP &addresses to connect:" ), Prefs::RPC_WHITELIST_ENABLED ) ); myWebWidgets << w; l = hig->addRow( tr( "Addresses:" ), w = lineEditNew( Prefs::RPC_WHITELIST ) ); myWebWhitelistWidgets << l << w; @@ -264,7 +264,7 @@ PrefsDialog :: createBandwidthTab( ) { QWidget *l, *r; HIG * hig = new HIG( this ); - hig->addSectionTitle( tr( "Global Bandwidth Limits" ) ); + hig->addSectionTitle( tr( "Speed Limits" ) ); l = checkBoxNew( tr( "Limit &download speed (KB/s):" ), Prefs::DSPEED_ENABLED ); r = spinBoxNew( Prefs::DSPEED, 0, INT_MAX, 5 ); @@ -283,13 +283,16 @@ PrefsDialog :: createBandwidthTab( ) label->setPixmap( QPixmap( ":/icons/alt-limit-off.png" ) ); label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter ); h->addWidget( label ); - label = new QLabel( tr( "Speed Limit Mode" ) ); + label = new QLabel( tr( "Temporary Speed Limits" ) ); label->setStyleSheet( "font: bold" ); label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter ); h->addWidget( label ); hig->addSectionTitle( h ); - QString s = tr( "Limit d&ownload speed (KB/s):" ); + QString s = tr( "Override normal speed limits manually or at scheduled times" ); + hig->addWideControl( new QLabel( s ) ); + + s = tr( "Limit d&ownload speed (KB/s):" ); r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_DOWN, 0, INT_MAX, 5 ); hig->addRow( s, r ); @@ -297,10 +300,7 @@ PrefsDialog :: createBandwidthTab( ) r = spinBoxNew( Prefs :: ALT_SPEED_LIMIT_UP, 0, INT_MAX, 5 ); hig->addRow( s, r ); - s = tr( "When enabled, Speed Limit Mode overrides the Global Bandwidth Limits" ); - hig->addWideControl( new QLabel( s ) ); - - QCheckBox * c = checkBoxNew( tr( "Use Speed Limit Mode &between" ), Prefs::ALT_SPEED_LIMIT_TIME_ENABLED ); + QCheckBox * c = checkBoxNew( tr( "&Scheduled use:" ), Prefs::ALT_SPEED_LIMIT_TIME_ENABLED ); h = new QHBoxLayout( ); h->setSpacing( HIG::PAD ); QWidget * w = timeEditNew( Prefs :: ALT_SPEED_LIMIT_TIME_BEGIN ); @@ -377,8 +377,8 @@ PrefsDialog :: createNetworkTab( ) hig->addRow( tr( "&Port for incoming connections:" ), s ); hig->addRow( "", h, 0 ); - hig->addWideControl( checkBoxNew( tr( "&Randomize the port every launch" ), Prefs :: PEER_PORT_RANDOM_ON_START ) ); hig->addWideControl( checkBoxNew( tr( "Use UPnP or NAT-PMP port &forwarding from my router" ), Prefs::PORT_FORWARDING ) ); + hig->addWideControl( checkBoxNew( tr( "Pick a &random port every time Transmission is started" ), Prefs :: PEER_PORT_RANDOM_ON_START ) ); hig->finish( ); return hig; @@ -456,23 +456,23 @@ PrefsDialog :: createPeersTab( ) myBlockWidgets << l; hig->addWideControl( l ); - hig->addSectionDivider( ); - hig->addSectionTitle( tr( "Limits" ) ); - hig->addRow( tr( "Maximum peers &overall:" ), spinBoxNew( Prefs::PEER_LIMIT_GLOBAL, 1, 3000, 5 ) ); - hig->addRow( tr( "Maximum peers per &torrent:" ), spinBoxNew( Prefs::PEER_LIMIT_TORRENT, 1, 300, 5 ) ); - QComboBox * box = new QComboBox( ); - box->addItem( tr( "Plaintext Preferred" ), 0 ); - box->addItem( tr( "Encryption Preferred" ), 1 ); - box->addItem( tr( "Encryption Required" ), 2 ); + box->addItem( tr( "Plaintext preferred" ), 0 ); + box->addItem( tr( "Encryption preferred" ), 1 ); + box->addItem( tr( "Encryption required" ), 2 ); myWidgets.insert( Prefs :: ENCRYPTION, box ); connect( box, SIGNAL(activated(int)), this, SLOT(encryptionEdited(int))); hig->addSectionDivider( ); hig->addSectionTitle( tr( "Privacy" ) ); hig->addRow( tr( "&Encryption mode:" ), box ); - hig->addWideControl( checkBoxNew( tr( "Use peer e&xchange (PEX)" ), Prefs::PEX_ENABLED ) ); - hig->addWideControl( checkBoxNew( tr( "Use &distributed hash table (DHT)" ), Prefs::PEX_ENABLED ) ); + hig->addWideControl( checkBoxNew( tr( "Use PE&X to find more peers" ), Prefs::PEX_ENABLED ) ); + hig->addWideControl( checkBoxNew( tr( "Use &DHT to find more peers" ), Prefs::DHT_ENABLED ) ); + + hig->addSectionDivider( ); + hig->addSectionTitle( tr( "Limits" ) ); + hig->addRow( tr( "Maximum peers per &torrent:" ), spinBoxNew( Prefs::PEER_LIMIT_TORRENT, 1, 300, 5 ) ); + hig->addRow( tr( "Maximum peers &overall:" ), spinBoxNew( Prefs::PEER_LIMIT_GLOBAL, 1, 3000, 5 ) ); hig->finish( ); updateBlocklistCheckBox( ); @@ -551,7 +551,7 @@ PrefsDialog :: createTorrentsTab( ) hig->addSectionDivider( ); hig->addSectionTitle( tr( "Limits" ) ); - l = checkBoxNew( tr( "&Stop seeding torrents at ratio:" ), Prefs::RATIO_ENABLED ); + l = checkBoxNew( tr( "&Seed torrent until its ratio reaches:" ), Prefs::RATIO_ENABLED ); r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 ); hig->addRow( l, r ); enableBuddyWhenChecked( qobject_cast(l), r ); diff --git a/qt/torrent.h b/qt/torrent.h index 9f0e4cc96..ba1653ecb 100644 --- a/qt/torrent.h +++ b/qt/torrent.h @@ -215,11 +215,13 @@ class Torrent: public QObject QString torrentFile( ) const { return getString( TORRENT_FILE ); } bool hasError( ) const { return !getError( ).isEmpty( ); } bool isDone( ) const { return getSize( LEFT_UNTIL_DONE ) == 0; } - bool isSeed( ) const { return haveVerified() >= getSize( TOTAL_SIZE ); } + bool isSeed( ) const { return haveVerified() >= totalSize(); } bool isPrivate( ) const { return getBool( IS_PRIVATE ); } bool getSeedRatio( double& setme ) const; uint64_t haveVerified( ) const { return getSize( HAVE_VERIFIED ); } - uint64_t haveTotal( ) const { return haveVerified( ) + getSize( HAVE_UNCHECKED ); } + uint64_t haveUnverified( ) const { return getSize( HAVE_UNCHECKED ); } + uint64_t haveTotal( ) const { return haveVerified( ) + haveUnverified(); } + uint64_t totalSize( ) const { return getSize( TOTAL_SIZE ); } uint64_t sizeWhenDone( ) const { return getSize( SIZE_WHEN_DONE ); } uint64_t leftUntilDone( ) const { return getSize( LEFT_UNTIL_DONE ); } uint64_t pieceSize( ) const { return getSize( PIECE_SIZE ); } diff --git a/qt/transmission_en.qm b/qt/transmission_en.qm new file mode 100644 index 000000000..16475f887 Binary files /dev/null and b/qt/transmission_en.qm differ diff --git a/qt/transmission_en.ts b/qt/transmission_en.ts index af4300a9b..52a327853 100644 --- a/qt/transmission_en.ts +++ b/qt/transmission_en.ts @@ -1,976 +1,27 @@ - - AboutDialog - - - About Transmission - - - - - Copyright 2005-2009 The Transmission Project - - - - - C&redits - - - - - &License - - - - - Credits - - - - - A fast and easy BitTorrent client - - - Details - - - Activity - - - - - Peers - - - - - Tracker - - - - - Files - - - - - Options - - - - - Information - - - - - %1 (%2 verified in %L3 pieces) - - - - - - None - - - - - Torrent Properties - - - - - Mixed - - - - - %L1 Pieces - - - - - %L1 Pieces @ %2 - - - - - Private to this tracker -- PEX disabled - - - - - Public torrent - - - - - Now - - - - - Transfer - - - - - State: - - - - - Progress: - - - - - Have: - - - - - Downloaded: - - - - - Uploaded: - - - - - Failed DL: - - - - - Ratio: - - - - - Swarm Rate: - - - - - Error: - - - - - Dates - - - - - Honor global &limits - - - - - Limit &download speed (KB/s) - - - - - Limit &upload speed (KB/s) - - - - - Low - - - - - Normal - - - - - High - - - - - &Bandwidth priority: - - - - - Seed-Until Ratio - - - - - Use &global setting - - - - - Seed &regardless of ratio - - - - - &Stop seeding when a torrent's ratio reaches - - - - - Peer Connections - - - - - &Maximum Peers - - - - - Details - - - - - Pieces: - - - - - Hash: - - - - - Privacy: - - - - - Comment: - - - - - - Origins - - - - - Creator: - - - - - Date: - - - - - Destination folder: - - - - - Torrent file: - - - - - Scrape - - - - - Last scrape at: - - - - - - Tracker responded: - - - - - Next scrape in: - - - - - Announce - - - - - Tracker: - - - - - Last announce at: - - - - - Next announce in: - - - - - Manual announce allowed in: - - - - - Unknown - - - - - Optimistic unchoke - - - - - Downloading from this peer - - - - - We would download from this peer if they would let us - - - - - Uploading to peer - - - - - We would upload to this peer if they asked - - - - - Peer has unchoked us, but we're not interested - - - - - We unchoked this peer, but they're not interested - - - - - - Encrypted connection - - - - - Peer was discovered through Peer Exchange (PEX) - - - - - Peer is an incoming connection - - - - - Added on: - - - - - Last activity on: - - - - - Speed - - - - - Up - - - - - Down - - - - - % - - - - - Status - - - - - Address - - - - - Client - - - - - FileTreeItem - - - Low - - - - - High - - - - - Normal - - - - - Mixed - - - - - FileTreeModel - - - File - - - - - Progress - - - - - Download - - - - - Priority - - - - - LicenseDialog - - - License - - - - - MainWindow - - - Transmission - - - - - &Torrent - - - - - &Edit - - - - - &Help - - - - - &View - - - - - toolBar - - - - - &Add... - - - - - Add a torrent - - - - - Ctrl+D - - - - - &New... - - - - - Create a new torrent - - - - - Ctrl+N - - - - - &Properties - - - - - Show torrent properties - - - - - Alt+Enter - - - - - &Open Folder - - - - - Open the torrent's folder - - - - - Ctrl+O - - - - - &Start - - - - - Start torrent - - - - - Ctrl+S - - - - - Ask Tracker for &More Peers - - - - - Ask tracker for more peers - - - - - &Pause - - - - - Pause torrent - - - - - Ctrl+P - - - - - &Verify Local Data - - - - - Verify local data - - - - - &Remove - - - - - Remove torrent - - - - - Del - - - - - &Delete Files and Remove - - - - - Remove torrent and delete its files - - - - - Shift+Del - - - - - &Start All - - - - - &Pause All - - - - - &Quit - - - - - Ctrl+Q - - - - - &Select All - - - - - Ctrl+A - - - - - &Deselect All - - - - - Ctrl+Shift+A - - - - - &Preferences - - - - - &Minimal View - - - - - Alt+M - - - - - &Toolbar - - - - - &Filterbar - - - - - &Statusbar - - - - - Sort by &Activity - - - - - Sort by A&ge - - - - - Sort by &ETA - - - - - Sort by &Name - - - - - Sort by &Progress - - - - - Sort by &Ratio - - - - - Sort by Si&ze - - - - - Sort by &State - - - - - Sort by &Tracker - - - - - Message &Log - - - - - &Main Window - - - - - &Change Session... - - - - - Choose Session - - - - - Set &Location... - - - - - &Statistics - - - - - &Contents - - - - - &About - - - - - &Reverse Sort Order - - - - - &Name - - - - - &Files - - - - - &Tracker - - - - - Total Ratio - - - - - Session Ratio - - - - - Total Transfer - - - - - Session Transfer - - - - - Tray &Icon - + + + %1 (%Ln pieces @ %2) + + %1 (%Ln piece @ %2) + %1 (%Ln pieces @ %2) + + + + + %1 (%Ln pieces) + + %1 (%Ln piece) + %1 (%Ln pieces) + MakeDialog - - - New Torrent - - - - - Source - - - - - <i>No source selected</i> - - - - - F&older - - - - - &File - - - - - Trackers - - - - - Separate tiers with an empty line - - - - - Options - - - - - Commen&t: - - - - - Progress - - - - - &New Torrent - - - - - &Close - - - - - %1.torrent created! - - - - - Error: Invalid URL - - - - - Torrent creation cancelled - - - - - Error: Couldn't read "%1": %2 - - - - - Error: Couldn't create "%1": %2 - - - - - Creating %1.torrent - - - - - - <i>No source selected<i> - - - - - <i>No tracker announce URLs listed</i> - - - - - %1 in %2; %3 @ %4 - - - - - &Stop - - %Ln File(s) @@ -988,166 +39,8 @@ - - Options - - - - Add Torrent - - - - - &Torrent file: - - - - - &Destination folder: - - - - - &Verify Local Data - - - - - &Start when added - - - - - &Delete source file - &Move source file to Trash - - - - - Torrent Files (*.torrent);;All Files (*.*) - - - - - Select Destination - - - PrefsDialog - - - Tracker Proxy - - - - - Connect to tracker via a pro&xy - - - - - Proxy &server: - - - - - Proxy &port: - - - - - Require &authentication - - - - - - &Username: - - - - - - Pass&word: - - - - - Web Interface - - - - - &Open web interface - - - - - &Enable web interface - - - - - Listening &port: - - - - - &Require username - - - - - Only allow the following IP &addresses to connect: - - - - - Addresses: - - - - - &Randomize the port every launch - - - - - - Limits - - - - - Limit &download speed (KB/s): - - - - - Limit d&ownload speed (KB/s): - - - - - Limit u&pload speed (KB/s): - - - - - Incoming Peers - - - - - Use UPnP or NAT-PMP port &forwarding from my router - - - - - Blocklist - - Enable &blocklist (contains %Ln rule(s)) @@ -1155,107 +48,6 @@ Enable &blocklist (contains %Ln rules) - - - Not supported by remote sessions - - - - - &Update blocklist - - - - - <small>When enabled, Speed Limit Mode overrides the Global Bandwidth Limits</small> - - - - - &On days: - - - - - Every Day - - - - - Weekdays - - - - - Weekends - - - - - Sunday - - - - - Monday - - - - - Tuesday - - - - - Wednesday - - - - - Thursday - - - - - Friday - - - - - Saturday - - - - - Port is <b>open</b> - - - - - Port is <b>closed</b> - - - - - Testing... - - - - - &Test Port - - - - - - Status unknown - - - - - &Port for incoming connections: - - <b>Update succeeded!</b><p>Blocklist now has %Ln rules. @@ -1264,111 +56,6 @@ - - - <b>Update Blocklist</b><p>Getting new blocklist... - - - - - Enable &automatic updates - - - - - Maximum peers &overall: - - - - - Maximum peers per &torrent: - - - - - Plaintext Preferred - - - - - Encryption Preferred - - - - - Encryption Required - - - - - Privacy - - - - - Select Watch Directory - - - - - Select Destination - - - - - Adding Torrents - - - - - Automatically &add torrents from: - - - - - Display &options dialog - - - - - &Start when added - - - - - &Destination folder: - - - - - Transmission Preferences - - - - - Torrents - - - - - Peers - - - - - Network - - - - - Web - - - - - Enable &blocklist - - Enable &blocklist (%Ln rules) @@ -1377,56 +64,6 @@ Enable &blocklist (%Ln rules) - - - Global Bandwidth Limits - - - - - Speed Limit Mode - - - - - Use Speed Limit Mode &between - - - - - &Encryption mode: - - - - - Use peer e&xchange (PEX) - - - - - Use &distributed hash table (DHT) - - - - - &Delete source files - - - - - &Stop seeding torrents at ratio: - - - - - Speed - - - - - Limit &upload speed (KB/s): - - Enable &blocklist (%Ln entries) @@ -1435,149 +72,8 @@ - - QObject - - - transmission %1 - - - - - Invalid option - - - - - Got opt %1 - - - - - RelocateDialog - - - Set Torrent Location - - - - - Set Location - - - - - New &location: - - - - - &Move from the current folder - - - - - Local data is &already there - - - - - Session - - - Add Torrent - - - - - SessionDialog - - - Change Session - - - - - Source - - - - - Start &Local Session - - - - - Connect to &Remote Session - - - - - &Host: - - - - - &Port: - - - - - &Authentication required - - - - - &Username: - - - - - Pass&word: - - - StatsDialog - - - Statistics - - - - - Current Session - - - - - - Uploaded: - - - - - - Downloaded: - - - - - - Ratio: - - - - - - Duration: - - - - - Total - - @@ -1588,107 +84,8 @@ - - Torrent - - - Waiting to verify local data - - - - - Verifying local data - - - - - Downloading - - - - - Seeding - - - - - Paused - - - TorrentDelegate - - - %1 of %2 (%3%) - - - - - %1 of %2 (%3%), uploaded %4 (Ratio: %5) - - - - - %1, uploaded %2 (Ratio: %3 Goal %4) - - - - - %1, uploaded %2 (Ratio: %3) - - - - - - - - - - - - %1 left - - - - - Remaining time unknown - - - - - Down: %1, Up: %2 - - - - - Down: %1 - - - - - Up: %1 - - - - - Idle - - - - - Paused - - - - - Waiting to verify local data - - - - - Verifying local data (%1% tested) - - Downloading from %1 of %n connected peer(s) @@ -1705,19 +102,9 @@ Seeding to %1 of %n connected peers - - - Ratio: %1, - - TrMainWindow - - - - %1 - - %Ln Torrent(s) @@ -1741,127 +128,9 @@ %L1 of %Ln Torrents - - - - Ratio: %1 - - - - - - Down: %1, Up: %2 - - - - - Add Torrent - - - - - Torrent Files (*.torrent);;All Files (*.*) - - - - - Display &options dialog - - - - - Transmission server is responding - - - - - Last response from server was %1 ago - - - - - Click to disable Speed Limit Mode - - - - - A&ll - - - - - &Active - - - - - &Downloading - - - - - &Seeding - - - - - &Paused - - - - - Limit Download Speed - - - - - - Unlimited - - - - - - - - Limited at %1 - - - - - Limit Upload Speed - - - - - Stop Seeding at Ratio - - - - - Seed Forever - - - - - - Stop at Ratio (%1) - - - - - Click to enable Speed Limit Mode - - Utils - - - - None - - %Ln byte(s) @@ -1870,21 +139,6 @@ %Ln bytes - - - %L1 KB - - - - - %L1 MB - - - - - %L1 GB - - %Ln day(s) @@ -1917,27 +171,5 @@ %Ln seconds - - - - - %1, %2 - - - - - %L1 KB/s - - - - - %L1 MB/s - - - - - %L1 GB/s - -