Changeset 4210


Ignore:
Timestamp:
Dec 19, 2007, 2:46:30 AM (14 years ago)
Author:
charles
Message:

first cut at adopting some of the OS X client's main list UI into the gtk+ client

Location:
trunk/gtk
Files:
2 added
2 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/Makefile.am

    r4092 r4210  
    2121    msgwin.h \
    2222    stats.h \
     23    torrent-cell-renderer.h \
    2324    torrent-inspector.h \
    24     tr_cell_renderer_progress.h \
    2525    tr_core.h \
    2626    tr_icon.h \
     
    4444    msgwin.c \
    4545    stats.c \
     46    torrent-cell-renderer.c \
    4647    torrent-inspector.c \
    47     tr_cell_renderer_progress.c \
    4848    tr_core.c \
    4949    tr_icon.c \
  • trunk/gtk/actions.c

    r3993 r4210  
    1515#include <gtk/gtk.h>
    1616#include <libtransmission/transmission.h>
     17#include "conf.h"
    1718#include "torrent-inspector.h"
     19#include "tr_prefs.h"
    1820#include "lock.h"
    1921#include "logo.h"
     
    5254  const int priority = gtk_radio_action_get_current_value (current);
    5355  set_selected_file_priority ( priority );
     56}
     57
     58static GtkRadioActionEntry sort_radio_entries[] =
     59{
     60  { "sort-by-activity",   NULL, N_("Sort by _Activity"),   NULL, NULL, 0 },
     61  { "sort-by-date-added", NULL, N_("Sort by _Date Added"), NULL, NULL, 1 },
     62  { "sort-by-name",       NULL, N_("Sort by _Name"),       NULL, NULL, 2 },
     63  { "sort-by-progress",   NULL, N_("Sort by _Progress"),   NULL, NULL, 3 },
     64  { "sort-by-state",      NULL, N_("Sort by _State"),      NULL, NULL, 4 },
     65  { "sort-by-tracker",    NULL, N_("Sort by _Tracker"),    NULL, NULL, 5 }
     66};
     67
     68static void
     69sort_changed_cb( GtkAction * action UNUSED, GtkRadioAction * current, gpointer user_data )
     70{
     71  const int i = gtk_radio_action_get_current_value( current );
     72  const char * name = sort_radio_entries[i].name;
     73  doAction ( name, user_data );
    5474}
    5575
     
    6282};
    6383
     84static GtkToggleActionEntry persistent_toggle_entries[] =
     85{
     86  { "minimal-view", NULL,
     87    N_("_Minimal View"), "<control>M", NULL, G_CALLBACK(action_cb), FALSE },
     88  { "reverse-sort-order", NULL,
     89    N_("_Reverse Sort Order"), NULL, NULL, G_CALLBACK(action_cb), FALSE }
     90};
     91
    6492static GtkActionEntry entries[] =
    6593{
    6694  { "torrent-menu", NULL, N_("_Torrent"), NULL, NULL, NULL },
     95  { "view-menu", NULL, N_("_View"), NULL, NULL, NULL },
     96  { "sort-menu", NULL, N_("_Sort Torrents By"), NULL, NULL, NULL },
    6797  { "edit-menu", NULL, N_("_Edit"), NULL, NULL, NULL },
    6898  { "help-menu", NULL, N_("_Help"), NULL, NULL, NULL },
     
    161191actions_init( GtkUIManager * ui_manager, gpointer callback_user_data )
    162192{
    163   int i;
     193  int i, n;
     194  int active;
     195  char * match;
    164196  const int n_entries = G_N_ELEMENTS( entries );
    165197  GtkActionGroup * action_group;
     
    181213                                      G_CALLBACK(priority_changed_cb), NULL);
    182214
    183   gtk_action_group_add_toggle_actions ( action_group,
    184                                         show_toggle_entries,
    185                                         G_N_ELEMENTS(show_toggle_entries),
    186                                         callback_user_data );
     215
     216  match = pref_string_get( PREF_KEY_SORT_MODE );
     217  for( i=0, n=G_N_ELEMENTS(sort_radio_entries), active=-1; active==-1 && i<n; ++i ) {
     218      if( !strcmp( sort_radio_entries[i].name, match ) ) {
     219          g_message( "found %s in index %d", match, i );
     220          active = i;
     221      }
     222  }
     223
     224  gtk_action_group_add_radio_actions( action_group,
     225                                      sort_radio_entries,
     226                                      G_N_ELEMENTS(sort_radio_entries),
     227                                      active,
     228                                      G_CALLBACK(sort_changed_cb),
     229                                      callback_user_data );
     230
     231  gtk_action_group_add_toggle_actions( action_group,
     232                                       show_toggle_entries,
     233                                       G_N_ELEMENTS(show_toggle_entries),
     234                                       callback_user_data );
     235
     236  for( i=0, n=G_N_ELEMENTS(persistent_toggle_entries); i<n; ++i )
     237    persistent_toggle_entries[i].is_active = pref_flag_get( persistent_toggle_entries[i].name );
     238
     239  gtk_action_group_add_toggle_actions( action_group,
     240                                       persistent_toggle_entries,
     241                                       G_N_ELEMENTS(persistent_toggle_entries),
     242                                       callback_user_data );
    187243
    188244  gtk_action_group_add_actions( action_group,
  • trunk/gtk/dialogs.c

    r3380 r4210  
    3636#include "dialogs.h"
    3737#include "hig.h"
    38 #include "tr_cell_renderer_progress.h"
    3938#include "tr_core.h"
    4039#include "tr_icon.h"
  • trunk/gtk/main.c

    r4169 r4210  
    4444#include "stats.h"
    4545#include "torrent-inspector.h"
    46 #include "tr_cell_renderer_progress.h"
    4746#include "tr_core.h"
    4847#include "tr_icon.h"
     
    170169    int status = 0;
    171170    struct counts_data * counts = user_data;
     171    tr_torrent * tor;
    172172
    173173    ++counts->totalCount;
    174174
    175     gtk_tree_model_get( model, iter, MC_STAT, &status, -1 );
     175    gtk_tree_model_get( model, iter, MC_TORRENT_RAW, &tor, -1 );
     176    status = tr_torrentStat( tor )->status;
     177
    176178    if( TR_STATUS_IS_ACTIVE( status ) )
    177179        ++counts->activeCount;
     
    248250    g_thread_init( NULL );
    249251    gtk_init_with_args( &argc, &argv, _("[torrent files]"), entries, domain, NULL );
     252    didinit = cf_init( tr_getPrefsDirectory(), NULL ); /* must come before actions_init */
     253    tr_prefs_init_global( );
    250254    myUIManager = gtk_ui_manager_new ();
    251255    actions_init ( myUIManager, cbdata );
     
    255259
    256260    argfiles = checkfilenames( argc-1, argv+1 );
    257     didinit = cf_init( tr_getPrefsDirectory(), NULL );
    258261    didlock = didinit && sendremote( argfiles, sendquit );
    259262    setupsighandlers( ); /* set up handlers for fatal signals */
     
    264267        /* create main window now to be a parent to any error dialogs */
    265268        GtkWindow * mainwind = GTK_WINDOW( tr_window_new( myUIManager ) );
    266 
    267         tr_prefs_init_global( );
    268269
    269270        /* set message level here before tr_init() */
     
    666667        PREF_KEY_PEX,
    667668        PREF_KEY_SYSTRAY,
    668         PREF_KEY_SORT_COLUMN,
     669        PREF_KEY_SORT_MODE,
     670        PREF_KEY_SORT_REVERSED,
     671        PREF_KEY_MINIMAL_VIEW,
    669672        PREF_KEY_ENCRYPTED_ONLY
    670673    };
     
    728731        }
    729732    }
    730     else if( !strcmp( key, PREF_KEY_SORT_COLUMN ) )
    731     {
    732         tr_core_set_sort_column_from_prefs( cbdata->core );
     733    else if( !strcmp( key, PREF_KEY_SORT_MODE ) || !strcmp( key, PREF_KEY_SORT_REVERSED ) )
     734    {
     735        tr_core_resort( cbdata->core );
    733736    }
    734737    else if( !strcmp( key, PREF_KEY_PEX ) )
     
    736739        gboolean enabled = pref_flag_get( key );
    737740        tr_torrentIterate( tr, setpex, &enabled );
     741    }
     742    else if( !strcmp( key, PREF_KEY_MINIMAL_VIEW ) )
     743    {
     744        const gboolean enabled = pref_flag_get( key );
     745        g_message( "minimal view: %d", enabled );
    738746    }
    739747}
     
    10171025            gtk_window_present (GTK_WINDOW(w));
    10181026    }
     1027    else if( !strcmp( action_name, "sort-by-activity" )
     1028         ||  !strcmp( action_name, "sort-by-date-added" )
     1029         ||  !strcmp( action_name, "sort-by-name" )
     1030         ||  !strcmp( action_name, "sort-by-progress" )
     1031         ||  !strcmp( action_name, "sort-by-state" )
     1032         ||  !strcmp( action_name, "sort-by-tracker" ) )
     1033    {
     1034        tr_core_set_pref( data->core, PREF_KEY_SORT_MODE, action_name );
     1035    }
     1036    else if( !strcmp( action_name, "reverse-sort-order" ) )
     1037    {
     1038        tr_core_toggle_pref_bool( data->core, PREF_KEY_SORT_REVERSED );
     1039    }
     1040    else if( !strcmp( action_name, "minimal-view" ) )
     1041    {
     1042        tr_core_toggle_pref_bool( data->core, PREF_KEY_MINIMAL_VIEW );
     1043    }
    10191044    else g_error ("Unhandled action: %s", action_name );
    10201045
  • trunk/gtk/makemeta-ui.c

    r4015 r4210  
    174174{
    175175    MakeMetaUI * ui = (MakeMetaUI *) user_data;
    176     char * pch;
    177176    char * filename;
     177    char sizeStr[128];
    178178    char buf[512];
    179179    uint64_t totalSize=0;
     
    195195    }
    196196
    197     pch = readablesize( totalSize );
     197    tr_strlsize( sizeStr, totalSize, sizeof(sizeStr) );
    198198    g_snprintf( buf, sizeof(buf), "<i>%s; %d %s</i>",
    199                 pch, fileCount,
     199                sizeStr, fileCount,
    200200                ngettext("File", "Files", fileCount) );
    201201    gtk_label_set_markup ( GTK_LABEL(ui->size_lb), buf );
    202     g_free( pch );
    203 
    204     pch = readablesize( pieceSize );
     202
     203    tr_strlsize( sizeStr, pieceSize, sizeof(sizeStr) );
    205204    g_snprintf( buf, sizeof(buf), "<i>%d %s @ %s</i>",
    206205                pieceCount,
    207206                ngettext("Piece", "Pieces", pieceCount),
    208                 pch );
     207                sizeStr );
    209208    gtk_label_set_markup ( GTK_LABEL(ui->pieces_lb), buf );
    210     g_free( pch );
    211209}
    212210
  • trunk/gtk/stats.c

    r3993 r4210  
    5050updateStats( gpointer gdata )
    5151{
     52    char buf[128];
     53
    5254    struct stat_ui * ui = gdata;
    5355    tr_session_stats one, all;
     
    5557    tr_getCumulativeSessionStats( ui->core->handle, &all );
    5658
    57     setLabel( ui->one_up_lb, readablesize( one.uploadedBytes ) );
    58     setLabel( ui->one_down_lb, readablesize( one.downloadedBytes ) );
    59     setLabel( ui->one_time_lb, readabletime( one.secondsActive ) );
     59    setLabel( ui->one_up_lb, tr_strlsize( buf, one.uploadedBytes, sizeof(buf) ) );
     60    setLabel( ui->one_down_lb, tr_strlsize( buf, one.downloadedBytes, sizeof(buf) ) );
     61    setLabel( ui->one_time_lb, tr_strlsize( buf, one.secondsActive, sizeof(buf) ) );
    6062    setLabelFromRatio( ui->one_ratio_lb, one.ratio );
    6163    setLabel( ui->all_sessions_lb, g_strdup_printf( _("Started %d times"), (int)all.sessionCount ) );
    62     setLabel( ui->all_up_lb, readablesize( all.uploadedBytes ) );
    63     setLabel( ui->all_down_lb, readablesize( all.downloadedBytes ) );
     64    setLabel( ui->all_up_lb, tr_strlsize( buf, all.uploadedBytes, sizeof(buf) ) );
     65    setLabel( ui->all_down_lb, tr_strlsize( buf, all.downloadedBytes, sizeof(buf) ) );
    6466    setLabel( ui->all_time_lb, readabletime( all.secondsActive ) );
    6567    setLabelFromRatio( ui->all_ratio_lb, all.ratio );
  • trunk/gtk/torrent-inspector.c

    r4015 r4210  
    399399    g_object_set (renderer, "text", "", NULL);
    400400  else {
    401     char * pch = readablespeed (rate);
    402     g_object_set (renderer, "text", pch, NULL);
    403     g_free (pch);
     401    char speedStr[64];
     402    tr_strlspeed( speedStr, rate, sizeof(speedStr) );
     403    g_object_set( renderer, "text", speedStr, NULL );
    404404  }
    405405}
     
    417417    g_object_set (renderer, "text", "", NULL);
    418418  else {
    419     char * pch = readablespeed (rate);
    420     g_object_set (renderer, "text", pch, NULL);
    421     g_free (pch);
     419    char speedStr[64];
     420    tr_strlspeed( speedStr, rate, sizeof(speedStr) );
     421    g_object_set( renderer, "text", speedStr, NULL );
    422422  }
    423423}
     
    740740  char *pch;
    741741  char *dname, *bname;
     742  char sizeStr[128];
    742743  char buf[256];
    743744  char name[128];
     
    760761
    761762    g_snprintf (name, sizeof(name), namefmt, _("Pieces"));
    762     pch = readablesize (info->pieceSize);
    763     g_snprintf (buf, sizeof(buf), "%d (%s)", info->pieceCount, pch);
     763    tr_strlsize( sizeStr, info->pieceSize, sizeof(sizeStr) );
     764    g_snprintf( buf, sizeof(buf), "%d (%s)", info->pieceCount, sizeStr );
    764765    l = gtk_label_new (buf);
    765766    hig_workarea_add_row (t, &row, name, l, NULL);
    766     g_free (pch);
    767767
    768768    g_snprintf (name, sizeof(name), namefmt, _("Hash"));
     
    854854  Activity * a = (Activity*) g_object_get_data (G_OBJECT(top), "activity-data");
    855855  const tr_stat * stat = tr_torrent_stat( a->gtor );
    856   char *pch, *pch2, *pch3;
     856  char *pch;
     857  char sizeStr[64];
     858  char sizeStr2[64];
     859  char buf[128];
    857860
    858861  pch = tr_torrent_status_str( a->gtor );
     
    864867  g_free (pch);
    865868
    866   pch = readablesize( stat->haveValid + stat->haveUnchecked );
    867   pch2 = readablesize( stat->haveValid );
    868   pch3 = g_strdup_printf( _("%s (%s verified)"), pch, pch2 );
    869   gtk_label_set_text( GTK_LABEL( a->have_lb ), pch3 );
    870   g_free( pch3 );
    871   g_free( pch2 );
    872   g_free( pch );
    873 
    874   pch = readablesize (stat->downloadedEver);
    875   gtk_label_set_text (GTK_LABEL(a->dl_lb), pch);
    876   g_free (pch);
    877 
    878   pch = readablesize (stat->uploadedEver);
    879   gtk_label_set_text (GTK_LABEL(a->ul_lb), pch);
    880   g_free (pch);
    881 
    882   pch = readablesize (stat->corruptEver);
    883   gtk_label_set_text (GTK_LABEL(a->failed_lb), pch);
    884   g_free (pch);
    885 
    886   pch = g_strdup_printf( "%.1f", stat->ratio );
    887   gtk_label_set_text (GTK_LABEL(a->ratio_lb), pch);
    888   g_free (pch);
    889 
    890   pch = readablespeed (stat->swarmspeed);
    891   gtk_label_set_text (GTK_LABEL(a->swarm_lb), pch);
    892   g_free (pch);
     869  tr_strlsize( sizeStr,  stat->haveValid + stat->haveUnchecked, sizeof(sizeStr) );
     870  tr_strlsize( sizeStr2, stat->haveValid,                       sizeof(sizeStr2) );
     871  g_snprintf( buf, sizeof(buf), _("%s (%s verified)"), sizeStr, sizeStr2 );
     872  gtk_label_set_text( GTK_LABEL( a->have_lb ), buf );
     873
     874  tr_strlsize( sizeStr, stat->downloadedEver, sizeof(sizeStr) );
     875  gtk_label_set_text( GTK_LABEL(a->dl_lb), sizeStr );
     876
     877  tr_strlsize( sizeStr, stat->uploadedEver, sizeof(sizeStr) );
     878  gtk_label_set_text( GTK_LABEL(a->ul_lb), sizeStr );
     879
     880  tr_strlsize( sizeStr, stat->corruptEver, sizeof(sizeStr) );
     881  gtk_label_set_text (GTK_LABEL(a->failed_lb), sizeStr );
     882
     883  g_snprintf( buf, sizeof(buf), "%.1f", stat->ratio );
     884  gtk_label_set_text (GTK_LABEL(a->ratio_lb), buf );
     885
     886  tr_strlspeed( buf, stat->swarmspeed, sizeof(buf) );
     887  gtk_label_set_text (GTK_LABEL(a->swarm_lb), buf );
    893888
    894889  gtk_label_set_text (GTK_LABEL(a->err_lb),
     
    11131108    GtkTreeIter    iter;
    11141109    uint64_t       mysize, subsize;
    1115     char         * sizestr, * name, * label;
     1110    char         * name, * label;
    11161111
    11171112    model  = GTK_TREE_MODEL( store );
     
    11191114    if( gtk_tree_model_iter_children( model, &iter, parent ) ) do
    11201115    {
     1116         char sizeStr[64];
    11211117        if( gtk_tree_model_iter_has_child( model, &iter ) )
    11221118        {
     
    11291125        }
    11301126        gtk_tree_model_get( model, &iter, FC_LABEL, &name, -1 );
    1131         sizestr = readablesize( subsize );
     1127        tr_strlsize( sizeStr, subsize, sizeof( sizeStr ) );
    11321128        label = g_markup_printf_escaped( "<small>%s (%s)</small>",
    1133                                           name, sizestr );
    1134         g_free( sizestr );
     1129                                          name, sizeStr );
    11351130        g_free( name );
    11361131        gtk_tree_store_set( store, &iter, FC_LABEL, label, -1 );
     
    16801675{
    16811676  guint tag;
    1682   char *size, *pch;
    16831677  GtkWidget *d, *n, *w;
    16841678  tr_torrent * tor = tr_torrent_handle (gtor);
     1679  char sizeStr[64];
     1680  char title[512];
    16851681  const tr_info * info = tr_torrent_info (gtor);
    16861682
    16871683  /* create the dialog */
    1688   size = readablesize( info->totalSize );
    1689   pch = g_strdup_printf( _( "Details for %s (%s)" ), info->name, size );
    1690   d = gtk_dialog_new_with_buttons (pch, parent, 0,
     1684  tr_strlsize( sizeStr, info->totalSize, sizeof(sizeStr) );
     1685  g_snprintf( title, sizeof(title), _( "Details for %s (%s)" ), info->name, sizeStr );
     1686  d = gtk_dialog_new_with_buttons (title, parent, 0,
    16911687                                   GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
    16921688                                   NULL);
     
    16941690  g_signal_connect (d, "response", G_CALLBACK (response_cb), gtor);
    16951691  g_object_weak_ref (G_OBJECT(gtor), torrent_destroyed, d);
    1696   g_free( pch );
    1697   g_free( size );
    16981692
    16991693  /* add the notebook */
  • trunk/gtk/tr_core.c

    r4050 r4210  
    172172
    173173static int
    174 compareProgress( GtkTreeModel  * model,
    175                  GtkTreeIter    * a,
    176                  GtkTreeIter    * b,
    177                  gpointer         user_data UNUSED )
     174compareByActivity( GtkTreeModel * model,
     175                   GtkTreeIter  * a,
     176                   GtkTreeIter  * b,
     177                   gpointer       user_data UNUSED )
    178178{
    179179    int ia, ib;
    180     gfloat rateUpA, rateUpB;
    181     gfloat rateDownA, rateDownB;
    182     gfloat percentDoneA, percentDoneB;
    183     guint64 uploadedEverA, uploadedEverB;
    184 
    185     gtk_tree_model_get( model, a, MC_PROG_D, &percentDoneA,
    186                                   MC_DRATE, &rateDownA,
    187                                   MC_URATE, &rateUpA,
    188                                   MC_UP, &uploadedEverA,
    189                                   -1 );
    190     gtk_tree_model_get( model, b, MC_PROG_D, &percentDoneB,
    191                                   MC_DRATE, &rateDownB,
    192                                   MC_URATE, &rateUpB,
    193                                   MC_UP, &uploadedEverB,
    194                                   -1 );
    195 
    196     ia = (int)( rateUpA + rateDownA );
    197     ib = (int)( rateUpB + rateDownB );
     180    tr_torrent *ta, *tb;
     181    const tr_stat *sa, *sb;
     182
     183    gtk_tree_model_get( model, a, MC_TORRENT_RAW, &ta, -1 );
     184    gtk_tree_model_get( model, b, MC_TORRENT_RAW, &tb, -1 );
     185
     186    sa = tr_torrentStat( ta );
     187    sb = tr_torrentStat( tb );
     188
     189    ia = (int)( 1024 * ( sa->rateUpload + sa->rateDownload ) );
     190    ib = (int)( 1024 * ( sb->rateUpload + sb->rateDownload ) );
    198191    if( ia != ib )
    199192        return ia - ib;
    200193
    201     ia = (int)( 100.0 * percentDoneA );
    202     ib = (int)( 100.0 * percentDoneB );
    203     if( ia != ib )
    204         return ia - ib;
    205 
    206     if( uploadedEverA != uploadedEverB )
    207         return uploadedEverA < uploadedEverB ? -1 : 1;
     194    if( sa->uploadedEver != sb->uploadedEver )
     195        return sa->uploadedEver < sa->uploadedEver ? -1 : 1;
    208196
    209197    return 0;
    210198}
    211199
    212 #define STR_REVERSE "reverse-"
    213 #define STR_PROGRESS "progress"
    214 #define STR_NAME "name"
    215 
    216 static void
    217 onSortColumnChanged( GtkTreeSortable * sortable, gpointer unused UNUSED )
    218 {
    219     int column;
    220     GtkSortType order;
    221     if( gtk_tree_sortable_get_sort_column_id( sortable, &column, &order ) )
    222     {
    223         GString * gstr = g_string_new( NULL );
    224         switch( column ) {
    225             case MC_PROG_D: g_string_assign( gstr, STR_PROGRESS ); break;
    226             default: g_string_assign( gstr, STR_NAME ); break;
    227         }
    228         if( order == GTK_SORT_DESCENDING )
    229             g_string_prepend( gstr, STR_REVERSE );
    230         pref_string_set( PREF_KEY_SORT_COLUMN, gstr->str );
    231         g_string_free( gstr, TRUE );
    232     }
     200static int
     201compareByDateAdded( GtkTreeModel   * model UNUSED,
     202                    GtkTreeIter    * a UNUSED,
     203                    GtkTreeIter    * b UNUSED,
     204                    gpointer         user_data UNUSED )
     205{
     206    /* FIXME */
     207    return 0;
     208}
     209
     210static int
     211compareByName( GtkTreeModel   * model,
     212               GtkTreeIter    * a,
     213               GtkTreeIter    * b,
     214               gpointer         user_data UNUSED )
     215{
     216    int ret;
     217    char *ca, *cb;
     218    gtk_tree_model_get( model, a, MC_NAME_COLLATED, &ca, -1 );
     219    gtk_tree_model_get( model, b, MC_NAME_COLLATED, &cb, -1 );
     220    ret = strcmp( ca, cb );
     221    g_free( cb );
     222    g_free( ca );
     223    return ret;
     224}
     225
     226static int
     227compareByProgress( GtkTreeModel   * model,
     228                   GtkTreeIter    * a,
     229                   GtkTreeIter    * b,
     230                   gpointer         user_data UNUSED )
     231{
     232    TrTorrent *ta, *tb;
     233    const tr_stat *sa, *sb;
     234    int ret;
     235    gtk_tree_model_get( model, a, MC_TORRENT, &ta, -1 );
     236    gtk_tree_model_get( model, b, MC_TORRENT, &tb, -1 );
     237    sa = tr_torrent_stat( ta );
     238    sb = tr_torrent_stat( tb );
     239         if( sa->percentDone < sb->percentDone ) ret = -1;
     240    else if( sa->percentDone > sb->percentDone ) ret =  1;
     241    else                                         ret =  0;
     242    g_object_unref( G_OBJECT( tb ) );
     243    g_object_unref( G_OBJECT( ta ) );
     244    return ret;
     245}
     246
     247static int
     248compareByState( GtkTreeModel   * model,
     249                GtkTreeIter    * a,
     250                GtkTreeIter    * b,
     251                gpointer         user_data UNUSED )
     252{
     253    TrTorrent *ta, *tb;
     254    const tr_stat *sa, *sb;
     255    int ret;
     256    gtk_tree_model_get( model, a, MC_TORRENT, &ta, -1 );
     257    gtk_tree_model_get( model, b, MC_TORRENT, &tb, -1 );
     258    sa = tr_torrent_stat( ta );
     259    sb = tr_torrent_stat( tb );
     260    ret = sa->status - sb->status;
     261    g_object_unref( G_OBJECT( ta ) );
     262    g_object_unref( G_OBJECT( tb ) );
     263    return ret;
     264}
     265
     266static int
     267compareByTracker( GtkTreeModel   * model,
     268                  GtkTreeIter    * a,
     269                  GtkTreeIter    * b,
     270                  gpointer         user_data UNUSED )
     271{
     272    TrTorrent *ta, *tb;
     273    const tr_info *ia, *ib;
     274    int ret;
     275    gtk_tree_model_get( model, a, MC_TORRENT, &ta, -1 );
     276    gtk_tree_model_get( model, b, MC_TORRENT, &tb, -1 );
     277    ia = tr_torrent_info( ta );
     278    ib = tr_torrent_info( tb );
     279    ret = strcmp( ia->primaryAddress, ib->primaryAddress );
     280    g_object_unref( G_OBJECT( ta ) );
     281    g_object_unref( G_OBJECT( tb ) );
     282    return ret;
     283}
     284
     285/***
     286****
     287***/
     288
     289
     290static void
     291setSort( TrCore * core, const char * mode, gboolean isReversed  )
     292{
     293    int col = MC_TORRENT_RAW;
     294    GtkSortType type;
     295    GtkTreeSortable * sortable = GTK_TREE_SORTABLE( core->model );
     296
     297    if( !strcmp( mode, "sort-by-activity" ) )
     298    {
     299        type = isReversed ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
     300        gtk_tree_sortable_set_sort_func( sortable, col, compareByActivity, NULL, NULL );
     301    }
     302    else if( !strcmp( mode, "sort-by-date-added" ) )
     303    {
     304        type = isReversed ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
     305        gtk_tree_sortable_set_sort_func( sortable, col, compareByDateAdded, NULL, NULL );
     306    }
     307    else if( !strcmp( mode, "sort-by-progress" ) )
     308    {
     309        type = isReversed ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
     310        gtk_tree_sortable_set_sort_func( sortable, col, compareByProgress, NULL, NULL );
     311    }
     312    else if( !strcmp( mode, "sort-by-state" ) )
     313    {
     314        type = isReversed ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
     315        gtk_tree_sortable_set_sort_func( sortable, col, compareByState, NULL, NULL );
     316    }
     317    else if( !strcmp( mode, "sort-by-tracker" ) )
     318    {
     319        type = isReversed ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
     320        gtk_tree_sortable_set_sort_func( sortable, col, compareByTracker, NULL, NULL );
     321    }
     322    else
     323    {
     324        type = isReversed ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
     325        gtk_tree_sortable_set_sort_func( sortable, col, compareByName, NULL, NULL );
     326    }
     327    gtk_tree_sortable_set_sort_column_id( sortable, col, type );
    233328}
    234329
    235330void
    236 tr_core_set_sort_column_from_prefs( TrCore * core )
    237 {
    238     char * val = pref_string_get( PREF_KEY_SORT_COLUMN );
    239     char * freeme = val;
    240     gint column;
    241     GtkSortType order = GTK_SORT_ASCENDING;
    242     if( g_str_has_prefix( val, STR_REVERSE ) ) {
    243         order = GTK_SORT_DESCENDING;
    244         val += strlen( STR_REVERSE );
    245     }
    246     if( !strcmp( val, STR_PROGRESS ) )
    247         column = MC_PROG_D;
    248     else /* default */
    249         column = MC_NAME;
    250     gtk_tree_sortable_set_sort_column_id ( GTK_TREE_SORTABLE( core->model ), column, order );
    251     g_free( freeme );
     331tr_core_resort( TrCore * core )
     332{
     333    char * mode = pref_string_get( PREF_KEY_SORT_MODE );
     334    gboolean isReversed = pref_flag_get( PREF_KEY_SORT_REVERSED );
     335    setSort( core, mode, isReversed );
     336    g_free( mode );
    252337}
    253338
     
    260345    /* column types for the model used to store torrent information */
    261346    /* keep this in sync with the enum near the bottom of tr_core.h */
    262     GType types[] =
    263     {
    264         /* info->name, info->totalSize, info->hashString, status, */
    265         G_TYPE_STRING, G_TYPE_UINT64,   G_TYPE_STRING,    G_TYPE_INT,
    266         /* error,   errorString,   percentComplete, percentDone,  rateDownload, rateUpload, */
    267         G_TYPE_INT, G_TYPE_STRING, G_TYPE_FLOAT,    G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_FLOAT,
    268         /* eta,     peersConnected, peersUploading, peersDownloading, seeders, */
    269         G_TYPE_INT, G_TYPE_INT,     G_TYPE_INT,     G_TYPE_INT,       G_TYPE_INT,
    270         /* leechers, completedFromTracker, downloaded,    uploaded */
    271         G_TYPE_INT,  G_TYPE_INT,           G_TYPE_UINT64, G_TYPE_UINT64,
    272         /* ratio,      left,          TrTorrent object, ID for IPC */
    273         G_TYPE_FLOAT,  G_TYPE_UINT64, TR_TORRENT_TYPE,  G_TYPE_INT,
     347    GType types[] = {
     348        G_TYPE_STRING,    /* name */
     349        G_TYPE_STRING,    /* collated name */
     350        G_TYPE_STRING,    /* hash string */
     351        TR_TORRENT_TYPE,  /* TrTorrent object */
     352        G_TYPE_POINTER,   /* tr_torrent* */
     353        G_TYPE_INT        /* ID for IPC */
    274354    };
    275355
     
    281361    g_assert( ALEN( types ) == MC_ROW_COUNT );
    282362    store = gtk_list_store_newv( MC_ROW_COUNT, types );
    283     g_signal_connect( store, "sort-column-changed", G_CALLBACK(onSortColumnChanged), NULL );
    284 
    285     gtk_tree_sortable_set_sort_func( GTK_TREE_SORTABLE(store),
    286                                      MC_PROG_D,
    287                                      compareProgress,
    288                                      NULL, NULL );
    289363
    290364    self->model    = GTK_TREE_MODEL( store );
     
    347421}
    348422
     423static char*
     424doCollate( const char * in )
     425{
     426    const char * end = in + strlen( in );
     427    char * casefold;
     428    char * ret;
     429
     430    while( in < end ) {
     431        const gunichar ch = g_utf8_get_char( in );
     432        if (!g_unichar_isalnum (ch)) // eat everything before the first alnum
     433            in += g_unichar_to_utf8( ch, NULL );
     434        else
     435            break;
     436    }
     437
     438    if ( in == end )
     439        return g_strdup ("");
     440
     441    casefold = g_utf8_casefold( in, end-in );
     442    ret = g_utf8_collate_key( casefold, -1 );
     443    g_free( casefold );
     444    return ret;
     445}
     446
    349447static void
    350448tr_core_insert( TrCore * self, TrTorrent * tor )
    351449{
    352450    const tr_info * inf = tr_torrent_info( tor );
     451    char * collated = doCollate( inf->name );
    353452    GtkTreeIter unused;
    354453    gtk_list_store_insert_with_values( GTK_LIST_STORE( self->model ), &unused, 0,
    355                                        MC_NAME,    inf->name,
    356                                        MC_SIZE,    inf->totalSize,
    357                                        MC_HASH,    inf->hashString,
    358                                        MC_TORRENT, tor,
    359                                        MC_ID,      self->nextid,
     454                                       MC_NAME,          inf->name,
     455                                       MC_NAME_COLLATED, collated,
     456                                       MC_HASH,          inf->hashString,
     457                                       MC_TORRENT,       tor,
     458                                       MC_TORRENT_RAW,   tor->handle,
     459                                       MC_ID,            self->nextid,
    360460                                       -1);
     461    self->nextid++;
    361462    g_object_unref( tor );
    362     self->nextid++;
     463    g_free( collated );
    363464}
    364465
     
    533634{
    534635    TrTorrent * tor;
    535     const tr_stat * st;
    536636
    537637    gtk_tree_model_get( model, iter, MC_TORRENT, &tor, -1 );
    538     st = tr_torrent_stat( tor );
    539638    tr_torrent_check_seeding_cap ( tor );
    540639    g_object_unref( tor );
    541 
    542     gtk_list_store_set( GTK_LIST_STORE( model ), iter,
    543                         MC_STAT,        st->status,
    544                         MC_ERR,         st->error,
    545                         MC_TERR,        st->errorString,
    546                         MC_PROG_C,      st->percentComplete,
    547                         MC_PROG_D,      st->percentDone,
    548                         MC_DRATE,       st->rateDownload,
    549                         MC_URATE,       st->rateUpload,
    550                         MC_ETA,         st->eta,
    551                         MC_PEERS,       st->peersConnected,
    552                         MC_UPEERS,      st->peersGettingFromUs,
    553                         MC_DPEERS,      st->peersSendingToUs,
    554                         MC_SEED,        st->seeders,
    555                         MC_LEECH,       st->leechers,
    556                         MC_DONE,        st->completedFromTracker,
    557                         MC_DOWN,        st->downloadedEver,
    558                         MC_UP,          st->uploadedEver,
    559                         MC_RATIO,       st->ratio,
    560                         MC_LEFT,        st->leftUntilDone,
    561                         -1 );
    562640
    563641    return FALSE;
     
    629707}
    630708
     709gboolean
     710tr_core_toggle_pref_bool( TrCore * core, const char * key )
     711{
     712    const gboolean newval = !pref_flag_get( key );
     713    pref_flag_set( key, newval );
     714    commitPrefsChange( core, key );
     715    return newval;
     716}
     717
    631718void
    632719tr_core_set_pref_int( TrCore * self, const char * key, int newval )
  • trunk/gtk/tr_core.h

    r3821 r4210  
    163163tr_core_set_pref( TrCore * self, const char * key, const char * val );
    164164
     165gboolean
     166tr_core_toggle_pref_bool( TrCore * core, const char * key );
    165167/* Set a boolean preference value, save the prefs file, and emit the
    166168   "prefs-changed" signal */
     
    174176
    175177void
    176 tr_core_set_sort_column_from_prefs( TrCore * core );
     178tr_core_resort( TrCore * core );
    177179
    178180/* column names for the model used to store torrent information */
    179181/* keep this in sync with the type array in tr_core_init() in tr_core.c */
    180 enum {
    181   MC_NAME, MC_SIZE, MC_HASH, MC_STAT, MC_ERR, MC_TERR,
    182   MC_PROG_C, MC_PROG_D, MC_DRATE, MC_URATE, MC_ETA, MC_PEERS,
    183   MC_UPEERS, MC_DPEERS, MC_SEED, MC_LEECH, MC_DONE,
    184   MC_DOWN, MC_UP, MC_RATIO, MC_LEFT, MC_TORRENT, MC_ID,
    185   MC_ROW_COUNT
     182enum
     183{
     184    MC_NAME,
     185    MC_NAME_COLLATED,
     186    MC_HASH,
     187    MC_TORRENT,
     188    MC_TORRENT_RAW,
     189    MC_ID,
     190    MC_ROW_COUNT
    186191};
    187192
  • trunk/gtk/tr_prefs.c

    r4180 r4210  
    5151    pref_int_set_default    ( PREF_KEY_MSGLEVEL, TR_MSG_INF );
    5252
    53     pref_string_set_default ( PREF_KEY_SORT_COLUMN, "name" );
     53    pref_string_set_default ( PREF_KEY_SORT_MODE, "sort-by-name" );
     54    pref_flag_set_default   ( PREF_KEY_SORT_REVERSED, FALSE );
     55    pref_flag_set_default   ( PREF_KEY_MINIMAL_VIEW, FALSE );
    5456
    5557    pref_save( NULL );
     
    220222    snprintf( url, sizeof(url), "http://transmission.m0k.org/PortCheck.php?port=%d", port );
    221223    text = miniwget( url, &size );
    222     g_message(" got len %d, [%*.*s]", size, size, size, text );
     224    /*g_message(" got len %d, [%*.*s]", size, size, size, text );*/
    223225    isOpen = text && *text=='1';
    224226    gtk_label_set_markup( GTK_LABEL(l), isOpen ? _("Port is <b>open</b>") : _("Port is <b>closed</b>") );
  • trunk/gtk/tr_prefs.h

    r3449 r4210  
    3636#define PREF_KEY_ENCRYPTED_ONLY    "encrypted-connections-only"
    3737#define PREF_KEY_MSGLEVEL          "debug-message-level"
    38 #define PREF_KEY_SORT_COLUMN       "sort-column"
     38#define PREF_KEY_SORT_MODE         "sort-mode"
     39#define PREF_KEY_SORT_REVERSED     "sort-reversed"
     40#define PREF_KEY_MINIMAL_VIEW      "minimal-view"
    3941
    4042void tr_prefs_init_global( void );
  • trunk/gtk/tr_torrent.c

    r3870 r4210  
    4646
    4747  self->handle = NULL;
    48   self->lastStatTime = 0;
    4948  self->delfile = NULL;
    5049  self->severed = FALSE;
     
    131130refreshStat( TrTorrent * tor )
    132131{
    133     tor->lastStatTime= time( NULL );
    134     tor->stat = *tr_torrentStat( tor->handle );
    135     return &tor->stat;
    136132}
    137133
     
    141137    g_assert( TR_IS_TORRENT(tor) );
    142138
    143     if( !tor->severed && tor->lastStatTime!=time(NULL) )
    144         refreshStat( tor );
    145 
    146     return &tor->stat;
     139    return tor->severed ? NULL : tr_torrentStat( tor->handle );
    147140}
    148141
  • trunk/gtk/tr_torrent.h

    r3381 r4210  
    5151  tr_torrent *handle;
    5252  char *delfile;
    53   tr_stat stat;
    54   time_t lastStatTime;
    5553
    5654  /* FIXME: hm, are these heavyweight enough to deserve their own properties? */
  • trunk/gtk/tr_window.c

    r3993 r4210  
    3232#include "actions.h"
    3333#include "hig.h"
    34 #include "tr_cell_renderer_progress.h"
     34#include "torrent-cell-renderer.h"
    3535#include "tr_core.h"
    3636#include "tr_torrent.h"
     
    4646    GtkWidget * dl_lb;
    4747    GtkTreeSelection * selection;
    48     GtkCellRenderer * namerend;
    4948}
    5049PrivateData;
     
    6160****
    6261***/
    63 
    64 static void
    65 formatname( GtkTreeViewColumn * col UNUSED, GtkCellRenderer * rend,
    66             GtkTreeModel * model, GtkTreeIter * iter, gpointer data UNUSED )
    67 {
    68     TrTorrent * gtor;
    69     char  * name, * mb, * str, * top, * bottom;
    70     const char * fmt;
    71     guint64 size;
    72     int     status, err, eta, tpeers, upeers, dpeers;
    73 
    74     gtk_tree_model_get( model, iter, MC_NAME, &name, MC_STAT, &status,
    75                         MC_ERR, &err, MC_SIZE, &size,
    76                         MC_ETA, &eta, MC_PEERS, &tpeers, MC_UPEERS, &upeers,
    77                         MC_DPEERS, &dpeers, MC_TORRENT, &gtor, -1 );
    78 
    79     tpeers = MAX( tpeers, 0 );
    80     upeers = MAX( upeers, 0 );
    81     dpeers = MAX( dpeers, 0 );
    82     mb = readablesize(size);
    83 
    84     top = tr_torrent_status_str ( gtor );
    85 
    86     if( TR_OK != err )
    87     {
    88         char * terr;
    89         gtk_tree_model_get( model, iter, MC_TERR, &terr, -1 );
    90         bottom = g_strconcat( _("Error"), ": ", terr, NULL );
    91         g_free( terr );
    92     }
    93     else if( TR_STATUS_DOWNLOAD & status )
    94     {
    95         bottom = g_strdup_printf( ngettext( "Downloading from %i of %i connections",
    96                                             "Downloading from %i of %i connections",
    97                                             tpeers ), dpeers, tpeers );
    98     }
    99     else
    100     {
    101         bottom = NULL;
    102     }
    103 
    104     fmt = err==TR_OK
    105         ? "<b>%s (%s)</b>\n<small>%s\n%s</small>"
    106         : "<span color='red'><b>%s (%s)</b>\n<small>%s\n%s</small></span>";
    107     str = g_markup_printf_escaped( fmt, name, mb, top, (bottom ? bottom : "") );
    108     g_object_set( rend, "markup", str, NULL );
    109     g_free( name );
    110     g_free( mb );
    111     g_free( str );
    112     g_free( top );
    113     g_free( bottom );
    114     g_object_unref( gtor );
    115 }
    116 
    117 static void
    118 formatprog( GtkTreeViewColumn * col UNUSED, GtkCellRenderer * rend,
    119             GtkTreeModel * model, GtkTreeIter * iter, gpointer data UNUSED )
    120 {
    121     char  * dlstr, * ulstr, * str, * marked;
    122     gfloat  prog, dl, ul, ratio;
    123     guint64 down, up;
    124 
    125     gtk_tree_model_get( model, iter, MC_PROG_D, &prog, MC_DRATE, &dl,
    126                         MC_URATE, &ul, MC_DOWN, &down, MC_UP, &up, MC_RATIO, &ratio, -1 );
    127     prog = MAX( prog, 0.0 );
    128     prog = MIN( prog, 1.0 );
    129 
    130     ulstr = readablespeed (ul);
    131     if( 1.0 == prog )
    132     {
    133         dlstr = g_strdup_printf( "%.1f", ratio );
    134         str = g_strdup_printf( _("Ratio: %s\nUL: %s"), dlstr, ulstr );
    135     }
    136     else
    137     {
    138         dlstr = readablespeed( dl );
    139         str = g_strdup_printf( _("DL: %s\nUL: %s"), dlstr, ulstr );
    140     }
    141     marked = g_markup_printf_escaped( "<small>%s</small>", str );
    142     g_object_set( rend, "markup", str, "progress", prog, NULL );
    143     g_free( dlstr );
    144     g_free( ulstr );
    145     g_free( str );
    146     g_free( marked );
    147 }
    14862
    14963static void
     
    17185    GtkTreeViewColumn * col;
    17286    GtkTreeSelection  * sel;
    173     GtkCellRenderer   * namerend, * progrend;
    174     char              * str;
     87    GtkCellRenderer   * r;
    17588
    17689    view = gtk_tree_view_new();
     90    gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(view), FALSE );
    17791
    17892    p->selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(view) );
    179     namerend = gtk_cell_renderer_text_new();
    180     p->namerend = namerend;
    181     /* note that this renderer is set to ellipsize, just not here */
    182     col = gtk_tree_view_column_new_with_attributes( _("Name"), namerend,
    183                                                     NULL );
    184     gtk_tree_view_column_set_cell_data_func( col, namerend, formatname,
    185                                              NULL, NULL );
    186     gtk_tree_view_column_set_expand( col, TRUE );
     93
     94    r = torrent_cell_renderer_new( );
     95    col = gtk_tree_view_column_new_with_attributes( _("Torrent"), r, "torrent", MC_TORRENT_RAW, NULL );
    18796    gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_AUTOSIZE );
    188     gtk_tree_view_column_set_sort_column_id( col, MC_NAME );
    18997    gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
    190 
    191     progrend = tr_cell_renderer_progress_new();
    192     /* this string is only used to determine the size of the progress bar */
    193     str = g_markup_printf_escaped( "<big>%s</big>", "  fnord    fnord  " );
    194     g_object_set( progrend, "bar-sizing", str, NULL );
    195     g_free(str);
    196     col = gtk_tree_view_column_new_with_attributes( _("Progress"), progrend,
    197                                                     NULL);
    198     gtk_tree_view_column_set_cell_data_func( col, progrend, formatprog,
    199                                              NULL, NULL );
    200     gtk_tree_view_column_set_sizing( col, GTK_TREE_VIEW_COLUMN_AUTOSIZE );
    201     gtk_tree_view_column_set_sort_column_id( col, MC_PROG_D );
    202     gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
     98    g_object_set( r, "xpad", GUI_PAD_SMALL, "ypad", GUI_PAD_SMALL, NULL );
    20399
    204100    gtk_tree_view_set_rules_hint( GTK_TREE_VIEW( view ), TRUE );
     
    223119    sizingmagic( GTK_WINDOW(wind), GTK_SCROLLED_WINDOW( p->scroll ),
    224120                 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS );
    225     g_object_set( p->namerend, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
    226121}
    227122
     
    290185{
    291186    PrivateData * p = get_private_data( self );
    292     char *tmp1, *tmp2;
    293 
    294     tmp1 = readablespeed( downspeed );
    295     tmp2 = g_strdup_printf( _("Total DL: %s"), tmp1 );
    296     gtk_label_set_text( GTK_LABEL(p->dl_lb), tmp2 );
    297     g_free( tmp2 );
    298     g_free( tmp1 );
    299 
    300     tmp1 = readablespeed( upspeed );
    301     tmp2 = g_strdup_printf( _("Total UL: %s"), tmp1 );
    302     gtk_label_set_text( GTK_LABEL(p->ul_lb), tmp2 );
    303     g_free( tmp2 );
    304     g_free( tmp1 );
     187    char speedStr[64];
     188    char buf[128];
     189
     190    tr_strlspeed( speedStr, downspeed, sizeof(speedStr) );
     191    g_snprintf( buf, sizeof(buf), _("Total DL: %s"), speedStr );
     192    gtk_label_set_text( GTK_LABEL(p->dl_lb), buf );
     193
     194    tr_strlspeed( speedStr, upspeed, sizeof(speedStr) );
     195    g_snprintf( buf, sizeof(buf), _("Total UL: %s"), speedStr );
     196    gtk_label_set_text( GTK_LABEL(p->ul_lb), buf );
    305197}
    306198
  • trunk/gtk/ui.h

    r3993 r4210  
    99"      <menuitem action='verify-torrent'/>\n"
    1010"      <menuitem action='remove-torrent'/>\n"
    11 "      <menuitem action='show-torrent-details'/>\n"
    1211"      <separator/>\n"
    1312"      <menuitem action='create-torrent'/>\n"
     
    1514"      <menuitem action='close'/>\n"
    1615"      <menuitem action='quit'/>\n"
     16"    </menu>\n"
     17"    <menu action='view-menu'>\n"
     18"      <menuitem action='show-torrent-details'/>\n"
     19"      <separator/>\n"
     20"      <menuitem action='minimal-view'/>\n"
     21"      <separator/>\n"
     22"      <menuitem action='sort-by-activity'/>\n"
     23"      <menuitem action='sort-by-name'/>\n"
     24"      <menuitem action='sort-by-progress'/>\n"
     25"      <menuitem action='sort-by-state'/>\n"
     26"      <menuitem action='sort-by-tracker'/>\n"
     27"      <menuitem action='reverse-sort-order'/>\n"
    1728"    </menu>\n"
    1829"    <menu action='edit-menu'>\n"
  • trunk/gtk/util.c

    r3821 r4210  
    3939#include "util.h"
    4040
    41 #define BESTDECIMAL(d) ( (d)<100 ? 1 : 0 )
    42 
    4341static void
    4442errcb(GtkWidget *wind, int resp, gpointer data);
     
    5351}
    5452
    55 static const char *sizestrs[] = {
    56   N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB"), N_("PiB"), N_("EiB"),
    57 };
    58 
    59 char *
    60 readablesize(guint64 size) {
    61   int ii;
    62   double small = size;
    63 
    64   if( !size )
    65     return g_strdup_printf( _("None") );
    66 
    67   for(ii = 0; ii + 1 < ALEN(sizestrs) && 1024.0 <= small / 1024.0; ii++)
    68     small /= 1024.0;
    69 
    70   if(1024.0 <= small) {
    71     small /= 1024.0;
    72     ii++;
    73   }
    74 
    75   return g_strdup_printf("%.*f %s", BESTDECIMAL(small), small,
    76                          gettext(sizestrs[ii]));
    77 }
    78 
    79 char *
    80 readablespeed (double KiBps)
    81 {
    82   const guint64 bps = KiBps * 1024;
    83   char * str = readablesize (bps);
    84   char * ret = bps ? g_strdup_printf ("%s/s", str) : g_strdup( str );
    85   g_free (str);
    86   return ret;
    87 }
    88  
     53char*
     54tr_strlsize( char * buf, guint64 size, size_t buflen )
     55{
     56    if( !size )
     57        g_strlcpy( buf, _("None"), buflen );
     58    else {
     59        static const char *units[] = {
     60            N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB"),
     61            N_("PiB"), N_("EiB"), N_("ZiB"), N_("YiB")
     62        };
     63        unsigned int i;
     64        guint64 small = size;
     65        for( i=0; i<G_N_ELEMENTS(units) && small>=1024; ++i )
     66            small >>= 10;
     67        if( small < 100 )
     68            g_snprintf( buf, buflen, "%.1f %s", (double)small, _(units[i]) );
     69        else
     70            g_snprintf( buf, buflen, "%d %s", (int)small, _(units[i]) );
     71    }
     72    return buf;
     73}
     74
     75char*
     76tr_strlspeed( char * buf, double KiBps, size_t buflen )
     77{
     78    const guint64 bps = KiBps * 1024;
     79    if( !bps )
     80        g_strlcpy( buf, _("None"), buflen );
     81    else {
     82        char bbuf[64];
     83        tr_strlsize( bbuf, (guint64)(KiBps*1024), sizeof(bbuf) );
     84        g_snprintf( buf, buflen, "%s/s", bbuf );
     85    }
     86    return buf;
     87}
    8988
    9089#define SECONDS(s)              ((s) % 60)
  • trunk/gtk/util.h

    r3821 r4210  
    4545typedef void (*callbackfunc_t)(void*);
    4646
    47 /* return a human-readable string for the size given in bytes.
    48    the string must be g_free()d */
    49 char *
    50 readablesize(guint64 size);
     47/* return a human-readable string for the size given in bytes. */
     48char* tr_strlsize( char * buf, guint64 size, size_t buflen );
    5149
    52 /* return a human-readable string for the transfer rate given in bytes.
    53    the string must be g_free()d */
    54 char *
    55 readablespeed (double KiBps);
    56 
     50/* return a human-readable string for the transfer rate given in bytes. */
     51char* tr_strlspeed (char * buf, double KiBps, size_t buflen );
    5752
    5853/* return a human-readable string for the time given in seconds.
Note: See TracChangeset for help on using the changeset viewer.