From 1083535d9ba03e2124e23c5849df46f7ba9c7eec Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 7 Aug 2009 20:49:06 +0000 Subject: [PATCH] (trunk gtk) fix #2292: wrong speed in bottom bar --- gtk/torrent-cell-renderer.c | 112 ++++++++++++++++++++---------------- gtk/tr-core.c | 78 ++++++++++++++++--------- gtk/tr-core.h | 2 + gtk/tr-window.c | 27 ++++++--- 4 files changed, 137 insertions(+), 82 deletions(-) diff --git a/gtk/torrent-cell-renderer.c b/gtk/torrent-cell-renderer.c index 107e0a762..bdc9f3553 100644 --- a/gtk/torrent-cell-renderer.c +++ b/gtk/torrent-cell-renderer.c @@ -27,6 +27,8 @@ enum { P_TORRENT = 1, + P_UPLOAD_SPEED, + P_DOWNLOAD_SPEED, P_BAR_HEIGHT, P_MINIMAL }; @@ -128,7 +130,9 @@ getProgressString( const tr_torrent * tor, static char* getShortTransferString( const tr_stat * torStat, - char * buf, + double uploadSpeed, + double downloadSpeed, + char * buf, size_t buflen ) { char downStr[32], upStr[32]; @@ -136,9 +140,9 @@ getShortTransferString( const tr_stat * torStat, const int haveUp = torStat->peersGettingFromUs > 0; if( haveDown ) - tr_strlspeed( downStr, torStat->pieceDownloadSpeed, sizeof( downStr ) ); + tr_strlspeed( downStr, downloadSpeed, sizeof( downStr ) ); if( haveUp ) - tr_strlspeed( upStr, torStat->pieceUploadSpeed, sizeof( upStr ) ); + tr_strlspeed( upStr, uploadSpeed, sizeof( upStr ) ); if( haveDown && haveUp ) /* Translators: "speed|" is here for disambiguation. Please remove it from your translation. @@ -160,7 +164,9 @@ getShortTransferString( const tr_stat * torStat, } static char* -getShortStatusString( const tr_stat * torStat ) +getShortStatusString( const tr_stat * torStat, + double uploadSpeed, + double downloadSpeed ) { GString * gstr = g_string_new( NULL ); @@ -190,7 +196,7 @@ getShortStatusString( const tr_stat * torStat ) g_string_append_printf( gstr, _( "Ratio: %s" ), buf ); g_string_append( gstr, ", " ); } - getShortTransferString( torStat, buf, sizeof( buf ) ); + getShortTransferString( torStat, uploadSpeed, downloadSpeed, buf, sizeof( buf ) ); g_string_append( gstr, buf ); break; } @@ -203,7 +209,9 @@ getShortStatusString( const tr_stat * torStat ) } static char* -getStatusString( const tr_stat * torStat ) +getStatusString( const tr_stat * torStat, + const double uploadSpeed, + const double downloadSpeed ) { const int isActive = torStat->activity != TR_STATUS_STOPPED; const int isChecking = torStat->activity == TR_STATUS_CHECK @@ -224,7 +232,7 @@ getStatusString( const tr_stat * torStat ) case TR_STATUS_CHECK_WAIT: case TR_STATUS_CHECK: { - char * pch = getShortStatusString( torStat ); + char * pch = getShortStatusString( torStat, uploadSpeed, downloadSpeed ); g_string_assign( gstr, pch ); g_free( pch ); break; @@ -254,7 +262,7 @@ getStatusString( const tr_stat * torStat ) if( isActive && !isChecking ) { char buf[256]; - getShortTransferString( torStat, buf, sizeof( buf ) ); + getShortTransferString( torStat, uploadSpeed, downloadSpeed, buf, sizeof( buf ) ); g_string_append_printf( gstr, " - %s", buf ); } @@ -274,8 +282,18 @@ struct TorrentCellRendererPrivate GtkCellRenderer * text_renderer_err; GtkCellRenderer * progress_renderer; GtkCellRenderer * icon_renderer; - int bar_height; - gboolean minimal; + int bar_height; + + /* use this instead of tr_stat.pieceUploadSpeed so that the model can + control when the speed displays get updated. this is done to keep + the individual torrents' speeds and the status bar's overall speed + in sync even if they refresh at slightly different times */ + int upload_speed; + + /* @see upload_speed */ + int download_speed; + + gboolean minimal; }; /*** @@ -327,7 +345,7 @@ get_size_minimal( TorrentCellRenderer * cell, icon = get_icon( tor, MINIMAL_ICON_SIZE, widget ); name = tr_torrentInfo( tor )->name; - status = getShortStatusString( st ); + status = getShortStatusString( st, p->upload_speed, p->download_speed ); /* get the idealized cell dimensions */ g_object_set( p->icon_renderer, "pixbuf", icon, NULL ); @@ -384,7 +402,7 @@ get_size_full( TorrentCellRenderer * cell, icon = get_icon( tor, FULL_ICON_SIZE, widget ); name = inf->name; - status = getStatusString( st ); + status = getStatusString( st, p->upload_speed, p->download_speed ); progress = getProgressString( tor, inf, st ); /* get the idealized cell dimensions */ @@ -487,7 +505,7 @@ render_minimal( TorrentCellRenderer * cell, icon = get_icon( tor, MINIMAL_ICON_SIZE, widget ); name = tr_torrentInfo( tor )->name; - status = getShortStatusString( st ); + status = getShortStatusString( st, p->upload_speed, p->download_speed ); /* get the cell dimensions */ g_object_set( p->icon_renderer, "pixbuf", icon, NULL ); @@ -582,7 +600,7 @@ render_full( TorrentCellRenderer * cell, icon = get_icon( tor, FULL_ICON_SIZE, widget ); name = inf->name; - status = getStatusString( st ); + status = getStatusString( st, p->upload_speed, p->download_speed ); progress = getProgressString( tor, inf, st ); /* get the idealized cell dimensions */ @@ -691,56 +709,42 @@ torrent_cell_renderer_render( GtkCellRenderer * cell, } static void -torrent_cell_renderer_set_property( GObject * object, +torrent_cell_renderer_set_property( GObject * object, guint property_id, const GValue * v, - GParamSpec * pspec ) + GParamSpec * pspec ) { - TorrentCellRenderer * self = TORRENT_CELL_RENDERER( - object ); + TorrentCellRenderer * self = TORRENT_CELL_RENDERER( object ); struct TorrentCellRendererPrivate * p = self->priv; switch( property_id ) { - case P_TORRENT: - p->tor = g_value_get_pointer( v ); break; - - case P_BAR_HEIGHT: - p->bar_height = g_value_get_int( v ); break; - - case P_MINIMAL: - p->minimal = g_value_get_boolean( v ); break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec ); - break; + case P_TORRENT: p->tor = g_value_get_pointer( v ); break; + case P_UPLOAD_SPEED: p->upload_speed = g_value_get_int( v ); break; + case P_DOWNLOAD_SPEED: p->download_speed = g_value_get_int( v ); break; + case P_BAR_HEIGHT: p->bar_height = g_value_get_int( v ); break; + case P_MINIMAL: p->minimal = g_value_get_boolean( v ); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec ); break; } } static void -torrent_cell_renderer_get_property( GObject * object, - guint property_id, - GValue * v, - GParamSpec * pspec ) +torrent_cell_renderer_get_property( GObject * object, + guint property_id, + GValue * v, + GParamSpec * pspec ) { - const TorrentCellRenderer * self = TORRENT_CELL_RENDERER( - object ); + const TorrentCellRenderer * self = TORRENT_CELL_RENDERER( object ); struct TorrentCellRendererPrivate * p = self->priv; switch( property_id ) { - case P_TORRENT: - g_value_set_pointer( v, p->tor ); break; - - case P_BAR_HEIGHT: - g_value_set_int( v, p->bar_height ); break; - - case P_MINIMAL: - g_value_set_boolean( v, p->minimal ); break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec ); - break; + case P_TORRENT: g_value_set_pointer( v, p->tor ); break; + case P_UPLOAD_SPEED: g_value_set_int( v, p->upload_speed ); break; + case P_DOWNLOAD_SPEED: g_value_set_int( v, p->download_speed ); break; + case P_BAR_HEIGHT: g_value_set_int( v, p->bar_height ); break; + case P_MINIMAL: g_value_set_boolean( v, p->minimal ); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec ); break; } } @@ -785,6 +789,18 @@ torrent_cell_renderer_class_init( TorrentCellRendererClass * klass ) "tr_torrent*", G_PARAM_READWRITE ) ); + g_object_class_install_property( gobject_class, P_UPLOAD_SPEED, + g_param_spec_int( "piece-upload-speed", NULL, + "tr_stat.pieceUploadSpeed", + 0, INT_MAX, 0, + G_PARAM_READWRITE ) ); + + g_object_class_install_property( gobject_class, P_DOWNLOAD_SPEED, + g_param_spec_int( "piece-download-speed", NULL, + "tr_stat.pieceDownloadSpeed", + 0, INT_MAX, 0, + G_PARAM_READWRITE ) ); + g_object_class_install_property( gobject_class, P_BAR_HEIGHT, g_param_spec_int( "bar-height", NULL, "Bar Height", diff --git a/gtk/tr-core.c b/gtk/tr-core.c index f2e50e4c9..ae655814c 100644 --- a/gtk/tr-core.c +++ b/gtk/tr-core.c @@ -256,20 +256,24 @@ compareByActivity( GtkTreeModel * model, GtkTreeIter * b, gpointer user_data UNUSED ) { - int i; - tr_torrent * ta, *tb; + int i, aUp, aDown, bUp, bDown; + tr_torrent *ta, *tb; const tr_stat *sa, *sb; - gtk_tree_model_get( model, a, MC_TORRENT_RAW, &ta, -1 ); - gtk_tree_model_get( model, b, MC_TORRENT_RAW, &tb, -1 ); + gtk_tree_model_get( model, a, MC_SPEED_UP, &aUp, + MC_SPEED_DOWN, &aDown, + MC_TORRENT_RAW, &ta, + -1 ); + gtk_tree_model_get( model, b, MC_SPEED_UP, &bUp, + MC_SPEED_DOWN, &bDown, + MC_TORRENT_RAW, &tb, + -1 ); + + if(( i = ((aUp+aDown)-(bUp+bDown)) )) + return i; sa = tr_torrentStatCached( ta ); sb = tr_torrentStatCached( tb ); - - if( ( i = compareDouble( sa->pieceUploadSpeed + sa->pieceDownloadSpeed, - sb->pieceUploadSpeed + sb->pieceDownloadSpeed ) ) ) - return i; - if( sa->uploadedEver != sb->uploadedEver ) return sa->uploadedEver < sa->uploadedEver ? -1 : 1; @@ -608,19 +612,19 @@ static void tr_core_init( GTypeInstance * instance, gpointer g_class UNUSED ) { - TrCore * self = (TrCore *) instance; - GtkListStore * store; + GtkListStore * store; struct TrCorePrivate * p; + TrCore * self = (TrCore *) instance; /* column types for the model used to store torrent information */ /* keep this in sync with the enum near the bottom of tr_core.h */ - GType types[] = { - G_TYPE_STRING, /* name */ - G_TYPE_STRING, /* collated name */ - TR_TORRENT_TYPE, /* TrTorrent object */ - G_TYPE_POINTER, /* tr_torrent* */ - G_TYPE_INT /* tr_stat()->status */ - }; + GType types[] = { G_TYPE_STRING, /* name */ + G_TYPE_STRING, /* collated name */ + TR_TORRENT_TYPE, /* TrTorrent object */ + G_TYPE_POINTER, /* tr_torrent* */ + G_TYPE_INT, /* tr_stat.pieceUploadSpeed */ + G_TYPE_INT, /* tr_stat.pieceDownloadSpeed */ + G_TYPE_INT }; /* tr_stat.status */ p = self->priv = G_TYPE_INSTANCE_GET_PRIVATE( self, TR_CORE_TYPE, @@ -751,7 +755,7 @@ tr_core_add_torrent( TrCore * self, gboolean doNotify ) { const tr_info * inf = tr_torrent_info( gtor ); - const tr_stat * torStat = tr_torrent_stat( gtor ); + const tr_stat * st = tr_torrent_stat( gtor ); tr_torrent * tor = tr_torrent_handle( gtor ); char * collated = doCollate( inf->name ); GtkListStore * store = GTK_LIST_STORE( tr_core_model( self ) ); @@ -762,7 +766,9 @@ tr_core_add_torrent( TrCore * self, MC_NAME_COLLATED, collated, MC_TORRENT, gtor, MC_TORRENT_RAW, tor, - MC_ACTIVITY, torStat->activity, + MC_SPEED_UP, (int)st->pieceUploadSpeed, + MC_SPEED_DOWN, (int)st->pieceDownloadSpeed, + MC_ACTIVITY, st->activity, -1 ); if( doNotify ) @@ -1023,25 +1029,43 @@ tr_core_remove_torrent( TrCore * core, ***/ static gboolean -update_foreach( GtkTreeModel * model, +update_foreach( GtkTreeModel * model, GtkTreePath * path UNUSED, - GtkTreeIter * iter, + GtkTreeIter * iter, gpointer data UNUSED ) { - int oldActivity; - int newActivity; + int oldActivity, newActivity; + int oldUpSpeed, newUpSpeed; + int oldDownSpeed, newDownSpeed; + const tr_stat * st; TrTorrent * gtor; - /* maybe update the status column in the model */ + /* get the old states */ gtk_tree_model_get( model, iter, MC_TORRENT, >or, MC_ACTIVITY, &oldActivity, + MC_SPEED_UP, &oldUpSpeed, + MC_SPEED_DOWN, &oldDownSpeed, -1 ); - newActivity = tr_torrentGetActivity( tr_torrent_handle( gtor ) ); - if( newActivity != oldActivity ) + + /* get the new states */ + st = tr_torrentStat( tr_torrent_handle( gtor ) ); + newActivity = st->activity; + newUpSpeed = st->pieceUploadSpeed; + newDownSpeed = st->pieceDownloadSpeed; + + /* updating the model triggers off resort/refresh, + so don't do it unless something's actually changed... */ + if( ( newActivity != oldActivity ) || + ( newUpSpeed != oldUpSpeed ) || + ( newDownSpeed != oldDownSpeed ) ) + { gtk_list_store_set( GTK_LIST_STORE( model ), iter, MC_ACTIVITY, newActivity, + MC_SPEED_UP, newUpSpeed, + MC_SPEED_DOWN, newDownSpeed, -1 ); + } /* cleanup */ g_object_unref( gtor ); diff --git a/gtk/tr-core.h b/gtk/tr-core.h index 48a33f8d4..23ee78aba 100644 --- a/gtk/tr-core.h +++ b/gtk/tr-core.h @@ -199,6 +199,8 @@ enum MC_NAME_COLLATED, MC_TORRENT, MC_TORRENT_RAW, + MC_SPEED_UP, + MC_SPEED_DOWN, MC_ACTIVITY, MC_ROW_COUNT }; diff --git a/gtk/tr-window.c b/gtk/tr-window.c index 01fbc648e..4a40718db 100644 --- a/gtk/tr-window.c +++ b/gtk/tr-window.c @@ -196,6 +196,8 @@ makeview( PrivateData * p, p->renderer = r = torrent_cell_renderer_new( ); gtk_tree_view_column_pack_start( col, r, FALSE ); gtk_tree_view_column_add_attribute( col, r, "torrent", MC_TORRENT_RAW ); + gtk_tree_view_column_add_attribute( col, r, "piece-upload-speed", MC_SPEED_UP ); + gtk_tree_view_column_add_attribute( col, r, "piece-download-speed", MC_SPEED_DOWN ); gtk_tree_view_append_column( GTK_TREE_VIEW( view ), col ); g_object_set( r, "xpad", GUI_PAD_SMALL, "ypad", GUI_PAD_SMALL, NULL ); @@ -1152,17 +1154,28 @@ updateSpeeds( PrivateData * p ) if( session != NULL ) { char buf[128]; - double d; + int up=0, down=0; + GtkTreeIter iter; + GtkTreeModel * model = tr_core_model( p->core ); - d = tr_sessionGetPieceSpeed( session, TR_DOWN ); - tr_strlspeed( buf, d, sizeof( buf ) ); + if( gtk_tree_model_get_iter_first( model, &iter ) ) do + { + int u, d; + gtk_tree_model_get( model, &iter, MC_SPEED_UP, &u, + MC_SPEED_DOWN, &d, + -1 ); + up += u; + down += d; + } + while( gtk_tree_model_iter_next( model, &iter ) ); + + tr_strlspeed( buf, down, sizeof( buf ) ); gtk_label_set_text( GTK_LABEL( p->dl_lb ), buf ); - g_object_set( p->dl_hbox, "visible", d>=0.01, NULL ); + g_object_set( p->dl_hbox, "visible", down>0, NULL ); - d = tr_sessionGetPieceSpeed( session, TR_UP ); - tr_strlspeed( buf, d, sizeof( buf ) ); + tr_strlspeed( buf, up, sizeof( buf ) ); gtk_label_set_text( GTK_LABEL( p->ul_lb ), buf ); - g_object_set( p->ul_hbox, "visible", d>=0.01, NULL ); + g_object_set( p->ul_hbox, "visible", up>0, NULL ); } }