~ubuntu-branches/ubuntu/maverick/transmission/maverick

« back to all changes in this revision

Viewing changes to gtk/tr-window.c

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Klimonda
  • Date: 2009-05-22 21:57:30 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (2.1.18 sid) (1.3.8 upstream)
  • mto: This revision was merged to the branch mainline in revision 36.
  • Revision ID: james.westby@ubuntu.com-20090522215730-ly5kgv5aw9ig2u82
Tags: upstream-1.61
ImportĀ upstreamĀ versionĀ 1.61

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: tr-window.c 7664 2009-01-11 17:46:51Z charles $
 
2
 * $Id: tr-window.c 8315 2009-05-02 13:53:49Z charles $
3
3
 *
4
4
 * Copyright (c) 2005-2008 Transmission authors and contributors
5
5
 *
73
73
 
74
74
typedef struct
75
75
{
 
76
    GtkWidget *           speedlimit_on_item[2];
 
77
    GtkWidget *           speedlimit_off_item[2];
 
78
    GtkWidget *           ratio_on_item;
 
79
    GtkWidget *           ratio_off_item;
76
80
    GtkWidget *           scroll;
77
81
    GtkWidget *           view;
78
82
    GtkWidget *           toolbar;
79
83
    GtkWidget *           filter;
80
84
    GtkWidget *           status;
81
85
    GtkWidget *           status_menu;
 
86
    GtkWidget *           ul_hbox;
 
87
    GtkWidget *           dl_hbox;
82
88
    GtkWidget *           ul_lb;
83
89
    GtkWidget *           dl_lb;
84
90
    GtkWidget *           stats_lb;
85
91
    GtkWidget *           gutter_lb;
 
92
    GtkWidget *           alt_speed_image[2]; /* 0==off, 1==on */
 
93
    GtkWidget *           alt_speed_button;
 
94
    GtkWidget *           options_menu;
86
95
    GtkTreeSelection *    selection;
87
96
    GtkCellRenderer *     renderer;
88
97
    GtkTreeViewColumn *   column;
92
101
    filter_mode_t         filter_mode;
93
102
    filter_text_mode_t    filter_text_mode;
94
103
    char *                filter_text;
 
104
    GtkToggleButton     * filter_toggles[FILTER_MODE_QTY];
95
105
}
96
106
PrivateData;
97
107
 
 
108
static const char*
 
109
getFilterName( int mode )
 
110
{
 
111
    switch( mode )
 
112
    {
 
113
        case FILTER_MODE_ACTIVE:      return "show-active";
 
114
        case FILTER_MODE_DOWNLOADING: return "show-downloading";
 
115
        case FILTER_MODE_SEEDING:     return "show-seeding";
 
116
        case FILTER_MODE_PAUSED:      return "show-paused";
 
117
        default:                      return "show-all"; /* the fallback */
 
118
    }
 
119
}
 
120
static int
 
121
getFilterModeFromName( const char * name )
 
122
{
 
123
    if( !strcmp( name, "show-active"      ) ) return FILTER_MODE_ACTIVE;
 
124
    if( !strcmp( name, "show-downloading" ) ) return FILTER_MODE_DOWNLOADING;
 
125
    if( !strcmp( name, "show-seeding"     ) ) return FILTER_MODE_SEEDING;
 
126
    if( !strcmp( name, "show-paused"      ) ) return FILTER_MODE_PAUSED;
 
127
    return FILTER_MODE_ALL; /* the fallback */
 
128
}
 
129
 
98
130
#define PRIVATE_DATA_KEY "private-data"
99
 
 
100
131
#define FILTER_MODE_KEY "tr-filter-mode"
101
132
#define FILTER_TEXT_MODE_KEY "tr-filter-text-mode"
102
 
#define FILTER_TOGGLES_KEY "tr-filter-toggles"
103
133
 
104
134
static PrivateData*
105
135
get_private_data( TrWindow * w )
147
177
 
148
178
    view = gtk_tree_view_new( );
149
179
    gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), FALSE );
 
180
    gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW( view ), TRUE );
150
181
 
151
182
    p->selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) );
152
183
 
 
184
    p->column = col = GTK_TREE_VIEW_COLUMN (g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,                  
 
185
        "title", _("Torrent"),
 
186
        "resizable", TRUE,
 
187
        "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
 
188
        NULL));
 
189
 
153
190
    p->renderer = r = torrent_cell_renderer_new( );
