1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: stats.c 13388 2012-07-14 19:26:55Z jordan $
11 */
12
13#include <glib/gi18n.h>
14#include <gtk/gtk.h>
15#include "hig.h"
16#include "stats.h"
17#include "tr-core.h"
18#include "tr-prefs.h"
19#include "util.h"
20
21enum
22{
23    TR_RESPONSE_RESET = 1
24};
25
26struct stat_ui
27{
28    GtkWidget *  one_up_lb;
29    GtkWidget *  one_down_lb;
30    GtkWidget *  one_ratio_lb;
31    GtkWidget *  one_time_lb;
32    GtkWidget *  all_up_lb;
33    GtkWidget *  all_down_lb;
34    GtkWidget *  all_ratio_lb;
35    GtkWidget *  all_time_lb;
36    GtkWidget *  all_sessions_lb;
37    TrCore *     core;
38};
39
40static void
41setLabel( GtkWidget *  w, const char * str )
42{
43    gtr_label_set_text( GTK_LABEL( w ), str );
44}
45
46static void
47setLabelFromRatio( GtkWidget * w, double d )
48{
49    char buf[128];
50
51    tr_strlratio( buf, d, sizeof( buf ) );
52    setLabel( w, buf );
53}
54
55static gboolean
56updateStats( gpointer gdata )
57{
58    char buf[128];
59    const char * fmt;
60    tr_session_stats one, all;
61    const size_t buflen = sizeof( buf );
62    struct stat_ui * ui = gdata;
63
64    tr_sessionGetStats( gtr_core_session( ui->core ), &one );
65    tr_sessionGetCumulativeStats( gtr_core_session( ui->core ), &all );
66
67    setLabel( ui->one_up_lb, tr_strlsize( buf, one.uploadedBytes, buflen ) );
68    setLabel( ui->one_down_lb, tr_strlsize( buf, one.downloadedBytes, buflen ) );
69    setLabel( ui->one_time_lb, tr_strltime( buf, one.secondsActive, buflen ) );
70    setLabelFromRatio( ui->one_ratio_lb, one.ratio );
71
72    fmt = ngettext( "Started %'d time", "Started %'d times",
73                     (int)all.sessionCount );
74    g_snprintf( buf, buflen, fmt, (int)all.sessionCount );
75    setLabel( ui->all_sessions_lb, buf );
76    setLabel( ui->all_up_lb, tr_strlsize( buf, all.uploadedBytes, buflen ) );
77    setLabel( ui->all_down_lb, tr_strlsize( buf, all.downloadedBytes, buflen ) );
78    setLabel( ui->all_time_lb, tr_strltime( buf, all.secondsActive, buflen ) );
79    setLabelFromRatio( ui->all_ratio_lb, all.ratio );
80
81    return TRUE;
82}
83
84static void
85dialogDestroyed( gpointer p, GObject * dialog UNUSED )
86{
87    g_source_remove( GPOINTER_TO_UINT( p ) );
88}
89
90static void
91dialogResponse( GtkDialog * dialog, gint response, gpointer gdata )
92{
93    struct stat_ui * ui = gdata;
94
95    if( response == TR_RESPONSE_RESET )
96    {
97        const char * primary = _( "Reset your statistics?" );
98        const char * secondary = _( "These statistics are for your information only. "
99                                    "Resetting them doesn't affect the statistics logged by your BitTorrent trackers." );
100        const int flags = GTK_DIALOG_DESTROY_WITH_PARENT
101                        | GTK_DIALOG_MODAL;
102        GtkWidget * w = gtk_message_dialog_new( GTK_WINDOW( dialog ),
103                                                flags,
104                                                GTK_MESSAGE_QUESTION,
105                                                GTK_BUTTONS_NONE,
106                                                "%s", primary );
107        gtk_dialog_add_buttons( GTK_DIALOG( w ),
108                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
109                                _( "_Reset" ), TR_RESPONSE_RESET,
110                                NULL );
111        gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( w ), "%s", secondary );
112        if( gtk_dialog_run( GTK_DIALOG( w ) ) == TR_RESPONSE_RESET )
113        {
114            tr_sessionClearStats( gtr_core_session( ui->core ) );
115            updateStats( ui );
116        }
117        gtk_widget_destroy( w );
118    }
119
120    if( response == GTK_RESPONSE_CLOSE )
121        gtk_widget_destroy( GTK_WIDGET( dialog ) );
122}
123
124GtkWidget*
125gtr_stats_dialog_new( GtkWindow * parent, TrCore * core )
126{
127    guint i;
128    GtkWidget * d;
129    GtkWidget * t;
130    GtkWidget * l;
131    guint row = 0;
132    struct stat_ui * ui = g_new0( struct stat_ui, 1 );
133
134    d = gtk_dialog_new_with_buttons( _( "Statistics" ),
135                                     parent,
136                                     GTK_DIALOG_DESTROY_WITH_PARENT,
137                                     _( "_Reset" ), TR_RESPONSE_RESET,
138                                     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
139                                     NULL );
140    gtk_dialog_set_default_response( GTK_DIALOG( d ),
141                                     GTK_RESPONSE_CLOSE );
142    gtk_dialog_set_alternative_button_order( GTK_DIALOG( d ),
143                                             GTK_RESPONSE_CLOSE,
144                                             TR_RESPONSE_RESET,
145                                             -1 );
146    t = hig_workarea_create( );
147    ui->core = core;
148
149    hig_workarea_add_section_title( t, &row, _( "Current Session" ) );
150    l = ui->one_up_lb = gtk_label_new( NULL );
151    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
152    hig_workarea_add_row( t, &row, _( "Uploaded:" ), l, NULL );
153    l = ui->one_down_lb = gtk_label_new( NULL );
154    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
155    hig_workarea_add_row( t, &row, _( "Downloaded:" ), l, NULL );
156    l = ui->one_ratio_lb = gtk_label_new( NULL );
157    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
158    hig_workarea_add_row( t, &row, _( "Ratio:" ), l, NULL );
159    l = ui->one_time_lb = gtk_label_new( NULL );
160    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
161    hig_workarea_add_row( t, &row, _( "Duration:" ), l, NULL );
162    hig_workarea_add_section_divider( t, &row );
163    hig_workarea_add_section_title( t, &row, _( "Total" ) );
164    l = ui->all_sessions_lb = gtk_label_new( _( "Started %'d time" ) );
165    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
166    hig_workarea_add_label_w( t, row++, l );
167    l = ui->all_up_lb = gtk_label_new( NULL );
168    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
169    hig_workarea_add_row( t, &row, _( "Uploaded:" ), l, NULL );
170    l = ui->all_down_lb = gtk_label_new( NULL );
171    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
172    hig_workarea_add_row( t, &row, _( "Downloaded:" ), l, NULL );
173    l = ui->all_ratio_lb = gtk_label_new( NULL );
174    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
175    hig_workarea_add_row( t, &row, _( "Ratio:" ), l, NULL );
176    l = ui->all_time_lb = gtk_label_new( NULL );
177    gtk_label_set_single_line_mode( GTK_LABEL( l ), TRUE );
178    hig_workarea_add_row( t, &row, _( "Duration:" ), l, NULL );
179    gtr_dialog_set_content( GTK_DIALOG( d ), t );
180
181    updateStats( ui );
182    g_object_set_data_full( G_OBJECT( d ), "data", ui, g_free );
183    g_signal_connect( d, "response", G_CALLBACK( dialogResponse ), ui );
184    i = gdk_threads_add_timeout_seconds( SECONDARY_WINDOW_REFRESH_INTERVAL_SECONDS, updateStats, ui );
185    g_object_weak_ref( G_OBJECT( d ), dialogDestroyed, GUINT_TO_POINTER( i ) );
186    return d;
187}
188