Changeset 5967


Ignore:
Timestamp:
May 29, 2008, 2:59:22 AM (14 years ago)
Author:
charles
Message:

(gtk)
#978: Details window hangs when changing priority
#946: Allow to select several files in the file chooser

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/file-list.c

    r5549 r5967  
    3030
    3131#include <libtransmission/transmission.h>
     32#include <libtransmission/utils.h> /* tr_getRatio */
    3233
    3334#include "file-list.h"
    3435#include "hig.h"
     36
     37enum
     38{
     39    SUB_STATE_HIGH          = (1<<0),
     40    SUB_STATE_NORMAL        = (1<<1),
     41    SUB_STATE_LOW           = (1<<2),
     42    SUB_STATE_PRIORITY_MASK = (SUB_STATE_HIGH|SUB_STATE_NORMAL|SUB_STATE_LOW),
     43    SUB_STATE_DOWNLOAD      = (1<<4),
     44    SUB_STATE_IGNORE        = (1<<5),
     45    SUB_STATE_DOWNLOAD_MASK = (SUB_STATE_DOWNLOAD|SUB_STATE_IGNORE)
     46};
    3547
    3648enum
     
    4254  FC_INDEX,
    4355  FC_SIZE,
     56  FC_HAVE,
    4457  FC_PRIORITY,
    4558  FC_ENABLED,
     59  FC_IS_FILE,
     60  FC_SUB_SIZE,
     61  FC_SUB_HAVE,
     62  FC_SUB_STATE,
    4663  N_FILE_COLS
    4764};
     
    5471  GtkTreeModel * model; /* same object as store, but recast */
    5572  GtkTreeStore * store; /* same object as model, but recast */
     73  tr_file_stat * refresh_file_stat;
    5674  guint timeout_tag;
    5775}
    5876FileData;
    5977
    60 static const char*
    61 priorityToString( const int priority )
    62 {
    63     switch( priority ) {
    64         /* this refers to priority */
    65         case TR_PRI_HIGH:   return _("High");
    66         /* this refers to priority */
    67         case TR_PRI_NORMAL: return _("Normal");
    68         /* this refers to priority */
    69         case TR_PRI_LOW:    return _("Low");
    70         default:            return "BUG!";
    71     }
    72 }
    73 
    74 static tr_priority_t
    75 stringToPriority( const char* str )
    76 {
    77     if( !strcmp( str, priorityToString( TR_PRI_HIGH ) ) ) return TR_PRI_HIGH;
    78     if( !strcmp( str, priorityToString( TR_PRI_LOW ) ) ) return TR_PRI_LOW;
    79     return TR_PRI_NORMAL;
    80 }
     78static void
     79clearData( FileData * data )
     80{
     81    data->gtor = NULL;
     82
     83    if( data->timeout_tag ) {
     84        g_source_remove( data->timeout_tag );
     85        data->timeout_tag = 0;
     86    }
     87}
     88
     89static void
     90freeData( gpointer gdata )
     91{
     92    FileData * data = gdata;
     93    clearData( data );
     94    g_free( data );
     95}
     96
     97/***
     98****
     99***/
    81100
    82101static void
     
    85104           GtkTreeIter       * ret,
    86105           const char        * path,
    87            int                 index,
     106           tr_file_index_t     index,
    88107           uint64_t            size )
    89108{
     
    94113    int            priority = 0;
    95114    gboolean       enabled = TRUE;
     115    gboolean       is_file;
    96116
    97117    model  = GTK_TREE_MODEL( store );
     
    120140
    121141    gtk_tree_store_append( store, &iter, parent );
    122     if( NULL == ret )
     142    if(( is_file = !ret ))
    123143    {
    124144        stock = GTK_STOCK_FILE;
     145        priority = tr_torrentGetFilePriority( tor, index );
     146        enabled  = tr_torrentGetFileDL( tor, index );
    125147    }
    126148    else
     
    128150        stock = GTK_STOCK_DIRECTORY;
    129151        size  = 0;
    130         index = -1;
    131     }
    132 
    133     if (index != -1) {
    134         priority = tr_torrentGetFilePriority( tor, index );
    135         enabled  = tr_torrentGetFileDL( tor, index );
    136152    }
    137153
     
    140156                                      FC_KEY, mykey,
    141157                                      FC_STOCK, stock,
    142                                       FC_PRIORITY, priorityToString(priority),
     158                                      FC_PRIORITY, priority,
    143159                                      FC_ENABLED, enabled,
    144                                       FC_SIZE, size, -1 );
     160                                      FC_IS_FILE, is_file,
     161                                      FC_SIZE, size,
     162                                      FC_HAVE, 0,
     163                                      -1 );
    145164  done:
    146165    g_free( mykey );
     
    151170}
    152171
    153 static uint64_t
    154 getdirtotals( GtkTreeStore * store, GtkTreeIter * parent )
    155 {
    156     GtkTreeModel * model;
    157     GtkTreeIter    iter;
    158     uint64_t       mysize, subsize;
    159     char         * name, * label;
    160 
    161     model  = GTK_TREE_MODEL( store );
    162     mysize = 0;
    163     if( gtk_tree_model_iter_children( model, &iter, parent ) ) do
    164     {
    165          char sizeStr[64];
    166         if( gtk_tree_model_iter_has_child( model, &iter ) )
     172
     173/***
     174****
     175***/
     176
     177static gboolean
     178refreshFilesForeach( GtkTreeModel  * model,
     179                     GtkTreePath   * path UNUSED,
     180                     GtkTreeIter   * iter,
     181                     gpointer        gdata )
     182{
     183    FileData * data = gdata;
     184    gboolean is_file;
     185    unsigned int index;
     186    gtk_tree_model_get( model, iter, FC_IS_FILE, &is_file, FC_INDEX, &index, -1  );
     187    if( is_file ) {
     188        GtkTreeStore * store = GTK_TREE_STORE( model );
     189        tr_torrent * tor = tr_torrent_handle( data->gtor );
     190        int download = tr_torrentGetFileDL( tor, index );
     191        int priority = tr_torrentGetFilePriority( tor, index );
     192        uint64_t have = data->refresh_file_stat[index].bytesCompleted;
     193        gtk_tree_store_set( store, iter, FC_PRIORITY, priority,
     194                                         FC_ENABLED, download,
     195                                         FC_HAVE, have,
     196                                         -1 );
     197    }
     198    return FALSE; /* keep walking */
     199}
     200
     201static gboolean
     202resetSubForeach( GtkTreeModel  * model,
     203                 GtkTreePath   * path UNUSED,
     204                 GtkTreeIter   * iter,
     205                 gpointer        gdata UNUSED )
     206{
     207    // set the subs to the lowest values...
     208    gtk_tree_store_set( GTK_TREE_STORE( model ), iter,
     209                        FC_SUB_STATE, 0,
     210                        FC_SUB_SIZE, (uint64_t)0,
     211                        FC_SUB_HAVE, (uint64_t)0,
     212                        -1 );
     213    return FALSE; /* keep walking */
     214}
     215
     216static gboolean
     217addSubForeach( GtkTreeModel  * model,
     218               GtkTreePath   * path UNUSED,
     219               GtkTreeIter   * iter,
     220               gpointer        gdata UNUSED )
     221{
     222    uint64_t size;
     223    uint64_t have;
     224    int priority;
     225    gboolean enabled;
     226    gboolean is_file;
     227    gtk_tree_model_get( model, iter, FC_SIZE, &size,
     228                                     FC_HAVE, &have,
     229                                     FC_PRIORITY, &priority,
     230                                     FC_ENABLED, &enabled,
     231                                     FC_IS_FILE, &is_file,
     232                                     -1 );
     233    if( is_file )
     234    {
     235        GtkTreeIter child = *iter;
     236        GtkTreeIter parent;
     237        while(( gtk_tree_model_iter_parent( model, &parent, &child )))
    167238        {
    168             subsize = getdirtotals( store, &iter );
    169             gtk_tree_store_set( store, &iter, FC_SIZE, subsize, -1 );
     239            uint64_t sub_size;
     240            uint64_t sub_have;
     241            int sub_state;
     242            gtk_tree_model_get( model, &parent, FC_SUB_SIZE, &sub_size,
     243                                                FC_SUB_HAVE, &sub_have,
     244                                                FC_SUB_STATE, &sub_state,
     245                                                -1 );
     246            sub_have += have;
     247            sub_size += size;
     248            switch( priority ) {
     249                case TR_PRI_HIGH:   sub_state |= SUB_STATE_HIGH;   break;
     250                case TR_PRI_NORMAL: sub_state |= SUB_STATE_NORMAL; break;
     251                case TR_PRI_LOW:    sub_state |= SUB_STATE_LOW;    break;
     252            }
     253            sub_state |= ( enabled ? SUB_STATE_DOWNLOAD : SUB_STATE_IGNORE );
     254            gtk_tree_store_set( GTK_TREE_STORE( model ), &parent,
     255                                FC_SUB_SIZE, sub_size,
     256                                FC_SUB_HAVE, sub_have,
     257                                FC_SUB_STATE, sub_state,
     258                                -1 );
     259            child = parent;
    170260        }
    171         else
    172         {
    173             gtk_tree_model_get( model, &iter, FC_SIZE, &subsize, -1 );
     261    }
     262    return FALSE; /* keep walking */
     263}
     264
     265static void
     266refresh( FileData * data )
     267{
     268    tr_file_index_t fileCount;
     269    tr_torrent * tor = tr_torrent_handle( data->gtor );
     270    data->refresh_file_stat = tr_torrentFiles( tor, &fileCount );
     271
     272    gtk_tree_model_foreach( data->model, refreshFilesForeach, data );
     273    gtk_tree_model_foreach( data->model, resetSubForeach, data );
     274    gtk_tree_model_foreach( data->model, addSubForeach, data );
     275
     276    tr_torrentFilesFree( data->refresh_file_stat, fileCount );
     277    data->refresh_file_stat = NULL;
     278}
     279
     280static gboolean
     281refreshModel( gpointer file_data )
     282{
     283    refresh( file_data );
     284    return TRUE;
     285}
     286
     287/***
     288****
     289***/
     290
     291struct ActiveData
     292{
     293    GtkTreeSelection * sel;
     294    GArray * array;
     295};
     296
     297static gboolean
     298getActiveFilesForeach( GtkTreeModel  * model,
     299                       GtkTreePath   * path UNUSED,
     300                       GtkTreeIter   * iter,
     301                       gpointer        gdata )
     302{
     303    struct ActiveData * data = gdata;
     304    unsigned int i;
     305    gboolean is_file = FALSE;
     306    gboolean is_active = FALSE;
     307
     308    /* active == if it's selected, or any ancestor is selected */
     309    gtk_tree_model_get( model, iter, FC_IS_FILE, &is_file, FC_INDEX, &i, -1 );
     310    if( is_file ) {
     311        is_active = gtk_tree_selection_iter_is_selected( data->sel, iter );
     312        if( !is_active ) {
     313            GtkTreeIter walk = *iter;
     314            GtkTreeIter parent;
     315            while( !is_active && gtk_tree_model_iter_parent( model, &parent, &walk )) {
     316                is_active = gtk_tree_selection_iter_is_selected( data->sel, &parent );
     317                walk = parent;
     318            }
    174319        }
    175         gtk_tree_model_get( model, &iter, FC_LABEL, &name, -1 );
    176         tr_strlsize( sizeStr, subsize, sizeof( sizeStr ) );
    177         label = g_markup_printf_escaped( "<small>%s (%s)</small>",
    178                                           name, sizeStr );
    179         g_free( name );
    180         gtk_tree_store_set( store, &iter, FC_LABEL, label, -1 );
    181         g_free( label );
    182         mysize += subsize;
    183     }
    184     while( gtk_tree_model_iter_next( model, &iter ) );
    185 
    186     return mysize;
    187 }
    188 
    189 static void
    190 updateprogress( GtkTreeModel   * model,
    191                 GtkTreeStore   * store,
    192                 GtkTreeIter    * parent,
    193                 tr_file_stat   * fileStats,
    194                 guint64        * setmeGotSize,
    195                 guint64        * setmeTotalSize)
    196 {
    197     GtkTreeIter iter;
    198     guint64 gotSize=0, totalSize=0;
    199 
    200     if( gtk_tree_model_iter_children( model, &iter, parent ) ) do
    201     {
    202         int oldProg, newProg;
    203         guint64 subGot, subTotal;
    204 
    205         if (gtk_tree_model_iter_has_child( model, &iter ) )
    206         {
    207             updateprogress( model, store, &iter, fileStats, &subGot, &subTotal);
    208         }
    209         else
    210         {
    211             int index, percent;
    212             gtk_tree_model_get( model, &iter, FC_SIZE, &subTotal,
    213                                               FC_INDEX, &index,
    214                                               -1 );
    215             g_assert( 0 <= index );
    216             percent = (int)(fileStats[index].progress * 100.0); /* [0...100] */
    217             subGot = (guint64)(subTotal * percent/100.0);
    218         }
    219 
    220         if (!subTotal) subTotal = 1; /* avoid div by zero */
    221         g_assert (subGot <= subTotal);
    222 
    223         /* why not just set it every time?
    224            because that causes the "priorities" combobox to pop down */
    225         gtk_tree_model_get (model, &iter, FC_PROG, &oldProg, -1);
    226         newProg = (int)(100.0*subGot/subTotal);
    227         if (oldProg != newProg)
    228           gtk_tree_store_set (store, &iter,
    229                               FC_PROG, (int)(100.0*subGot/subTotal), -1);
    230 
    231         gotSize += subGot;
    232         totalSize += subTotal;
    233     }
    234     while( gtk_tree_model_iter_next( model, &iter ) );
    235 
    236     *setmeGotSize = gotSize;
    237     *setmeTotalSize = totalSize;
    238 }
    239 
    240 static GtkTreeModel*
    241 priority_model_new (void)
    242 {
    243   GtkTreeIter iter;
    244   GtkListStore * store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
    245   gtk_list_store_append (store, &iter);
    246   gtk_list_store_set (store, &iter, 0, priorityToString( TR_PRI_HIGH ), 1, TR_PRI_HIGH, -1);
    247   gtk_list_store_append (store, &iter);
    248   gtk_list_store_set (store, &iter, 0, priorityToString( TR_PRI_NORMAL ), 1, TR_PRI_NORMAL, -1);
    249   gtk_list_store_append (store, &iter);
    250   gtk_list_store_set (store, &iter, 0, priorityToString( TR_PRI_LOW ), 1, TR_PRI_LOW, -1);
    251   return GTK_TREE_MODEL (store);
    252 }
    253 
    254 static void
    255 subtree_walk_dnd( GtkTreeStore   * store,
    256                   GtkTreeIter    * iter,
    257                   tr_torrent     * tor,
    258                   gboolean         enabled,
    259                   GArray         * indices )
    260 {
    261     int index;
    262     GtkTreeIter child;
    263  
    264     /* update this node */
    265     gtk_tree_model_get( GTK_TREE_MODEL(store), iter, FC_INDEX, &index, -1  );
    266     if (index >= 0) {
    267       tr_file_index_t fi = index;
    268       g_array_append_val( indices, fi );
    269     }
    270     gtk_tree_store_set( store, iter, FC_ENABLED, enabled, -1 );
    271 
    272     /* visit the children */
    273     if( gtk_tree_model_iter_children( GTK_TREE_MODEL(store), &child, iter ) ) do
    274       subtree_walk_dnd( store, &child, tor, enabled, indices );
    275     while( gtk_tree_model_iter_next( GTK_TREE_MODEL(store), &child ) );
    276 }
    277 
    278 static void
    279 set_subtree_dnd( GtkTreeStore   * store,
    280                  GtkTreeIter    * iter,
    281                  tr_torrent     * tor,
    282                  gboolean         enabled )
    283 {
    284     GArray * indices = g_array_new( FALSE, FALSE, sizeof(tr_file_index_t) );
    285     subtree_walk_dnd( store, iter, tor, enabled, indices );
    286     tr_torrentSetFileDLs( tor, (tr_file_index_t*)indices->data, (tr_file_index_t)indices->len, enabled );
    287     g_array_free( indices, TRUE );
    288 }
    289 
    290 static void
    291 subtree_walk_priority( GtkTreeStore   * store,
    292                        GtkTreeIter    * iter,
    293                        tr_torrent     * tor,
    294                        int              priority,
    295                        GArray         * indices )
    296 {
    297     int index;
    298     GtkTreeIter child;
    299 
    300     /* update this node */
    301     gtk_tree_model_get( GTK_TREE_MODEL(store), iter, FC_INDEX, &index, -1  );
    302     if( index >= 0 )
    303         g_array_append_val( indices, index );
    304     gtk_tree_store_set( store, iter, FC_PRIORITY, priorityToString(priority), -1 );
    305 
    306     /* visit the children */
    307     if( gtk_tree_model_iter_children( GTK_TREE_MODEL(store), &child, iter ) ) do
    308         subtree_walk_priority( store, &child, tor, priority, indices );
    309     while( gtk_tree_model_iter_next( GTK_TREE_MODEL(store), &child ) );
    310 
    311 }
    312 
    313 static void
    314 set_subtree_priority( GtkTreeStore * store,
    315                       GtkTreeIter * iter,
    316                       tr_torrent * tor,
    317                       int priority )
    318 {
    319     GArray * indices = g_array_new( FALSE, FALSE, sizeof(int) );
    320     subtree_walk_priority( store, iter, tor, priority, indices );
    321     tr_torrentSetFilePriorities( tor, (tr_file_index_t*)indices->data, (tr_file_index_t)indices->len, priority );
    322     g_array_free( indices, TRUE );
    323 }
    324 
    325 static void
    326 priority_changed_cb (GtkCellRendererText * cell UNUSED,
    327                      const gchar         * path,
    328                      const gchar         * value,
    329                      void                * file_data)
    330 {
    331     GtkTreeIter iter;
    332     FileData * d = file_data;
    333     if (gtk_tree_model_get_iter_from_string (d->model, &iter, path))
    334     {
    335         tr_torrent  * tor = tr_torrent_handle( d->gtor );
    336         const tr_priority_t priority = stringToPriority( value );
    337         set_subtree_priority( d->store, &iter, tor, priority );
    338     }
    339 }
    340 
    341 static void
    342 enabled_toggled (GtkCellRendererToggle  * cell UNUSED,
    343                  const gchar            * path_str,
    344                  gpointer                 data_gpointer)
    345 {
    346   FileData * data = data_gpointer;
    347   GtkTreePath * path = gtk_tree_path_new_from_string( path_str );
    348   GtkTreeModel * model = data->model;
    349   GtkTreeIter iter;
    350   gboolean enabled;
    351 
    352   gtk_tree_model_get_iter( model, &iter, path );
    353   gtk_tree_model_get( model, &iter, FC_ENABLED, &enabled, -1 );
    354   enabled = !enabled;
    355   set_subtree_dnd( GTK_TREE_STORE(model),
    356                    &iter,
    357                    tr_torrent_handle( data->gtor ),
    358                    enabled );
    359 
    360   gtk_tree_path_free( path );
    361 }
    362 
    363 static gboolean
    364 refreshModel( gpointer gdata )
    365 {
    366     FileData * data  = gdata;
    367 
    368     g_assert( data != NULL );
    369 
    370     if( data->gtor )
    371     {
    372         guint64 foo, bar;
    373         tr_file_index_t fileCount;
    374         tr_torrent * tor;
    375         tr_file_stat * fileStats;
    376 
    377         tor = tr_torrent_handle( data->gtor );
    378         fileCount = 0;
    379         fileStats = tr_torrentFiles( tor, &fileCount );
    380         updateprogress (data->model, data->store, NULL, fileStats, &foo, &bar);
    381         tr_torrentFilesFree( fileStats, fileCount );
    382     }
    383 
    384     return TRUE;
    385 }
    386 
    387 static void
    388 clearData( FileData * data )
    389 {
    390     data->gtor = NULL;
    391 
    392     if( data->timeout_tag ) {
    393         g_source_remove( data->timeout_tag );
    394         data->timeout_tag = 0;
    395     }
    396 }
     320    }
     321
     322    if( is_active )
     323        g_array_append_val( data->array, i );
     324
     325    return FALSE; /* walk the entire model */
     326}
     327
     328static GArray*
     329getActiveFiles( GtkTreeView * view )
     330{
     331    struct ActiveData data;
     332    data.sel = gtk_tree_view_get_selection( view );
     333    data.array  = g_array_new( FALSE, FALSE, sizeof( tr_file_index_t ) );
     334    gtk_tree_model_foreach( gtk_tree_view_get_model( view ), getActiveFilesForeach, &data );
     335    return data.array;
     336}
     337
     338static void
     339setPriority( FileData * data, int priority )
     340{
     341    GtkTreeView * view = GTK_TREE_VIEW( data->view );
     342    GArray * a = getActiveFiles( view );
     343    tr_torrentSetFilePriorities( tr_torrent_handle( data->gtor ),
     344                                 (tr_file_index_t*)a->data,
     345                                 (tr_file_index_t)a->len,
     346                                 priority );
     347    refresh( data );
     348    g_array_free( a, TRUE );
     349}
     350
     351
     352static void
     353setDownload( FileData * data, int do_download )
     354{
     355    GtkTreeView * view = GTK_TREE_VIEW( data->view );
     356    GArray * a = getActiveFiles( view );
     357    tr_torrentSetFileDLs ( tr_torrent_handle( data->gtor ),
     358                           (tr_file_index_t*)a->data,
     359                           (tr_file_index_t)a->len,
     360                           do_download );
     361    refresh( data );
     362    g_array_free( a, TRUE );
     363}
     364
     365static void
     366onHighClicked( GtkButton * button UNUSED, gpointer gdata )
     367{
     368    setPriority( gdata, TR_PRI_HIGH );
     369}
     370static void
     371onNormalClicked( GtkButton * button UNUSED, gpointer gdata )
     372{
     373    setPriority( gdata, TR_PRI_NORMAL );
     374}
     375static void
     376onLowClicked( GtkButton * button UNUSED, gpointer gdata )
     377{
     378    setPriority( gdata, TR_PRI_LOW );
     379}
     380static void
     381onDownloadClicked( GtkButton * button UNUSED, gpointer gdata )
     382{
     383    setDownload( gdata, TRUE );
     384}
     385static void
     386onIgnoreClicked( GtkButton * button UNUSED, gpointer gdata )
     387{
     388    setDownload( gdata, FALSE );
     389}
     390
     391/***
     392****
     393***/
    397394
    398395void
     
    413410                                 G_TYPE_INT,       /* prog [0..100] */
    414411                                 G_TYPE_STRING,    /* key */
    415                                  G_TYPE_INT,       /* index */
     412                                 G_TYPE_UINT,      /* index */
    416413                                 G_TYPE_UINT64,    /* size */
    417                                  G_TYPE_STRING,    /* priority */
    418                                  G_TYPE_BOOLEAN ); /* dl enabled */
     414                                 G_TYPE_UINT64,    /* have */
     415                                 G_TYPE_INT,       /* priority */
     416                                 G_TYPE_BOOLEAN,   /* dl enabled */
     417                                 G_TYPE_BOOLEAN,   /* is file */
     418                                 G_TYPE_UINT64,    /* sub size */
     419                                 G_TYPE_UINT64,    /* sub have */
     420                                 G_TYPE_INT );     /* sub state */
    419421    data->store = store;
    420422    data->model = GTK_TREE_MODEL( store );
     
    436438        }
    437439
    438         getdirtotals( store, NULL );
    439 
    440         data->timeout_tag = g_timeout_add( 1000, refreshModel, data );
     440        refresh( data );
     441
     442        data->timeout_tag = g_timeout_add( 2500, refreshModel, data );
    441443    }
    442444
     
    445447}
    446448
    447 static void
    448 freeData( gpointer gdata )
    449 {
    450     FileData * data = gdata;
    451     clearData( data );
    452     g_free( data );
     449/***
     450****
     451***/
     452
     453static void
     454renderProgress( GtkTreeViewColumn  * column UNUSED,
     455                GtkCellRenderer    * renderer,
     456                GtkTreeModel       * model,
     457                GtkTreeIter        * iter,
     458                gpointer             data UNUSED)
     459{
     460    gboolean is_file;
     461    uint64_t size, have, subsize, subhave;
     462    double progress;
     463    gtk_tree_model_get( model, iter, FC_SIZE, &size,
     464                                     FC_HAVE, &have,
     465                                     FC_SUB_SIZE, &subsize,
     466                                     FC_SUB_HAVE, &subhave,
     467                                     FC_IS_FILE, &is_file,
     468                                     -1 );
     469    progress = is_file ? tr_getRatio( have, size )
     470                       : tr_getRatio( subhave, subsize );
     471    g_object_set( renderer, "value", (int)(progress*100), NULL );
     472}
     473
     474static void
     475renderFilename( GtkTreeViewColumn  * column UNUSED,
     476                GtkCellRenderer    * renderer,
     477                GtkTreeModel       * model,
     478                GtkTreeIter        * iter,
     479                gpointer             data UNUSED)
     480{
     481    char * filename;
     482    char * str;
     483    int64_t size;
     484    int64_t subsize;
     485    gboolean is_file;
     486    char buf[64];
     487    gtk_tree_model_get( model, iter, FC_LABEL, &filename,
     488                                     FC_SIZE, &size,
     489                                     FC_SUB_SIZE, &subsize,
     490                                     FC_IS_FILE, &is_file,
     491                                     -1 );
     492    tr_strlsize( buf, is_file ? size : subsize, sizeof( buf ) );
     493    str = g_markup_printf_escaped( "<small>%s (%s)</small>",
     494                                   filename, buf );
     495    g_object_set( renderer, "markup", str, NULL );
     496    g_free( str );
     497    g_free( filename );
     498}
     499
     500static void
     501renderDownload( GtkTreeViewColumn  * column UNUSED,
     502                GtkCellRenderer    * renderer,
     503                GtkTreeModel       * model,
     504                GtkTreeIter        * iter,
     505                gpointer             data UNUSED)
     506{
     507    int sub_state;
     508    gboolean enabled;
     509    gboolean is_file = FALSE;
     510    const char * text;
     511
     512    gtk_tree_model_get( model, iter, FC_IS_FILE, &is_file,
     513                                     FC_ENABLED, &enabled,
     514                                     FC_SUB_STATE, &sub_state,
     515                                     -1 );
     516    if( is_file && enabled )
     517        text = _( "Yes" );
     518    else if( is_file )
     519        text = _( "No" );
     520    else switch( sub_state & SUB_STATE_DOWNLOAD_MASK ) {
     521        case SUB_STATE_DOWNLOAD: text = _( "Yes" );   break;
     522        case SUB_STATE_IGNORE:   text = _( "No" );    break;
     523        default:                 text = _( "Mixed" ); break;
     524    }
     525
     526    g_object_set( renderer, "text", text,
     527                            "xalign", (gfloat)0.5,
     528                            "yalign", (gfloat)0.5,
     529                            NULL );
     530}
     531
     532static void
     533renderPriority( GtkTreeViewColumn  * column UNUSED,
     534                GtkCellRenderer    * renderer,
     535                GtkTreeModel       * model,
     536                GtkTreeIter        * iter,
     537                gpointer             data UNUSED)
     538{
     539    int priority;
     540    int sub_state;
     541    gboolean is_file = FALSE;
     542    const char * text = "";
     543    gtk_tree_model_get( model, iter, FC_IS_FILE, &is_file,
     544                                     FC_PRIORITY, &priority,
     545                                     FC_SUB_STATE, &sub_state,
     546                                     -1 );
     547    if( !is_file )
     548    {
     549        switch( sub_state & SUB_STATE_PRIORITY_MASK )
     550        {
     551            case SUB_STATE_HIGH:   priority = TR_PRI_HIGH;   break;
     552            case SUB_STATE_NORMAL: priority = TR_PRI_NORMAL; break;
     553            case SUB_STATE_LOW:    priority = TR_PRI_LOW;    break;
     554            default:               priority = 666;           break;
     555        }
     556    }
     557
     558    switch( priority )
     559    {
     560        case TR_PRI_HIGH: text = _( "High" );
     561                          break;
     562        case TR_PRI_NORMAL: text = _( "Normal" );
     563                            break;
     564        case TR_PRI_LOW: text = _( "Low" );
     565                         break;
     566        default: text = _( "Mixed" );
     567                 break;
     568    }
     569
     570    g_object_set( renderer, "text", text,
     571                            "xalign", (gfloat)0.5,
     572                            "yalign", (gfloat)0.5,
     573                            NULL );
    453574}
    454575
     
    460581    GtkWidget           * view, * scroll;
    461582    GtkCellRenderer     * rend;
    462     GtkCellRenderer     * priority_rend;
    463     GtkCellRenderer     * enabled_rend;
    464583    GtkTreeViewColumn   * col;
    465584    GtkTreeSelection    * sel;
    466     GtkTreeModel        * model;
     585    GtkWidget           * hbox;
     586    GtkWidget           * vbox;
     587    GtkWidget           * w;
    467588
    468589    /* create the view */
     
    470591    gtk_tree_view_set_rules_hint( GTK_TREE_VIEW( view ), TRUE );
    471592    gtk_container_set_border_width( GTK_CONTAINER( view ), GUI_PAD_BIG );
     593
     594    /* set up view */
     595    sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) );
     596    gtk_tree_selection_set_mode( sel, GTK_SELECTION_MULTIPLE );
     597    gtk_tree_view_expand_all( GTK_TREE_VIEW( view ) );
     598    gtk_tree_view_set_search_column( GTK_TREE_VIEW( view ), FC_LABEL );
    472599
    473600    /* add file column */
     
    486613    g_object_set( rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL );
    487614    gtk_tree_view_column_pack_start( col, rend, TRUE );
    488     gtk_tree_view_column_add_attribute( col, rend, "markup", FC_LABEL );
     615    gtk_tree_view_column_set_cell_data_func( col, rend, renderFilename, NULL, NULL);
    489616    gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
    490     /* add progress column */
    491     rend = gtk_cell_renderer_progress_new();
     617
     618
     619    rend = gtk_cell_renderer_progress_new( );
    492620    /* Translators: this is a column header in Files tab, Details dialog;
    493621       Don't include the prefix "filedetails|" in the translation. */
    494     col = gtk_tree_view_column_new_with_attributes (Q_("filedetails|Progress"),
    495                                                     rend,
    496                                                     "value", FC_PROG,
    497                                                     NULL);
    498     gtk_tree_view_column_set_sort_column_id( col, FC_PROG );
    499     gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
    500     /* set up view */
    501     sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) );
    502     gtk_tree_view_expand_all( GTK_TREE_VIEW( view ) );
    503     gtk_tree_view_set_search_column( GTK_TREE_VIEW( view ), FC_LABEL );
    504 
    505     /* add "download" checkbox column */
    506     col = gtk_tree_view_column_new ();
    507     gtk_tree_view_column_set_sort_column_id( col, FC_ENABLED );
    508     rend = enabled_rend = gtk_cell_renderer_toggle_new  ();
     622    col = gtk_tree_view_column_new_with_attributes( Q_("filedetails|Progress"), rend, NULL );
     623    gtk_tree_view_column_set_cell_data_func( col, rend, renderProgress, NULL, NULL);
     624    gtk_tree_view_append_column ( GTK_TREE_VIEW( view ), col);
     625
     626    /* add "enabled" column */
     627    rend = gtk_cell_renderer_text_new( );
    509628    /* Translators: this is a column header in Files tab, Details dialog;
    510629       Don't include the prefix "filedetails|" in the translation.
    511        Please note the items for this column are checkboxes (yes/no) */
    512     col = gtk_tree_view_column_new_with_attributes (Q_("filedetails|Download"),
    513                                                     rend,
    514                                                     "active", FC_ENABLED,
    515                                                     NULL);
    516     gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
     630       The items for this column are checkboxes (yes/no) */
     631    col = gtk_tree_view_column_new_with_attributes( Q_( "filedetails|Download" ), rend, NULL );
     632    gtk_tree_view_column_set_cell_data_func( col, rend, renderDownload, NULL, NULL);
     633    gtk_tree_view_append_column ( GTK_TREE_VIEW( view ), col);
    517634
    518635    /* add priority column */
    519     model = priority_model_new ();
    520     col = gtk_tree_view_column_new ();
    521     gtk_tree_view_column_set_sort_column_id( col, FC_PRIORITY );
    522     /* Translators: this is a column header in Files tab, Details dialog;
    523        Don't include the prefix "filedetails|" in the translation. */
    524     gtk_tree_view_column_set_title (col, Q_("filedetails|Priority"));
    525     rend = priority_rend = gtk_cell_renderer_combo_new ();
    526     gtk_tree_view_column_pack_start (col, rend, TRUE);
    527     g_object_set (G_OBJECT(rend), "model", model,
    528                                   "editable", TRUE,
    529                                   "has-entry", FALSE,
    530                                   "text-column", 0,
    531                                   NULL);
    532     g_object_unref (G_OBJECT(model));
    533     gtk_tree_view_column_add_attribute (col, rend, "text", FC_PRIORITY);
    534     gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
     636    rend = gtk_cell_renderer_text_new( );
     637    col = gtk_tree_view_column_new_with_attributes( _( "Priorities" ), rend, NULL );
     638    gtk_tree_view_column_set_cell_data_func( col, rend, renderPriority, NULL, NULL);
     639    gtk_tree_view_append_column ( GTK_TREE_VIEW( view ), col);
    535640
    536641    /* create the scrolled window and stick the view in it */
     
    543648    gtk_widget_set_size_request (scroll, 0u, 200u);
    544649
    545     ret = scroll;
    546650    data = g_new0( FileData, 1 );
     651
     652    vbox = gtk_vbox_new( FALSE, GUI_PAD );
     653        w = gtk_button_new_with_mnemonic( _( "_High" ) );
     654        g_signal_connect( w, "clicked", G_CALLBACK(onHighClicked), data );
     655        gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
     656        w = gtk_button_new_with_mnemonic( _( "_Normal" ) );
     657        g_signal_connect( w, "clicked", G_CALLBACK(onNormalClicked), data );
     658        gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
     659        w = gtk_button_new_with_mnemonic( _( "_Low" ) );
     660        g_signal_connect( w, "clicked", G_CALLBACK(onLowClicked), data );
     661        gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
     662        w = gtk_button_new_with_mnemonic( "_Ignore" );
     663        g_signal_connect( w, "clicked", G_CALLBACK(onIgnoreClicked), data );
     664        gtk_box_pack_end( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
     665        w = gtk_button_new_with_mnemonic( "_Download" );
     666        g_signal_connect( w, "clicked", G_CALLBACK(onDownloadClicked), data );
     667        gtk_box_pack_end( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
     668    hbox = gtk_hbox_new( FALSE, GUI_PAD );
     669    gtk_box_pack_start_defaults( GTK_BOX( hbox ), scroll );
     670    gtk_box_pack_start( GTK_BOX( hbox ), vbox, 0, 0, 0 );
     671
     672    ret = hbox;
    547673    data->view = view;
    548674    data->top = scroll;
    549     g_signal_connect (G_OBJECT(priority_rend), "edited", G_CALLBACK(priority_changed_cb), data);
    550     g_signal_connect(enabled_rend, "toggled", G_CALLBACK(enabled_toggled), data );
    551675    g_object_set_data_full( G_OBJECT( ret ), "file-data", data, freeData );
    552676    file_list_set_torrent( ret, gtor );
Note: See TracChangeset for help on using the changeset viewer.