154
 
    p->column = col = gtk_tree_view_column_new_with_attributes(
155
 
                    _( "Torrent" ), r, "torrent", MC_TORRENT_RAW, NULL );
156
 
    g_object_set( G_OBJECT( col ), "resizable", TRUE,
157
 
                  "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
158
 
                  NULL );
 
191
    gtk_tree_view_column_pack_start( col, r, FALSE );
 
192
    gtk_tree_view_column_add_attribute( col, r, "torrent", MC_TORRENT_RAW );
 
193
    
159
194
    gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col );
160
195
    g_object_set( r, "xpad", GUI_PAD_SMALL, "ypad", GUI_PAD_SMALL, NULL );
161
196
 
188
223
    return view;
189
224
}
190
225
 
 
226
static void syncAltSpeedButton( PrivateData * p );
 
227
static void setFilter( PrivateData * p, int mode );
 
228
 
191
229
static void
192
230
prefsChanged( TrCore * core UNUSED,
193
231
              const char *  key,
198
236
    if( !strcmp( key, PREF_KEY_MINIMAL_VIEW ) )
199
237
    {
200
238
        g_object_set( p->renderer, "minimal", pref_flag_get( key ), NULL );
201
 
        gtk_tree_view_column_queue_resize( p->column );
202
 
        gtk_widget_queue_draw( p->view );
 
239
        /* since the cell size has changed, we need gtktreeview to revalidate
 
240
         * its fixed-height mode values.  Unfortunately there's not an API call
 
241
         * for that, but it *does* revalidate when it thinks the style's been tweaked */
 
242
        g_signal_emit_by_name( p->view, "style-set", NULL, NULL );
 
243
    }
 
244
    else if( !strcmp( key, PREF_KEY_FILTER_MODE ) )
 
245
    {
 
246
        setFilter( p, getFilterModeFromName( pref_string_get( key ) ) );
203
247
    }
204
248
    else if( !strcmp( key, PREF_KEY_STATUSBAR ) )
205
249
    {
220
264
    {
221
265
        tr_window_update( (TrWindow*)wind );
222
266
    }
 
267
    else if( !strcmp( key, TR_PREFS_KEY_ALT_SPEED_ENABLED ) )
 
268
    {
 
269
        syncAltSpeedButton( p );
 
270
    }
223
271
}
224
272
 
225
273
static void
269
317
    }
270
318
}
271
319
 
 
320
static void
 
321
syncAltSpeedButton( PrivateData * p )
 
322
{
 
323
    const char * tip;
 
324
    const gboolean b = pref_flag_get( TR_PREFS_KEY_ALT_SPEED_ENABLED );
 
325
    GtkWidget * w = p->alt_speed_button;
 
326
 
 
327
    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), b );
 
328
 
 
329
    gtk_button_set_image( GTK_BUTTON( w ), p->alt_speed_image[b?1:0] );
 
330
    gtk_button_set_alignment( GTK_BUTTON( w ), 0.5, 0.5 );
 
331
 
 
332
    tip = b ? _( "Click to disable Speed Limit Mode" )
 
333
            : _( "Click to enable Speed Limit Mode" );
 
334
    gtr_widget_set_tooltip_text( w, tip );
 
335
}
 
336
 
 
337
static void
 
338
alt_speed_toggled_cb( GtkToggleButton * button, gpointer vprivate )
 
339
{
 
340
    PrivateData * p = vprivate;
 
341
    const gboolean b = gtk_toggle_button_get_active( button );
 
342
    tr_core_set_pref_bool( p->core, TR_PREFS_KEY_ALT_SPEED_ENABLED,  b );
 
343
}
 
344
    
272
345
/***
273
346
****  FILTER
274
347
***/
332
405
        case FILTER_MODE_ACTIVE:
333
406
        {
334
407
            const tr_stat * s = tr_torrentStatCached( tor );
335
 
            ret = s->peersSendingToUs > 0 || s->peersGettingFromUs > 0;
 
408
            ret = s->peersSendingToUs > 0
 
409
               || s->peersGettingFromUs > 0
 
410
               || tr_torrentGetActivity( tor ) == TR_STATUS_CHECK;
336
411
            break;
337
412
        }
338
413
 
382
457
}
383
458
 
384
459
static void
385
 
filter_toggled_cb( GtkToggleButton * toggle,
386
 
                   gpointer          vprivate )
 
