diff --git a/gtk/actions.c b/gtk/actions.c
index b4c8cc921..50de23948 100644
--- a/gtk/actions.c
+++ b/gtk/actions.c
@@ -49,11 +49,12 @@ static GtkRadioActionEntry sort_radio_entries[] =
{ "sort-by-activity", NULL, N_( "Sort by _Activity" ), NULL, NULL, 0 },
{ "sort-by-name", NULL, N_( "Sort by _Name" ), NULL, NULL, 1 },
{ "sort-by-progress", NULL, N_( "Sort by _Progress" ), NULL, NULL, 2 },
- { "sort-by-ratio", NULL, N_( "Sort by Rati_o" ), NULL, NULL, 3 },
- { "sort-by-state", NULL, N_( "Sort by Stat_e" ), NULL, NULL, 4 },
- { "sort-by-age", NULL, N_( "Sort by A_ge" ), NULL, NULL, 5 },
- { "sort-by-time-left", NULL, N_( "Sort by Time _Left" ), NULL, NULL, 6 },
- { "sort-by-size", NULL, N_( "Sort by Si_ze" ), NULL, NULL, 7 }
+ { "sort-by-queue", NULL, N_( "Sort by _Queue" ), NULL, NULL, 3 },
+ { "sort-by-ratio", NULL, N_( "Sort by Rati_o" ), NULL, NULL, 4 },
+ { "sort-by-state", NULL, N_( "Sort by Stat_e" ), NULL, NULL, 5 },
+ { "sort-by-age", NULL, N_( "Sort by A_ge" ), NULL, NULL, 6 },
+ { "sort-by-time-left", NULL, N_( "Sort by Time _Left" ), NULL, NULL, 7 },
+ { "sort-by-size", NULL, N_( "Sort by Si_ze" ), NULL, NULL, 8 }
};
static void
diff --git a/gtk/main.c b/gtk/main.c
index 867959ba8..7909450d3 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -247,7 +247,6 @@ show_details_dialog_for_selected_torrents( struct cbdata * data )
struct counts_data
{
int total_count;
- int active_count;
int queued_count;
int stopped_count;
};
@@ -257,27 +256,23 @@ get_selected_torrent_counts_foreach( GtkTreeModel * model, GtkTreePath * path UN
GtkTreeIter * iter, gpointer user_data )
{
int activity = 0;
- int queuePosition = -1;
struct counts_data * counts = user_data;
++counts->total_count;
gtk_tree_model_get( model, iter, MC_ACTIVITY, &activity, -1 );
- if( activity == TR_STATUS_DOWNLOAD_WAIT )
+ if( ( activity == TR_STATUS_DOWNLOAD_WAIT ) || ( activity == TR_STATUS_SEED_WAIT ) )
++counts->queued_count;
- if( ( activity == TR_STATUS_STOPPED ) && ( queuePosition < 0 ) )
+ if( activity == TR_STATUS_STOPPED )
++counts->stopped_count;
- else
- ++counts->active_count;
}
static void
get_selected_torrent_counts( struct cbdata * data, struct counts_data * counts )
{
counts->total_count = 0;
- counts->active_count = 0;
counts->queued_count = 0;
counts->stopped_count = 0;
@@ -302,30 +297,30 @@ refresh_actions( gpointer gdata )
const size_t total = gtr_core_get_torrent_count( data->core );
const size_t active = gtr_core_get_active_torrent_count( data->core );
const int torrent_count = gtk_tree_model_iter_n_children( gtr_core_model( data->core ), NULL );
- const tr_session * session = gtr_core_session( data->core );
- const bool queue_enabled = tr_sessionGetQueueEnabled( session, TR_DOWN )
- || tr_sessionGetQueueEnabled( session, TR_UP );
+ bool has_selection;
+
+ get_selected_torrent_counts( data, &sel_counts );
+ has_selection = sel_counts.total_count > 0;
gtr_action_set_sensitive( "select-all", torrent_count != 0 );
gtr_action_set_sensitive( "deselect-all", torrent_count != 0 );
gtr_action_set_sensitive( "pause-all-torrents", active != 0 );
gtr_action_set_sensitive( "start-all-torrents", active != total );
- get_selected_torrent_counts( data, &sel_counts );
- gtr_action_set_sensitive( "torrent-stop", ( sel_counts.active_count + sel_counts.queued_count ) > 0 );
+ gtr_action_set_sensitive( "torrent-stop", ( sel_counts.stopped_count < sel_counts.total_count ) );
gtr_action_set_sensitive( "torrent-start", ( sel_counts.stopped_count ) > 0 );
gtr_action_set_sensitive( "torrent-start-now", ( sel_counts.stopped_count + sel_counts.queued_count ) > 0 );
- gtr_action_set_sensitive( "torrent-verify", sel_counts.total_count != 0 );
- gtr_action_set_sensitive( "remove-torrent", sel_counts.total_count != 0 );
- gtr_action_set_sensitive( "delete-torrent", sel_counts.total_count != 0 );
- gtr_action_set_sensitive( "relocate-torrent", sel_counts.total_count != 0 );
- gtr_action_set_sensitive( "show-torrent-properties", sel_counts.total_count != 0 );
+ gtr_action_set_sensitive( "torrent-verify", has_selection );
+ gtr_action_set_sensitive( "remove-torrent", has_selection );
+ gtr_action_set_sensitive( "delete-torrent", has_selection );
+ gtr_action_set_sensitive( "relocate-torrent", has_selection );
+ gtr_action_set_sensitive( "queue-move-top", has_selection );
+ gtr_action_set_sensitive( "queue-move-up", has_selection );
+ gtr_action_set_sensitive( "queue-move-down", has_selection );
+ gtr_action_set_sensitive( "queue-move-bottom", has_selection );
+ gtr_action_set_sensitive( "show-torrent-properties", has_selection );
gtr_action_set_sensitive( "open-torrent-folder", sel_counts.total_count == 1 );
gtr_action_set_sensitive( "copy-magnet-link-to-clipboard", sel_counts.total_count == 1 );
- gtr_action_set_sensitive( "queue-move-top", queue_enabled && ( sel_counts.queued_count > 0 ) );
- gtr_action_set_sensitive( "queue-move-up", queue_enabled && ( sel_counts.queued_count > 0 ) );
- gtr_action_set_sensitive( "queue-move-down", queue_enabled && ( sel_counts.queued_count > 0 ) );
- gtr_action_set_sensitive( "queue-move-bottom", queue_enabled && ( sel_counts.queued_count > 0 ) );
canUpdate = 0;
gtk_tree_selection_selected_foreach( data->sel, count_updatable_foreach, &canUpdate );
diff --git a/gtk/torrent-cell-renderer.c b/gtk/torrent-cell-renderer.c
index 1b1bb18e4..56900a804 100644
--- a/gtk/torrent-cell-renderer.c
+++ b/gtk/torrent-cell-renderer.c
@@ -228,11 +228,10 @@ getShortStatusString( GString * gstr,
break;
case TR_STATUS_DOWNLOAD_WAIT:
- g_string_append_printf( gstr, _( "Download queue #%d" ), st->queuePosition + 1 );
+ g_string_append( gstr, _( "Waiting to download" ) );
break;
-
case TR_STATUS_SEED_WAIT:
- g_string_append_printf( gstr, _( "Seed queue #%d" ), st->queuePosition + 1 );
+ g_string_append( gstr, _( "Waiting to seed" ) );
break;
case TR_STATUS_DOWNLOAD:
@@ -685,7 +684,7 @@ render_compact( TorrentCellRenderer * cell,
g_object_set( p->icon_renderer, "pixbuf", icon, "sensitive", sensitive, NULL );
gtr_cell_renderer_render( p->icon_renderer, window, widget, &icon_area, flags );
g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", NULL,
- "sensitive", sensitive || ( st->queuePosition >= 0 ),
+ "sensitive", sensitive,
#if GTK_CHECK_VERSION( 3,0,0 )
"inverted", seed,
#elif GTK_CHECK_VERSION( 2,6,0 )
@@ -805,7 +804,7 @@ render_full( TorrentCellRenderer * cell,
gtr_cell_renderer_render( p->text_renderer, window, widget, &name_area, flags );
g_object_set( p->text_renderer, "text", gstr_prog->str, "scale", SMALL_SCALE, "weight", PANGO_WEIGHT_NORMAL, NULL );
gtr_cell_renderer_render( p->text_renderer, window, widget, &prog_area, flags );
- g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", "", "sensitive", ( sensitive || st->queuePosition >= 0 ),
+ g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", "", "sensitive", sensitive,
#if GTK_CHECK_VERSION( 3,0,0 )
"inverted", seed,
#elif GTK_CHECK_VERSION( 2,6,0 )
diff --git a/gtk/tr-core.c b/gtk/tr-core.c
index 7c6849d9e..5bd8e71b6 100644
--- a/gtk/tr-core.c
+++ b/gtk/tr-core.c
@@ -459,12 +459,17 @@ compare_by_name( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointer us
}
static int
-compare_by_queue( const tr_stat * a, const tr_stat * b )
+compare_by_queue( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data UNUSED )
{
- const bool a_is_queued = a->queuePosition >= 0;
- const bool b_is_queued = b->queuePosition >= 0;
- if( a_is_queued != b_is_queued ) return a_is_queued ? -1 : 1;
- return b->queuePosition - a->queuePosition;
+ tr_torrent *ta, *tb;
+ const tr_stat *sa, *sb;
+
+ gtk_tree_model_get( m, a, MC_TORRENT, &ta, -1 );
+ sa = tr_torrentStatCached( ta );
+ gtk_tree_model_get( m, b, MC_TORRENT, &tb, -1 );
+ sb = tr_torrentStatCached( tb );
+
+ return sb->queuePosition - sa->queuePosition;
}
static int
@@ -480,8 +485,7 @@ compare_by_ratio( GtkTreeModel* m, GtkTreeIter * a, GtkTreeIter * b, gpointer us
sb = tr_torrentStatCached( tb );
if( !ret ) ret = compare_ratio( sa->ratio, sb->ratio );
- if( !ret ) ret = compare_by_queue( sa, sb );
- if( !ret ) ret = compare_by_name( m, a, b, user_data );
+ if( !ret ) ret = compare_by_queue( m, a, b, user_data );
return ret;
}
@@ -506,8 +510,7 @@ compare_by_activity( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointe
if( !ret ) ret = compare_double( aUp+aDown, bUp+bDown );
if( !ret ) ret = compare_uint64( sa->uploadedEver, sb->uploadedEver );
- if( !ret ) ret = compare_by_queue( sa, sb );
- if( !ret ) ret = compare_by_name( m, a, b, user_data );
+ if( !ret ) ret = compare_by_queue( m, a, b, user_data );
return ret;
}
@@ -587,8 +590,7 @@ compare_by_state( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointer u
gtk_tree_model_get( m, b, MC_ACTIVITY, &sb, MC_TORRENT, &tb, -1 );
if( !ret ) ret = compare_int( sa, sb );
- if( !ret ) ret = compare_by_queue( tr_torrentStatCached( ta ), tr_torrentStatCached( tb ) );
- if( !ret ) ret = compare_by_progress( m, a, b, u );
+ if( !ret ) ret = compare_by_queue( m, a, b, u );
return ret;
}
@@ -606,6 +608,8 @@ core_set_sort_mode( TrCore * core, const char * mode, gboolean is_reversed )
sort_func = compare_by_age;
else if( !strcmp( mode, "sort-by-progress" ) )
sort_func = compare_by_progress;
+ else if( !strcmp( mode, "sort-by-queue" ) )
+ sort_func = compare_by_queue;
else if( !strcmp( mode, "sort-by-time-left" ) )
sort_func = compare_by_eta;
else if( !strcmp( mode, "sort-by-ratio" ) )
diff --git a/gtk/ui.h b/gtk/ui.h
index 3f998c559..2ea24c41a 100644
--- a/gtk/ui.h
+++ b/gtk/ui.h
@@ -50,6 +50,7 @@ static const char * fallback_ui_file =
" \n"
" \n"
" \n"
+ " \n"
" \n"
" \n"
" \n"
diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c
index 2caa9a76c..a4b784f6b 100644
--- a/libtransmission/rpcimpl.c
+++ b/libtransmission/rpcimpl.c
@@ -313,7 +313,7 @@ torrentStop( tr_session * session,
{
tr_torrent * tor = torrents[i];
- if( tor->isRunning || ( tor->queuePosition >= 0 ) )
+ if( tor->isRunning || tr_torrentIsQueued( tor ) )
{
tor->isStopping = true;
notify( session, TR_RPC_TORRENT_STOPPED, tor );
diff --git a/libtransmission/session.c b/libtransmission/session.c
index 148ab8631..430d233be 100644
--- a/libtransmission/session.c
+++ b/libtransmission/session.c
@@ -2692,13 +2692,19 @@ tr_sessionGetNextQueuedTorrent( tr_session * session, tr_direction direction )
assert( tr_isSession( session ) );
assert( tr_isDirection( direction ) );
- while(( tor = tr_torrentNext( session, tor ))) {
- if( !tor->isRunning && ( direction == tr_torrentGetQueueDirection( tor ) ) ) {
- const int position = tr_torrentGetQueuePosition( tor );
- if( ( position >= 0 ) && ( best_position > position ) ) {
- best_position = position;
- best_tor = tor;
- }
+ while(( tor = tr_torrentNext( session, tor )))
+ {
+ int position;
+
+ if( !tr_torrentIsQueued( tor ) )
+ continue;
+ if( direction != tr_torrentGetQueueDirection( tor ) )
+ continue;
+
+ position = tr_torrentGetQueuePosition( tor );
+ if( best_position > position ) {
+ best_position = position;
+ best_tor = tor;
}
}
@@ -2711,7 +2717,7 @@ tr_sessionCountQueueFreeSlots( tr_session * session, tr_direction dir )
tr_torrent * tor;
int active_count;
const int max = tr_sessionGetQueueSize( session, dir );
- const tr_torrent_activity activity = TR_UP ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
+ const tr_torrent_activity activity = dir == TR_UP ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
if( !tr_sessionGetQueueEnabled( session, dir ) )
return INT_MAX;
diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c
index a2278fb34..321f885b3 100644
--- a/libtransmission/torrent.c
+++ b/libtransmission/torrent.c
@@ -802,7 +802,7 @@ torrentInit( tr_torrent * tor, const tr_ctor * ctor )
tor->session = session;
tor->uniqueId = nextUniqueId++;
tor->magicNumber = TORRENT_MAGIC_NUMBER;
- tor->queuePosition = -1;
+ tor->queuePosition = session->torrentCount;
tr_peerIdInit( tor->peer_id );
@@ -870,7 +870,7 @@ torrentInit( tr_torrent * tor, const tr_ctor * ctor )
}
/* add the torrent to tr_session.torrentList */
- ++session->torrentCount;
+ session->torrentCount++;
if( session->torrentList == NULL )
session->torrentList = tor;
else {
@@ -1105,7 +1105,7 @@ torrentGetActivity( const tr_torrent * tor )
if( tor->isRunning )
return is_seed ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
- if( tor->queuePosition >= 0 ) {
+ if( tr_torrentIsQueued( tor ) ) {
if( is_seed && tr_sessionGetQueueEnabled( tor->session, TR_UP ) )
return TR_STATUS_SEED_WAIT;
if( !is_seed && tr_sessionGetQueueEnabled( tor->session, TR_DOWN ) )
@@ -1496,12 +1496,15 @@ tr_torrentSetHasPiece( tr_torrent * tor,
****
***/
+static bool queueIsSequenced( tr_session * );
+
static void
freeTorrent( tr_torrent * tor )
{
tr_torrent * t;
tr_session * session = tor->session;
tr_info * inf = &tor->info;
+ const time_t now = tr_time( );
assert( !tor->isRunning );
@@ -1525,9 +1528,20 @@ freeTorrent( tr_torrent * tor )
}
}
+ /* decrement the torrent count */
assert( session->torrentCount >= 1 );
session->torrentCount--;
+ /* resequence the queue positions */
+ t = NULL;
+ while(( t = tr_torrentNext( session, tor ))) {
+ if( t->queuePosition > tor->queuePosition ) {
+ t->queuePosition--;
+ t->anyDate = now;
+ }
+ }
+ assert( queueIsSequenced( session ) );
+
tr_bandwidthDestruct( &tor->bandwidth );
tr_metainfoFree( inf );
@@ -1540,7 +1554,7 @@ freeTorrent( tr_torrent * tor )
*** Start/Stop Callback
**/
-static void queueRemove( tr_torrent * tor );
+static void torrentSetQueued( tr_torrent * tor, bool queued );
static void
torrentStartImpl( void * vtor )
@@ -1553,7 +1567,7 @@ torrentStartImpl( void * vtor )
tr_sessionLock( tor->session );
tr_torrentRecheckCompleteness( tor );
- queueRemove( tor );
+ torrentSetQueued( tor, false );
now = tr_time( );
tor->isRunning = true;
@@ -1602,8 +1616,6 @@ torrentShouldQueue( const tr_torrent * tor )
return tr_sessionCountQueueFreeSlots( tor->session, dir ) == 0;
}
-static void queueAppend( tr_torrent * tor );
-
static void
torrentStart( tr_torrent * tor, bool bypass_queue )
{
@@ -1630,7 +1642,7 @@ torrentStart( tr_torrent * tor, bool bypass_queue )
case TR_STATUS_STOPPED:
if( !bypass_queue && torrentShouldQueue( tor ) ) {
- queueAppend( tor );
+ torrentSetQueued( tor, true );
return;
}
break;
@@ -1754,7 +1766,7 @@ stopTorrent( void * vtor )
tr_torrentLock( tor );
tr_verifyRemove( tor );
- queueRemove( tor );
+ torrentSetQueued( tor, false );
tr_peerMgrStopTorrent( tor );
tr_announcerTorrentStopped( tor );
tr_cacheFlushTorrent( tor->session->cache, tor );
@@ -3174,31 +3186,28 @@ compareTorrentByQueuePosition( const void * va, const void * vb )
}
static bool
-queueIsSequenced( tr_torrent * tor )
+queueIsSequenced( tr_session * session )
{
int i ;
int n ;
bool is_sequenced = true;
- tr_session * session = tor->session;
- tr_direction direction = tr_torrentGetQueueDirection( tor );
+ tr_torrent * tor;
tr_torrent ** tmp = tr_new( tr_torrent *, session->torrentCount );
- /* get all the torrents in that queue */
+ /* get all the torrents */
n = 0;
tor = NULL;
while(( tor = tr_torrentNext( session, tor )))
- if( tr_torrentIsQueued( tor ) && ( direction == tr_torrentGetQueueDirection( tor ) ) )
- tmp[n++] = tor;
+ tmp[n++] = tor;
/* sort them by position */
qsort( tmp, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
#if 0
- /* print them */
- fprintf( stderr, "sequence: " );
+ fprintf( stderr, "%s", "queue: " );
for( i=0; iqueuePosition );
- fprintf( stderr, "\n" );
+ fputc( '\n', stderr );
#endif
/* test them */
@@ -3219,48 +3228,41 @@ tr_torrentGetQueuePosition( const tr_torrent * tor )
void
tr_torrentSetQueuePosition( tr_torrent * tor, int pos )
{
- if( tr_torrentIsQueued( tor ) )
+ int back = -1;
+ tr_torrent * walk;
+ const int old_pos = tor->queuePosition;
+ const time_t now = tr_time( );
+
+ if( pos < 0 )
+ pos = 0;
+
+ tor->queuePosition = -1;
+
+ walk = NULL;
+ while(( walk = tr_torrentNext( tor->session, walk )))
{
- int back = -1;
- tr_torrent * walk;
- const tr_direction direction = tr_torrentGetQueueDirection( tor );
- const int old_pos = tor->queuePosition;
- const time_t now = tr_time( );
-
- if( pos < 0 )
- pos = 0;
-
- tor->queuePosition = -1;
-
- walk = NULL;
- while(( walk = tr_torrentNext( tor->session, walk )))
- {
- if( tr_torrentIsQueued( walk ) && ( tr_torrentGetQueueDirection( walk ) == direction ) )
- {
- if( old_pos < pos ) {
- if( ( old_pos <= walk->queuePosition ) && ( walk->queuePosition <= pos ) ) {
- walk->queuePosition--;
- walk->anyDate = now;
- }
- }
-
- if( old_pos > pos ) {
- if( ( pos <= walk->queuePosition ) && ( walk->queuePosition < old_pos ) ) {
- walk->queuePosition++;
- walk->anyDate = now;
- }
- }
-
- if( back < walk->queuePosition )
- back = walk->queuePosition;
+ if( old_pos < pos ) {
+ if( ( old_pos <= walk->queuePosition ) && ( walk->queuePosition <= pos ) ) {
+ walk->queuePosition--;
+ walk->anyDate = now;
}
}
- tor->queuePosition = MIN( pos, (back+1) );
- tor->anyDate = now;
+ if( old_pos > pos ) {
+ if( ( pos <= walk->queuePosition ) && ( walk->queuePosition < old_pos ) ) {
+ walk->queuePosition++;
+ walk->anyDate = now;
+ }
+ }
+
+ if( back < walk->queuePosition )
+ back = walk->queuePosition;
}
- assert( queueIsSequenced( tor ) );
+ tor->queuePosition = MIN( pos, (back+1) );
+ tor->anyDate = now;
+
+ assert( queueIsSequenced( tor->session ) );
}
void
@@ -3307,63 +3309,15 @@ tr_torrentsQueueMoveBottom( tr_torrent ** torrents_in, int n )
tr_free( torrents );
}
-/* Ensure that the torrents queued for downloads have queuePositions contiguous from [0...n] */
static void
-queueResequence( tr_session * session, tr_direction direction )
+torrentSetQueued( tr_torrent * tor, bool queued )
{
- int i;
- int n;
- tr_torrent * tor = NULL;
- tr_torrent ** tmp = tr_new( tr_torrent *, session->torrentCount );
- const time_t now = tr_time( );
+ assert( tr_isTorrent( tor ) );
+ assert( tr_isBool( queued ) );
- assert( tr_isSession( session ) );
- assert( tr_isDirection( direction ) );
-
- /* get all the torrents in that queue */
- n = 0;
- while(( tor = tr_torrentNext( session, tor ))) {
- if( direction == tr_torrentGetQueueDirection( tor )) {
- const int position = tr_torrentGetQueuePosition( tor );
- if( position >= 0 )
- tmp[n++] = tor;
- }
- }
-
- /* sort them by position */
- qsort( tmp, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
-
- /* sequence them... */
- for( i=0; iqueuePosition != i ) {
- tor->queuePosition = i;
- tor->anyDate = now;
- }
- }
-
- tr_free( tmp );
-}
-
-static void
-queueRemove( tr_torrent * tor )
-{
- if( tr_torrentIsQueued( tor ) )
+ if( tr_torrentIsQueued( tor ) != queued )
{
- tor->queuePosition = -1;
- queueResequence( tor->session, tr_torrentGetQueueDirection( tor ) );
- }
-}
-
-static void
-queueAppend( tr_torrent * tor )
-{
- if( !tr_torrentIsQueued( tor ) )
- {
- /* tr_torrentSetQueuePosition() requres the torrent to be queued,
- so init tor->queuePosition to the back... */
- tor->queuePosition = INT_MAX;
-
- tr_torrentSetQueuePosition( tor, INT_MAX );
+ tor->isQueued = queued;
+ tor->anyDate = tr_time( );
}
}
diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h
index 8732bc468..79112fb2d 100644
--- a/libtransmission/torrent.h
+++ b/libtransmission/torrent.h
@@ -241,6 +241,7 @@ struct tr_torrent
bool isDeleting;
bool startAfterVerify;
bool isDirty;
+ bool isQueued;
bool infoDictOffsetIsCached;
@@ -433,7 +434,7 @@ bool tr_torrentIsStalled( const tr_torrent * tor );
static inline bool
tr_torrentIsQueued( const tr_torrent * tor )
{
- return tor->queuePosition >= 0;
+ return tor->isQueued;
}
static inline tr_direction
diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h
index 66fab0de1..16000557c 100644
--- a/libtransmission/transmission.h
+++ b/libtransmission/transmission.h
@@ -1997,8 +1997,8 @@ typedef struct tr_stat
As a result, only paused torrents can be finished. */
bool finished;
- /** The position of this torrent in the download queue.
- This will be >= 0 if the torrent is queued; -1 otherwise. */
+ /** This torrent's queue position.
+ All torrents have a queue position, even if it's not queued. */
int queuePosition;
/** True if the torrent is running, but has been idle for long enough
diff --git a/qt/filters.cc b/qt/filters.cc
index 64e9855d0..d2122f638 100644
--- a/qt/filters.cc
+++ b/qt/filters.cc
@@ -39,6 +39,7 @@ const QString SortMode::names[NUM_MODES] = {
"sort-by-eta",
"sort-by-name",
"sort-by-progress",
+ "sort-by-queue"
"sort-by-ratio",
"sort-by-size",
"sort-by-state",
diff --git a/qt/filters.h b/qt/filters.h
index 2bb42aee1..f41317387 100644
--- a/qt/filters.h
+++ b/qt/filters.h
@@ -42,7 +42,7 @@ class SortMode
SortMode( const QString& name ): myMode(modeFromName(name)) { }
static const QString names[];
enum { SORT_BY_ACTIVITY, SORT_BY_AGE, SORT_BY_ETA, SORT_BY_NAME,
- SORT_BY_PROGRESS, SORT_BY_RATIO, SORT_BY_SIZE,
+ SORT_BY_PROGRESS, SORT_BY_QUEUE, SORT_BY_RATIO, SORT_BY_SIZE,
SORT_BY_STATE, SORT_BY_ID, NUM_MODES };
static int modeFromName( const QString& name );
static const QString& nameFromMode( int mode );
diff --git a/qt/mainwin.cc b/qt/mainwin.cc
index ba6a87350..88873fb04 100644
--- a/qt/mainwin.cc
+++ b/qt/mainwin.cc
@@ -140,6 +140,7 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode
connect( ui.action_SortByETA, SIGNAL(toggled(bool)), this, SLOT(onSortByETAToggled(bool)));
connect( ui.action_SortByName, SIGNAL(toggled(bool)), this, SLOT(onSortByNameToggled(bool)));
connect( ui.action_SortByProgress, SIGNAL(toggled(bool)), this, SLOT(onSortByProgressToggled(bool)));
+ connect( ui.action_SortByQueue, SIGNAL(toggled(bool)), this, SLOT(onSortByQueueToggled(bool)));
connect( ui.action_SortByRatio, SIGNAL(toggled(bool)), this, SLOT(onSortByRatioToggled(bool)));
connect( ui.action_SortBySize, SIGNAL(toggled(bool)), this, SLOT(onSortBySizeToggled(bool)));
connect( ui.action_SortByState, SIGNAL(toggled(bool)), this, SLOT(onSortByStateToggled(bool)));
@@ -520,6 +521,7 @@ void TrMainWindow :: onSortByAgeToggled ( bool b ) { if( b ) setSortPref( S
void TrMainWindow :: onSortByETAToggled ( bool b ) { if( b ) setSortPref( SortMode::SORT_BY_ETA ); }
void TrMainWindow :: onSortByNameToggled ( bool b ) { if( b ) setSortPref( SortMode::SORT_BY_NAME ); }
void TrMainWindow :: onSortByProgressToggled ( bool b ) { if( b ) setSortPref( SortMode::SORT_BY_PROGRESS ); }
+void TrMainWindow :: onSortByQueueToggled ( bool b ) { if( b ) setSortPref( SortMode::SORT_BY_QUEUE ); }
void TrMainWindow :: onSortByRatioToggled ( bool b ) { if( b ) setSortPref( SortMode::SORT_BY_RATIO ); }
void TrMainWindow :: onSortBySizeToggled ( bool b ) { if( b ) setSortPref( SortMode::SORT_BY_SIZE ); }
void TrMainWindow :: onSortByStateToggled ( bool b ) { if( b ) setSortPref( SortMode::SORT_BY_STATE ); }
@@ -758,10 +760,10 @@ TrMainWindow :: refreshActionSensitivity( )
ui.action_Pause->setEnabled( selectedAndPaused < selected );
ui.action_Announce->setEnabled( selected > 0 && ( canAnnounce == selected ) );
- ui.action_QueueMoveTop->setEnabled( selectedAndQueued > 0 );
- ui.action_QueueMoveUp->setEnabled( selectedAndQueued > 0 );
- ui.action_QueueMoveDown->setEnabled( selectedAndQueued > 0 );
- ui.action_QueueMoveBottom->setEnabled( selectedAndQueued > 0 );
+ ui.action_QueueMoveTop->setEnabled( haveSelection );
+ ui.action_QueueMoveUp->setEnabled( haveSelection );
+ ui.action_QueueMoveDown->setEnabled( haveSelection );
+ ui.action_QueueMoveBottom->setEnabled( haveSelection );
if( myDetailsDialog )
myDetailsDialog->setIds( getSelectedTorrents( ) );
@@ -959,6 +961,7 @@ TrMainWindow :: refreshPref( int key )
ui.action_SortByETA->setChecked ( i == SortMode::SORT_BY_ETA );
ui.action_SortByName->setChecked ( i == SortMode::SORT_BY_NAME );
ui.action_SortByProgress->setChecked ( i == SortMode::SORT_BY_PROGRESS );
+ ui.action_SortByQueue->setChecked ( i == SortMode::SORT_BY_QUEUE );
ui.action_SortByRatio->setChecked ( i == SortMode::SORT_BY_RATIO );
ui.action_SortBySize->setChecked ( i == SortMode::SORT_BY_SIZE );
ui.action_SortByState->setChecked ( i == SortMode::SORT_BY_STATE );
diff --git a/qt/mainwin.h b/qt/mainwin.h
index 6147c164c..5218f6b6c 100644
--- a/qt/mainwin.h
+++ b/qt/mainwin.h
@@ -138,6 +138,7 @@ class TrMainWindow: public QMainWindow
void onSortByETAToggled ( bool );
void onSortByNameToggled ( bool );
void onSortByProgressToggled ( bool );
+ void onSortByQueueToggled ( bool );
void onSortByRatioToggled ( bool );
void onSortBySizeToggled ( bool );
void onSortByStateToggled ( bool );
diff --git a/qt/mainwin.ui b/qt/mainwin.ui
index 78e5bce76..1ebddd3e5 100644
--- a/qt/mainwin.ui
+++ b/qt/mainwin.ui
@@ -126,6 +126,7 @@
+
@@ -632,6 +633,14 @@
Move to &Bottom
+
+
+ true
+
+
+ Sort by &Queue
+
+
diff --git a/qt/torrent-filter.cc b/qt/torrent-filter.cc
index 45f4ccace..c71d32114 100644
--- a/qt/torrent-filter.cc
+++ b/qt/torrent-filter.cc
@@ -85,6 +85,9 @@ TorrentFilter :: lessThan( const QModelIndex& left, const QModelIndex& right ) c
switch( myPrefs.get(Prefs::SORT_MODE).mode() )
{
+ case SortMode :: SORT_BY_QUEUE:
+ if( !val ) val = -compare( a->queuePosition(), b->queuePosition() );
+ break;
case SortMode :: SORT_BY_SIZE:
if( !val ) val = compare( a->sizeWhenDone(), b->sizeWhenDone() );
break;
@@ -101,12 +104,12 @@ TorrentFilter :: lessThan( const QModelIndex& left, const QModelIndex& right ) c
case SortMode :: SORT_BY_STATE:
if( !val ) val = compare( a->hasError(), b->hasError() );
if( !val ) val = compare( a->getActivity(), b->getActivity() );
- if( !val ) val = a->compareQueue( *b );
+ if( !val ) val = -compare( a->queuePosition(), b->queuePosition() );
// fall through
case SortMode :: SORT_BY_PROGRESS:
if( !val ) val = compare( a->percentComplete(), b->percentComplete() );
if( !val ) val = a->compareSeedRatio( *b );
- if( !val ) val = a->compareQueue( *b );
+ if( !val ) val = -compare( a->queuePosition(), b->queuePosition() );
case SortMode :: SORT_BY_RATIO:
if( !val ) val = a->compareRatio( *b );
break;
diff --git a/qt/torrent.cc b/qt/torrent.cc
index 038f9cf04..d87902248 100644
--- a/qt/torrent.cc
+++ b/qt/torrent.cc
@@ -370,18 +370,6 @@ Torrent :: hasTrackerSubstring( const QString& substr ) const
return false;
}
-int
-Torrent :: compareQueue( const Torrent& that ) const
-{
- const bool a_is_queued = isQueued( );
- const bool b_is_queued = that.isQueued( );
-
- if( a_is_queued != b_is_queued )
- return a_is_queued ? -1 : 1;
-
- return that.queuePosition() - queuePosition();
-}
-
int
Torrent :: compareSeedRatio( const Torrent& that ) const
{
@@ -718,10 +706,10 @@ Torrent :: activityString( ) const
case TR_STATUS_STOPPED: str = isFinished() ? tr( "Finished" ): tr( "Paused" ); break;
case TR_STATUS_CHECK_WAIT: str = tr( "Waiting to verify local data" ); break;
case TR_STATUS_CHECK: str = tr( "Verifying local data" ); break;
- case TR_STATUS_DOWNLOAD_WAIT: str = tr( "Download queue #%1" ).arg( queuePosition() + 1 ); break;
- case TR_STATUS_DOWNLOAD: str = tr( "Downloading" );
- case TR_STATUS_SEED_WAIT: str = tr( "Seed queue #%1" ).arg( queuePosition() + 1 ); break;
- case TR_STATUS_SEED: str = tr( "Seeding" ); break;
+ case TR_STATUS_DOWNLOAD_WAIT: str = tr( "Waiting to download" ); break;
+ case TR_STATUS_DOWNLOAD: str = tr( "Downloading" ); break;
+ case TR_STATUS_SEED_WAIT: str = tr( "Queued" ); break;
+ case TR_STATUS_SEED: str = tr( "Waiting to seed" ); break;
}
return str;
diff --git a/qt/torrent.h b/qt/torrent.h
index 2e5796fd7..5e05de5d5 100644
--- a/qt/torrent.h
+++ b/qt/torrent.h
@@ -273,7 +273,6 @@ class Torrent: public QObject
int compareTracker( const Torrent& ) const;
int compareSeedRatio( const Torrent& ) const;
int compareRatio( const Torrent& ) const;
- int compareQueue( const Torrent& ) const;
int compareETA( const Torrent& ) const;
bool hasETA( ) const { return getETA( ) >= 0; }
int getETA( ) const { return getInt( ETA ); }
@@ -308,7 +307,6 @@ class Torrent: public QObject
PeerList peers( ) const{ return myValues[PEERS].value(); }
const FileList& files( ) const { return myFiles; }
int queuePosition( ) const { return getInt( QUEUE_POSITION ); }
- bool isQueued( ) const { return queuePosition( ) >= 0; }
bool isStalled( ) const { return getBool( IS_STALLED ); }
public:
@@ -323,6 +321,7 @@ class Torrent: public QObject
bool isSeeding( ) const { return getActivity( ) == TR_STATUS_SEED; }
bool isWaitingToSeed( ) const { return getActivity( ) == TR_STATUS_SEED_WAIT; }
bool isReadyToTransfer( ) const { return getActivity()==TR_STATUS_DOWNLOAD || getActivity()==TR_STATUS_SEED; }
+ bool isQueued( ) const { return isWaitingToDownload() || isWaitingToSeed(); }
void notifyComplete( ) const;
public:
diff --git a/web/index.html b/web/index.html
index b8df0e961..bff9a4576 100755
--- a/web/index.html
+++ b/web/index.html
@@ -526,6 +526,7 @@
Name
Progress
Ratio
+ Queue Order
State
Reverse Sort Order
diff --git a/web/javascript/common.js b/web/javascript/common.js
index bfb28a62b..d8be8497c 100644
--- a/web/javascript/common.js
+++ b/web/javascript/common.js
@@ -233,6 +233,7 @@ Prefs._SortMethod = 'sort_method';
Prefs._SortByAge = 'age';
Prefs._SortByActivity = 'activity';
Prefs._SortByName = 'name';
+Prefs._SortByQueue = 'queue_order';
Prefs._SortByProgress = 'percent_completed';
Prefs._SortByRatio = 'ratio';
Prefs._SortByState = 'state';
diff --git a/web/javascript/torrent.js b/web/javascript/torrent.js
index 8da271e89..d64be234e 100644
--- a/web/javascript/torrent.js
+++ b/web/javascript/torrent.js
@@ -252,7 +252,8 @@ Torrent.prototype =
isSeeding: function() { return this.state() == Torrent._StatusSeed; },
name: function() { return this._name; },
queuePosition: function() { return this._queue_position; },
- isQueued: function() { return this.queuePosition() >= 0; },
+ isQueued: function() { return ( this.state() == Torrent._StatusSeedWait )
+ || ( this.state() == Torrent._StatusDownloadWait ); },
webseedsSendingToUs: function() { return this._webseeds_sending_to_us; },
peersSendingToUs: function() { return this._peers_sending_to_us; },
peersGettingFromUs: function() { return this._peers_getting_from_us; },
@@ -272,9 +273,9 @@ Torrent.prototype =
case Torrent._StatusStopped: return this.isFinished() ? 'Seeding complete' : 'Paused';
case Torrent._StatusCheckWait: return 'Waiting to verify local data';
case Torrent._StatusCheck: return 'Verifying local data';
- case Torrent._StatusDownloadWait: return 'Waiting to download #' + (this.queuePosition()+1);
+ case Torrent._StatusDownloadWait: return 'Waiting to download';
case Torrent._StatusDownload: return 'Downloading';
- case Torrent._StatusSeedWait: return 'Waiting to seed #' + (this.queuePosition()+1);
+ case Torrent._StatusSeedWait: return 'Waiting to seed';
case Torrent._StatusSeed: return 'Seeding';
default: return 'error';
}
@@ -770,17 +771,7 @@ Torrent.compareByName = function( a, b ) {
/** Helper function for sortTorrents(). */
Torrent.compareByQueue = function( a, b )
{
- var a_is_queued = a.isQueued( );
- var b_is_queued = b.isQueued( );
- if( a_is_queued != b_is_queued )
- return a_is_queued ? -1 : 1;
-
- var a_pos = a.queuePosition( );
- var b_pos = b.queuePosition( );
- if( a_pos != b_pos )
- return a_pos - b_pos;
-
- return Torrent.compareByName( a, b );
+ return a.queuePosition( ) - b.queuePosition();
};
/** Helper function for sortTorrents(). */
@@ -846,6 +837,9 @@ Torrent.sortTorrents = function( torrents, sortMethod, sortDirection )
case Prefs._SortByAge:
torrents.sort( this.compareByAge );
break;
+ case Prefs._SortByQueue:
+ torrents.sort( this.compareByQueue );
+ break;
case Prefs._SortByProgress:
torrents.sort( this.compareByProgress );
break;