460
setFilter( PrivateData * p, int mode )
387
461
{
388
 
    PrivateData *       p = vprivate;
389
 
    GSList *            l;
390
 
    GSList *            toggles = g_object_get_data( G_OBJECT(
391
 
                                                         toggle ),
392
 
                                                     FILTER_TOGGLES_KEY );
393
 
    const gboolean      isActive = gtk_toggle_button_get_active( toggle );
394
 
    const filter_mode_t mode =
395
 
        GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toggle ),
396
 
                                             FILTER_MODE_KEY ) );
397
 
 
398
 
    /* update the filter */
399
 
    if( isActive )
 
462
    if( mode != (int)p->filter_mode )
400
463
    {
 
464
        int i;
 
465
 
 
466
        /* refilter */
401
467
        p->filter_mode = mode;
402
468
        refilter( p );
 
469
 
 
470
        /* update the prefs */
 
471
        tr_core_set_pref( p->core, PREF_KEY_FILTER_MODE, getFilterName( mode ) );
 
472
 
 
473
        /* update the togglebuttons */
 
474
        for( i=0; i<FILTER_MODE_QTY; ++i )
 
475
            gtk_toggle_button_set_active( p->filter_toggles[i], i==mode );
403
476
    }
 
477
}
 
478
  
404
479
 
405
 
    /* deactivate the other toggles */
406
 
    for( l = toggles; l != NULL; l = l->next )
 
480
static void
 
481
filter_toggled_cb( GtkToggleButton * toggle, gpointer vprivate )
 
482
{
 
483
    if( gtk_toggle_button_get_active( toggle ) )
407
484
    {
408
 
        GtkToggleButton * walk = GTK_TOGGLE_BUTTON( l->data );
409
 
        if( isActive && ( toggle != walk ) )
410
 
            gtk_toggle_button_set_active( walk, FALSE );
 
485
        PrivateData * p = vprivate;
 
486
        const int mode = GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toggle ), FILTER_MODE_KEY ) );
 
487
        setFilter( p, mode );
411
488
    }
412
 
 
413
 
    /* at least one button must always be set */
414
 
    if( !isActive && ( p->filter_mode == mode ) )
415
 
        gtk_toggle_button_set_active( toggle, TRUE );
416
489
}
417
490
 
418
491
static void
493
566
 
494
567
#endif
495
568
 
 
569
static gboolean
 
570
onAltSpeedToggledIdle( gpointer vp )
 
571
{
 
572
    PrivateData * p = vp;
 
573
    gboolean b = tr_sessionUsesAltSpeed( tr_core_session( p->core ) );
 
574
    tr_core_set_pref_bool( p->core, TR_PREFS_KEY_ALT_SPEED_ENABLED, b );
 
575
 
 
576
    return FALSE;
 
577
}
 
578
 
 
579
static void
 
580
onAltSpeedToggled( tr_session * s UNUSED, tr_bool isEnabled UNUSED, tr_bool byUser UNUSED, void * p )
 
581
{
 
582
    g_idle_add( onAltSpeedToggledIdle, p );
 
583
}
 
584
 
 
585
/***
 
586
****  Speed limit menu
 
587
***/
 
588
 
 
589
#define DIRECTION_KEY "direction-key"
 
590
#define ENABLED_KEY "enabled-key"
 
591
#define SPEED_KEY "speed-key"
 
592
 
 
593
static void
 
594
onSpeedToggled( GtkCheckMenuItem * check, gpointer vp ) 
 
595
{
 
596
    PrivateData * p = vp;
 
597
    GObject * o = G_OBJECT( check );
 
598
    gboolean isEnabled = g_object_get_data( o, ENABLED_KEY ) != 0;
 
599
    tr_direction dir = GPOINTER_TO_INT( g_object_get_data( o, DIRECTION_KEY ) );
 
600
    const char * key = dir == TR_UP ? TR_PREFS_KEY_USPEED_ENABLED
 
601
                                    : TR_PREFS_KEY_DSPEED_ENABLED;
 
602
 
 
603
    if( gtk_check_menu_item_get_active( check ) )
 
604
        tr_core_set_pref_bool( p->core, key, isEnabled );
 
605
}
 
606
 
 
607
static void
 
608
onSpeedSet( GtkCheckMenuItem * check, gpointer vp ) 
 
609
{
 
610
    const char * key;
 
611
    PrivateData * p = vp;
 
612
    GObject * o = G_OBJECT( check );
 
613
    const int speed = GPOINTER_TO_INT( g_object_get_data( o, SPEED_KEY ) );
 
614
    tr_direction dir = GPOINTER_TO_INT( g_object_get_data( o, DIRECTION_KEY ) );
 
615
 
 
616
    key = dir==TR_UP ? TR_PREFS_KEY_USPEED : TR_PREFS_KEY_DSPEED;
 
617
    tr_core_set_pref_int( p->core, key, speed );
 
618
 
 
619
    key = dir==TR_UP ? TR_PREFS_KEY_USPEED_ENABLED : TR_PREFS_KEY_DSPEED_ENABLED;
 
620
    tr_core_set_pref_bool( p->core, key, TRUE );
 
621
}
 
622
 
 
623
static GtkWidget*
 
624
createSpeedMenu( PrivateData * p, tr_direction dir )
 
625
{
 
626
    int i, n;
 
627
    GtkWidget *w, *m;
 
628
    const int speeds[] = { 5, 10, 20, 30, 40, 50, 75, 100, 150, 200, 250, 500, 750 };
 
629
 
 
630
    m = gtk_menu_new( );
 
631
 
 
632
    w = gtk_radio_menu_item_new_with_label( NULL, _( "Unlimited" ) );
 
633
    p->speedlimit_off_item[dir] = w;
 
634
    g_object_set_data( G_OBJECT( w ), DIRECTION_KEY, GINT_TO_POINTER( dir ) );
 
635
    g_object_set_data( G_OBJECT( w ), ENABLED_KEY, GINT_TO_POINTER( FALSE ) );
 
636
    g_signal_connect( w, "toggled", G_CALLBACK(onSpeedToggled), p );
 
637
    gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
638
 
 
639
    w = gtk_radio_menu_item_new_with_label_from_widget( GTK_RADIO_MENU_ITEM( w ), "" );
 
640
    p->speedlimit_on_item[dir] = w;
 
641
    g_object_set_data( G_OBJECT( w ), DIRECTION_KEY, GINT_TO_POINTER( dir ) );
 
642
    g_object_set_data( G_OBJECT( w ), ENABLED_KEY, GINT_TO_POINTER( TRUE ) );
 
643
    g_signal_connect( w, "toggled", G_CALLBACK(onSpeedToggled), p );
 
644
    gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
645
 
 
646
    w = gtk_separator_menu_item_new( );
 
647
    gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
648
 
 
649
    for( i=0, n=G_N_ELEMENTS(speeds); i<n; ++i )
 
650
    {
 
651
        char buf[128];
 
652
        tr_strlspeed( buf, speeds[i], sizeof( buf ) );
 
653
        w = gtk_menu_item_new_with_label( buf );
 
654
        g_object_set_data( G_OBJECT( w ), DIRECTION_KEY, GINT_TO_POINTER( dir ) );
 
655
        g_object_set_data( G_OBJECT( w ), SPEED_KEY, GINT_TO_POINTER( speeds[i] ) );
 
656
        g_signal_connect( w, "activate", G_CALLBACK(onSpeedSet), p );
 
657
        gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
658
    }
 
659
 
 
660
    return m;
 
661
}
 
662
 
 
663
/***
 
664
****  Speed limit menu
 
665
***/
 
666
 
 
667
#define RATIO_KEY "stock-ratio-index"
 
668
 
 
669
static const double stockRatios[] = { 0.25, 0.5, 0.75, 1, 1.5, 2, 3 };
 
670
 
 
671
static void
 
672
onRatioToggled( GtkCheckMenuItem * check, gpointer vp ) 
 
673
{
 
674
    PrivateData * p = vp;
 
675
    if( gtk_check_menu_item_get_active( check ) )
 
676
    {
 
677
        gboolean f = g_object_get_data( G_OBJECT( check ), ENABLED_KEY ) != 0;
 
678
        tr_core_set_pref_bool( p->core, TR_PREFS_KEY_RATIO_ENABLED, f );
 
679
    }
 
680
}
 
681
static void
 
682
onRatioSet( GtkCheckMenuItem * check, gpointer vp ) 
 
683
{
 
684
    PrivateData * p = vp;
 
685
    int i = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( check ), RATIO_KEY ) );
 
686
    const double ratio = stockRatios[i];
 
687
    tr_core_set_pref_double( p->core, TR_PREFS_KEY_RATIO, ratio );
 
688
    tr_core_set_pref_bool  ( p->core, TR_PREFS_KEY_RATIO_ENABLED, TRUE );
 
689
}
 
690
 
 
691
static GtkWidget*
 
692
createRatioMenu( PrivateData * p )
 
693
{
 
694
    int i, n;
 
695
    GtkWidget *m, *w;
 
696
 
 
697
    m = gtk_menu_new( );
 
698
 
 
699
    w = gtk_radio_menu_item_new_with_label( NULL, _( "Seed Forever" ) );
 
700
    p->ratio_off_item = w;
 
701
    g_object_set_data( G_OBJECT( w ), ENABLED_KEY, GINT_TO_POINTER( FALSE ) );
 
702
    g_signal_connect( w, "toggled", G_CALLBACK(onRatioToggled), p );
 
703
    gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
704
 
 
705
    w = gtk_radio_menu_item_new_with_label_from_widget( GTK_RADIO_MENU_ITEM( w ), "" );
 
706
    p->ratio_on_item = w;
 
707
    g_object_set_data( G_OBJECT( w ), ENABLED_KEY, GINT_TO_POINTER( TRUE ) );
 
708
    g_signal_connect( w, "toggled", G_CALLBACK(onRatioToggled), p );
 
709
    gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
710
 
 
711
    w = gtk_separator_menu_item_new( );
 
712
    gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
713
 
 
714
    for( i=0, n=G_N_ELEMENTS(stockRatios); i<n; ++i )
 
715
    {
 
716
        char buf[128];
 
717
        tr_strlratio( buf, stockRatios[i], sizeof( buf ) );
 
718
        w = gtk_menu_item_new_with_label( buf );
 
719
        g_object_set_data( G_OBJECT( w ), RATIO_KEY, GINT_TO_POINTER( i ) );
 
720
        g_signal_connect( w, "activate", G_CALLBACK(onRatioSet), p );
 
721
        gtk_menu_shell_append( GTK_MENU_SHELL( m ), w );
 
722
    }
 
723
 
 
724
    return m;
 
725
}
 
726
 
 
727
/***
 
728
****  Option menu
 
729
***/
 
730
 
 
731
static GtkWidget*
 
732
createOptionsMenu( PrivateData * p )
 
733
{
 
734
    GtkWidget * m;
 
735
    GtkWidget * top = gtk_menu_new( );
 
736
 
 
737
    m = gtk_menu_item_new_with_label( _( "Limit Download Speed" ) );
 
738
    gtk_menu_item_set_submenu( GTK_MENU_ITEM( m ), createSpeedMenu( p, TR_DOWN ) );
 
739
    gtk_menu_shell_append( GTK_MENU_SHELL( top ), m );
 
740
 
 
741
    m = gtk_menu_item_new_with_label( _( "Limit Upload Speed" ) );
 
742
    gtk_menu_item_set_submenu( GTK_MENU_ITEM( m ), createSpeedMenu( p, TR_UP ) );
 
743
    gtk_menu_shell_append( GTK_MENU_SHELL( top ), m );
 
744
 
 
745
    m = gtk_separator_menu_item_new( );
 
746
    gtk_menu_shell_append( GTK_MENU_SHELL( top ), m );
 
747
 
 
748
    m = gtk_menu_item_new_with_label( _( "Stop Seeding at Ratio" ) );
 
749
    gtk_menu_item_set_submenu( GTK_MENU_ITEM( m ), createRatioMenu( p ) );
 
750
    gtk_menu_shell_append( GTK_MENU_SHELL( top ), m );
 
751
 
 
752
    gtk_widget_show_all( top );
 
753
    return top;
 
754
}
 
755
 
 
756
static void
 
757
onOptionsClicked( GtkButton * button UNUSED, gpointer vp )
 
758
{
 
759
    char buf1[512];
 
760
    char buf2[512];
 
761
    gboolean b;
 
762
    GtkWidget * w;
 
763
    PrivateData * p = vp;
 
764
 
 
765
    w = p->speedlimit_on_item[TR_DOWN];
 
766
    tr_strlspeed( buf1, pref_int_get( TR_PREFS_KEY_DSPEED ), sizeof( buf1 ) );
 
767
    gtk_label_set_text( GTK_LABEL( gtk_bin_get_child( GTK_BIN( w ) ) ), buf1 );
 
768
 
 
769
    b = pref_flag_get( TR_PREFS_KEY_DSPEED_ENABLED );
 
770
    w = b ? p->speedlimit_on_item[TR_DOWN] : p->speedlimit_off_item[TR_DOWN];
 
771
    gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( w ), TRUE );
 
772
 
 
773
    w = p->speedlimit_on_item[TR_UP];
 
774
    tr_strlspeed( buf1, pref_int_get( TR_PREFS_KEY_USPEED ), sizeof( buf1 ) );
 
775
    gtk_label_set_text( GTK_LABEL( gtk_bin_get_child( GTK_BIN( w ) ) ), buf1 );
 
776
 
 
777
    b = pref_flag_get( TR_PREFS_KEY_USPEED_ENABLED );
 
778
    w = b ? p->speedlimit_on_item[TR_UP] : p->speedlimit_off_item[TR_UP];
 
779
    gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( w ), TRUE );
 
780
 
 
781
    tr_strlratio( buf1, pref_double_get( TR_PREFS_KEY_RATIO ), sizeof( buf1 ) );
 
782
    g_snprintf( buf2, sizeof( buf2 ), _( "Stop at Ratio (%s)" ), buf1 );
 
783
    gtk_label_set_text( GTK_LABEL( gtk_bin_get_child( GTK_BIN( p->ratio_on_item ) ) ), buf2 );
 
784
 
 
785
    b = pref_flag_get( TR_PREFS_KEY_RATIO_ENABLED );
 
786
    gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( b ? p->ratio_on_item : p->ratio_off_item ), TRUE );
 
787
 
 
788
    gtk_menu_popup ( GTK_MENU( p->options_menu ), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time( ) );
 
789
}
 
790
 
496
791
/***
497
792
****  PUBLIC
498
793
***/
504
799
    const char *  pch;
505
800
    PrivateData * p;
506
801
    GtkWidget   *mainmenu, *toolbar, *filter, *list, *status;
507
 
    GtkWidget *   vbox, *w, *self, *h, *c, *s, *image, *menu;
 
802
    GtkWidget *   vbox, *w, *self, *h, *c, *s, *hbox, *image, *menu;
508
803
    GtkWindow *   win;
509
804
    GSList *      l;
510
 
    GSList *      toggles;
511
805
 
512
806
    const char *  filter_names[FILTER_MODE_QTY] = {
513
807
        /* show all torrents */
526
820
    };
527
821
 
528
822
    p = g_new0( PrivateData, 1 );
529
 
    p->filter_mode = FILTER_MODE_ALL;
530
823
    p->filter_text_mode = FILTER_TEXT_MODE_NAME;
531
824
    p->filter_text = NULL;
532
825
 
560
853
    w = toolbar = p->toolbar = action_get_widget( "/main-window-toolbar" );
561
854
 
562
855
    /* filter */
563
 
    toggles = NULL;
564
856
    h = filter = p->filter = gtk_hbox_new( FALSE, 0 );
565
857
    gtk_container_set_border_width( GTK_CONTAINER( h ), GUI_PAD_SMALL );
566
858
    for( i = 0; i < FILTER_MODE_QTY; ++i )
567
859
    {
568
860
        const char * mnemonic = _( filter_names[i] );
569
861
        w = gtk_toggle_button_new_with_mnemonic( mnemonic );
570
 
        g_object_set_data( G_OBJECT( w ), FILTER_MODE_KEY,
571
 
                          GINT_TO_POINTER( i ) );
 
862
        g_object_set_data( G_OBJECT( w ), FILTER_MODE_KEY, GINT_TO_POINTER( i ) );
572
863
        gtk_button_set_relief( GTK_BUTTON( w ), GTK_RELIEF_NONE );
573
 
        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(
574
 
                                          w ), i == FILTER_MODE_ALL );
575
 
        toggles = g_slist_prepend( toggles, w );
 
864
        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( w ), i == FILTER_MODE_ALL );
 
865
        p->filter_toggles[i] = GTK_TOGGLE_BUTTON( w );
576
866
        g_signal_connect( w, "toggled", G_CALLBACK( filter_toggled_cb ), p );
577
867
        gtk_box_pack_start( GTK_BOX( h ), w, FALSE, FALSE, 0 );
578
868
    }
579
 
    for( l = toggles; l != NULL; l = l->next )
580
 
        g_object_set_data( G_OBJECT( l->data ), FILTER_TOGGLES_KEY, toggles );
 
869
 
581
870
    s = sexy_icon_entry_new( );
582
871
    sexy_icon_entry_add_clear_button( SEXY_ICON_ENTRY( s ) );
583
872
    image = gtk_image_new_from_stock( GTK_STOCK_FIND, GTK_ICON_SIZE_MENU );
612
901
 
613
902
    /* status */
614
903
    h = status = p->status = gtk_hbox_new( FALSE, GUI_PAD );
615
 
    gtk_container_set_border_width( GTK_CONTAINER( h ), GUI_PAD );
616
 
    w = p->gutter_lb = gtk_label_new( "N Torrents" );
617
 
    gtk_box_pack_start( GTK_BOX( h ), w, 0, 0, 0 );
618
 
    w = p->ul_lb = gtk_label_new( NULL );
619
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
620
 
    w = gtk_image_new_from_stock( GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU );
621
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
622
 
    w = gtk_alignment_new( 0.0f, 0.0f, 0.0f, 0.0f );
623
 
    gtk_widget_set_size_request( w, GUI_PAD, 0u );
624
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
625
 
    w = p->dl_lb = gtk_label_new( NULL );
626
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
627
 
    w = gtk_image_new_from_stock( GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU );
628
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
629
 
    w = gtk_alignment_new( 0.0f, 0.0f, 0.0f, 0.0f );
630
 
    gtk_widget_set_size_request( w, GUI_PAD, 0u );
631
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
632
 
    w = p->stats_lb = gtk_label_new( NULL );
633
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
634
 
    w = gtk_image_new_from_stock( GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU );
635
 
    c = gtk_event_box_new( );
636
 
    gtk_container_add( GTK_CONTAINER( c ), w );
637
 
    w = c;
638
 
    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
639
 
    g_signal_connect( w, "button-release-event",
640
 
                      G_CALLBACK( onYinYangReleased ), p );
 
904
    gtk_container_set_border_width( GTK_CONTAINER( h ), GUI_PAD_SMALL );
 
905
 
 
906
        w = gtk_button_new( );
 
907
        gtk_container_add( GTK_CONTAINER( w ), gtk_image_new_from_stock( "options", GTK_ICON_SIZE_SMALL_TOOLBAR ) );
 
908
        gtk_box_pack_start( GTK_BOX( h ), w, 0, 0, 0 );
 
909
        gtk_button_set_relief( GTK_BUTTON( w ), GTK_RELIEF_NONE );
 
910
        p->options_menu = createOptionsMenu( p );
 
911
        g_signal_connect( w, "clicked", G_CALLBACK(onOptionsClicked), p );
 
912
 
 
913
        p->alt_speed_image[0] = gtk_image_new_from_stock( "alt-speed-off", -1 );
 
914
        p->alt_speed_image[1]  = gtk_image_new_from_stock( "alt-speed-on", -1 );
 
915
        w = p->alt_speed_button = gtk_toggle_button_new( );
 
916
        gtk_button_set_relief( GTK_BUTTON( w ), GTK_RELIEF_NONE );
 
917
        g_object_ref( G_OBJECT( p->alt_speed_image[0] ) );
 
918
        g_object_ref( G_OBJECT( p->alt_speed_image[1] ) );
 
919
        g_signal_connect( w, "toggled", G_CALLBACK(alt_speed_toggled_cb ), p );
 
920
        gtk_box_pack_start( GTK_BOX( h ), w, 0, 0, 0 );
 
921
 
 
922
        w = p->gutter_lb = gtk_label_new( "N Torrents" );
 
923
        gtk_box_pack_start( GTK_BOX( h ), w, 1, 1, GUI_PAD_BIG );
 
924
 
 
925
        hbox = p->ul_hbox = gtk_hbox_new( FALSE, GUI_PAD_SMALL );
 
926
            w = gtk_alignment_new( 0.0f, 0.0f, 0.0f, 0.0f );
 
927
            gtk_widget_set_size_request( w, GUI_PAD, 0u );
 
928
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
 
929
            w = gtk_image_new_from_stock( GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU );
 
930
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
 
931
            w = p->ul_lb = gtk_label_new( NULL );
 
932
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 ); 
 
933
        gtk_box_pack_end( GTK_BOX( h ), hbox, FALSE, FALSE, 0 );
 
934
 
 
935
        hbox = p->dl_hbox = gtk_hbox_new( FALSE, GUI_PAD_SMALL );
 
936
            w = gtk_alignment_new( 0.0f, 0.0f, 0.0f, 0.0f );
 
937
            gtk_widget_set_size_request( w, GUI_PAD, 0u );
 
938
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
 
939
            w = gtk_image_new_from_stock( GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU );
 
940
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
 
941
            w = p->dl_lb = gtk_label_new( NULL );
 
942
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 ); 
 
943
        gtk_box_pack_end( GTK_BOX( h ), hbox, FALSE, FALSE, 0 );
 
944
 
 
945
        hbox = gtk_hbox_new( FALSE, GUI_PAD_SMALL );
 
946
            w = gtk_alignment_new( 0.0f, 0.0f, 0.0f, 0.0f );
 
947
            gtk_widget_set_size_request( w, GUI_PAD, 0u );
 
948
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
 
949
            w = gtk_image_new_from_stock( GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU );
 
950
            c = gtk_event_box_new( );
 
951
            gtk_container_add( GTK_CONTAINER( c ), w );
 
952
            w = c;
 
953
            g_signal_connect( w, "button-release-event", G_CALLBACK( onYinYangReleased ), p );
 
954
            gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
 
955
            w = p->stats_lb = gtk_label_new( NULL );
 
956
            gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
 
957
        gtk_box_pack_end( GTK_BOX( h ), hbox, FALSE, FALSE, 0 );
 
958
 
641
959
 
642
960
    menu = gtk_menu_new( );
643
961
    l = NULL;
697
1015
    prefsChanged( core, PREF_KEY_STATUSBAR, self );
698
1016
    prefsChanged( core, PREF_KEY_STATUSBAR_STATS, self );
699
1017
    prefsChanged( core, PREF_KEY_TOOLBAR, self );
 
1018
    prefsChanged( core, PREF_KEY_FILTER_MODE, self );
 
1019
    prefsChanged( core, TR_PREFS_KEY_ALT_SPEED_ENABLED, self );
700
1020
    p->pref_handler_id = g_signal_connect( core, "prefs-changed",
701
1021
                                           G_CALLBACK( prefsChanged ), self );
702
1022
 
 
1023
    tr_sessionSetAltSpeedFunc( tr_core_session( core ), onAltSpeedToggled, p );
 
1024
 
703
1025
    filter_entry_changed( GTK_EDITABLE( s ), p );
704
1026
    return self;
705
1027
}
715
1037
        const int visibleCount = gtk_tree_model_iter_n_children(
716
1038
            p->filter_model, NULL );
717
1039
 
718
 
        if( torrentCount != visibleCount )
 
1040
        if( !torrentCount )
 
1041
            *buf = '\0';
 
1042
        else if( torrentCount != visibleCount )
719
1043
            g_snprintf( buf, sizeof( buf ),
720
1044
                        ngettext( "%1$'d of %2$'d Torrent",
721
1045
                                  "%1$'d of %2$'d Torrents",
722
1046
                                  torrentCount ),
723
1047
                        visibleCount, torrentCount );
724
1048
        else
725
 
            g_snprintf( buf, sizeof( buf ), ngettext( "%'d Torrent",
726
 
                                                      "%'d Torrents",
727
 
                                                      torrentCount ),
 
1049
            g_snprintf( buf, sizeof( buf ),
 
1050
                        ngettext( "%'d Torrent", "%'d Torrents", torrentCount ),
728
1051
                        torrentCount );
729
1052
        gtk_label_set_text( GTK_LABEL( p->gutter_lb ), buf );
730
1053
    }
790
1113
        d = tr_sessionGetPieceSpeed( session, TR_DOWN );
791
1114
        tr_strlspeed( buf, d, sizeof( buf ) );
792
1115
        gtk_label_set_text( GTK_LABEL( p->dl_lb ), buf );
 
1116
        g_object_set( p->dl_hbox, "visible", d>=0.01, NULL );
793
1117
 
794
1118
        d = tr_sessionGetPieceSpeed( session, TR_UP );
795
1119
        tr_strlspeed( buf, d, sizeof( buf ) );
796
1120
        gtk_label_set_text( GTK_LABEL( p->ul_lb ), buf );
 
1121
        g_object_set( p->ul_hbox, "visible", d>=0.01, NULL );
797
1122
    }
798
1123
}
799
1124