1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-19 10:15:36 +00:00

(trunk web) Torrent class cleanup:

1. remove some of its unnecessary coupling to other classes
2. make more of its method names consistent with each other
3. make its field names consistent with the RPC spec
4. better grouping of methods by relevance
5. syntactical cleanup
This commit is contained in:
Jordan Lee 2011-08-20 21:17:12 +00:00
parent 56e47e96d0
commit b36c648b31
5 changed files with 440 additions and 438 deletions

View file

@ -90,7 +90,7 @@ FileRow.prototype =
{
var i = this.getIndex( );
var t = this.getTorrent( );
this.readAttributes( t._file_model[i] );
this.readAttributes( t._files[i] );
this.refreshHTML();
},
@ -98,17 +98,17 @@ FileRow.prototype =
return this._done >= this._size;
},
isEditable: function () {
return (this.getTorrent()._file_model.length>1) && !this.isDone();
return (this.getTorrent()._files.length>1) && !this.isDone();
},
createRow: function( torrent, i )
{
var me = this;
var file = torrent._file_model[i];
var file = torrent._files[i];
var name = file.name.substring (file.name.lastIndexOf('/')+1);
var root = document.createElement('li');
root.id = 't' + this._torrent.id() + 'f' + this._index;
root.id = 't' + this._torrent.getId() + 'f' + this._index;
root.classNameConst = 'inspector_torrent_file_list_entry ' + ((i%2)?'odd':'even');
root.className = root.classNameConst;

View file

@ -19,11 +19,11 @@ TorrentRendererHelper.getProgressInfo = function( controller, t )
var pct = 0;
if( t.needsMetaData( ) )
pct = t._metadataPercentComplete * 100;
pct = t.getMetadataPercentComplete() * 100;
else if( !t.isDone( ) )
pct = Math.round( t.getPercentDone() * 100 );
else if( seed_ratio_limit > 0 )
pct = Math.round( t._upload_ratio * 100 / seed_ratio_limit );
pct = Math.round( t.getUploadRatio() * 100 / seed_ratio_limit );
else
pct = 100;
@ -72,12 +72,12 @@ TorrentRendererHelper.renderProgressbar = function( controller, t, progressbar )
TorrentRendererHelper.formatUL = function( t )
{
return 'UL: ' + Transmission.fmt.speedBps( t.uploadSpeed( ) );
return 'UL: ' + Transmission.fmt.speedBps( t.getUploadSpeed( ) );
}
TorrentRendererHelper.formatDL = function( t )
{
return 'DL: ' + Transmission.fmt.speedBps( t.downloadSpeed( ) );
return 'DL: ' + Transmission.fmt.speedBps( t.getDownloadSpeed( ) );
}
/****
@ -134,9 +134,9 @@ TorrentRendererFull.prototype =
if( t.isDownloading( ) )
return [ 'Downloading from',
t.peersSendingToUs(),
t.getPeersSendingToUs(),
'of',
t._peers_connected,
t.getPeersConnected(),
'peers',
'-',
TorrentRendererHelper.formatDL(t),
@ -144,60 +144,63 @@ TorrentRendererFull.prototype =
if( t.isSeeding( ) )
return [ 'Seeding to',
t.peersGettingFromUs(),
t.getPeersGettingFromUs(),
'of',
t._peers_connected,
t.getPeersConnected(),
'peers',
'-',
TorrentRendererHelper.formatUL(t) ].join(' ');
if( t.state() === Torrent._StatusCheck )
if( t.isChecking( ) )
return [ 'Verifying local data (',
Transmission.fmt.percentString( 100.0 * t._recheckProgress ),
Transmission.fmt.percentString( 100.0 * t.getRecheckProgress() ),
'% tested)' ].join('');
return t.stateStr( );
return t.getStateString( );
},
getProgressDetails: function( controller, t )
{
if( t.needsMetaData() ) {
var percent = 100 * t._metadataPercentComplete;
var percent = 100 * t.getMetadataPercentComplete();
return [ "Magnetized transfer - retrieving metadata (",
Transmission.fmt.percentString( percent ),
"%)" ].join('');
}
var c;
var is_done = ( t.isDone( ) )
|| ( t.state() === Torrent._StatusSeeding );
var sizeWhenDone = t.getSizeWhenDone()
var totalSize = t.getTotalSize()
var is_done = ( t.isDone( ) ) || ( t.isSeeding() )
if( is_done ) {
if( t._size == t._sizeWhenDone ) // seed: '698.05 MiB'
c = [ Transmission.fmt.size( t._size ) ];
if( totalSize == sizeWhenDone ) // seed: '698.05 MiB'
c = [ Transmission.fmt.size( totalSize ) ];
else // partial seed: '127.21 MiB of 698.05 MiB (18.2%)'
c = [ Transmission.fmt.size( t._sizeWhenDone ),
c = [ Transmission.fmt.size( sizeWhenDone ),
' of ',
Transmission.fmt.size( t._size ),
Transmission.fmt.size( t.getTotalSize() ),
' (', t.getPercentDoneStr, '%)' ];
// append UL stats: ', uploaded 8.59 GiB (Ratio: 12.3)'
c.push( ', uploaded ',
Transmission.fmt.size( t._upload_total ),
Transmission.fmt.size( t.getUploadedEver() ),
' (Ratio ',
Transmission.fmt.ratioString( t._upload_ratio ),
Transmission.fmt.ratioString( t.getUploadRatio() ),
')' );
} else { // not done yet
c = [ Transmission.fmt.size( t._sizeWhenDone - t._leftUntilDone ),
' of ', Transmission.fmt.size( t._sizeWhenDone ),
c = [ Transmission.fmt.size( sizeWhenDone - t.getLeftUntilDone() ),
' of ', Transmission.fmt.size( sizeWhenDone ),
' (', t.getPercentDoneStr(), '%)' ];
}
// maybe append eta
if( t.isActive() && ( !is_done || t.seedRatioLimit(controller)>0 ) ) {
if( !t.isStopped() && ( !is_done || t.seedRatioLimit(controller)>0 ) ) {
c.push(' - ');
if (t._eta < 0 || this._eta >= Torrent._InfiniteTimeRemaining )
var eta = t.getETA()
if (eta < 0 || eta >= (999*60*60) /* arbitrary */ )
c.push( 'remaining time unknown' );
else
c.push( Transmission.fmt.timeInterval(t._eta),
c.push( Transmission.fmt.timeInterval(t.getETA()),
' remaining' );
}
@ -207,13 +210,13 @@ TorrentRendererFull.prototype =
render: function( controller, t, root )
{
// name
setInnerHTML( root._name_container, t.name() );
setInnerHTML( root._name_container, t.getName() );
// progressbar
TorrentRendererHelper.renderProgressbar( controller, t, root._progressbar );
// peer details
var has_error = t._error !== Torrent._ErrNone;
var has_error = t.getError() !== Torrent._ErrNone;
var e = root._peer_details_container;
$(e).toggleClass('error',has_error);
setInnerHTML( e, this.getPeerDetails( t ) );
@ -223,10 +226,10 @@ TorrentRendererFull.prototype =
setInnerHTML( e, this.getProgressDetails( controller, t ) );
// pause/resume button
var is_stopped = t.state() === Torrent._StatusStopped;
e = root._pause_resume_button_image;
e.alt = is_stopped ? 'Resume' : 'Pause';
e.className = is_stopped ? 'torrent_resume' : 'torrent_pause';
var is_stopped = t.isStopped()
e = root._pause_resume_button_image
e.alt = is_stopped ? 'Resume' : 'Pause'
e.className = is_stopped ? 'torrent_resume' : 'torrent_pause'
}
};
@ -271,19 +274,19 @@ TorrentRendererCompact.prototype =
TorrentRendererHelper.formatUL(t) ].join(' ');
if( t.isSeeding( ) )
return TorrentRendererHelper.formatUL(t);
return t.stateStr( );
return t.getStateString( );
},
render: function( controller, t, root )
{
// name
var is_stopped = t.state() === Torrent._StatusStopped;
var is_stopped = t.isStopped()
var e = root._name_container;
$(e).toggleClass( 'paused', is_stopped );
setInnerHTML( e, t.name() );
setInnerHTML( e, t.getName() );
// peer details
var has_error = t._error !== Torrent._ErrNone;
var has_error = t.getError() !== Torrent._ErrNone;
e = root._details_container;
$(e).toggleClass('error', has_error );
setInnerHTML( e, this.getPeerDetails( t ) );

View file

@ -1,411 +1,415 @@
/*
* Copyright © Dave Perrett and Malcolm Jarvis
* Copyright © Jordan Lee, Dave Perrett and Malcolm Jarvis
* This code is licensed under the GPL version 2.
* For details, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Class Torrent
*/
function Torrent( controller, data) {
this.initialize( controller, data);
function Torrent(controller, data)
{
this.initialize(controller, data)
}
// Constants
Torrent._StatusStopped = 0; /* torrent is stopped */
Torrent._StatusCheckWait = 1; /* waiting in queue to check files */
Torrent._StatusCheck = 2; /* checking files */
Torrent._StatusDownloadWait = 3; /* queued to download */
Torrent._StatusDownload = 4; /* downloading */
Torrent._StatusSeedWait = 5; /* queeud to seed */
Torrent._StatusSeed = 6; /* seeding */
/***
****
**** Constants
****
***/
Torrent._InfiniteTimeRemaining = 215784000; // 999 Hours - may as well be infinite
// Torrent.fields.status
Torrent._StatusStopped = 0
Torrent._StatusCheckWait = 1
Torrent._StatusCheck = 2
Torrent._StatusDownloadWait = 3
Torrent._StatusDownload = 4
Torrent._StatusSeedWait = 5
Torrent._StatusSeed = 6
Torrent._RatioUseGlobal = 0;
Torrent._RatioUseLocal = 1;
Torrent._RatioUnlimited = 2;
// Torrent.fields.seedRatioMode
Torrent._RatioUseGlobal = 0
Torrent._RatioUseLocal = 1
Torrent._RatioUnlimited = 2
Torrent._ErrNone = 0;
Torrent._ErrTrackerWarning = 1;
Torrent._ErrTrackerError = 2;
Torrent._ErrLocalError = 3;
// Torrent.fields.error
Torrent._ErrNone = 0
Torrent._ErrTrackerWarning = 1
Torrent._ErrTrackerError = 2
Torrent._ErrLocalError = 3
Torrent._TrackerInactive = 0;
Torrent._TrackerWaiting = 1;
Torrent._TrackerQueued = 2;
Torrent._TrackerActive = 3;
// TrackerStats' announceState
Torrent._TrackerInactive = 0
Torrent._TrackerWaiting = 1
Torrent._TrackerQueued = 2
Torrent._TrackerActive = 3
Torrent._StaticFields = [ 'hashString', 'id' ]
// fields whose values never change and are always known
Torrent._StaticFields = [
'hashString', 'id' ]
Torrent._MetaDataFields = [ 'addedDate', 'comment', 'creator', 'dateCreated',
'isPrivate', 'name', 'totalSize', 'pieceCount', 'pieceSize' ]
// fields whose values never change and are known upon constructon OR
// when a magnet torrent finishes downloading its metadata
Torrent._MetaDataFields = [
'addedDate', 'comment', 'creator', 'dateCreated',
'isPrivate', 'name', 'totalSize', 'pieceCount', 'pieceSize' ]
Torrent._DynamicFields = [ 'downloadedEver', 'error', 'errorString', 'eta',
'haveUnchecked', 'haveValid', 'leftUntilDone', 'metadataPercentComplete',
'peers', 'peersConnected', 'peersGettingFromUs', 'peersSendingToUs',
'queuePosition', 'rateDownload', 'rateUpload', 'recheckProgress',
'sizeWhenDone', 'status', 'trackerStats', 'desiredAvailable',
'uploadedEver', 'uploadRatio', 'seedRatioLimit', 'seedRatioMode',
'downloadDir', 'isFinished' ]
// torrent fields whose values change all the time
Torrent._DynamicFields = [
'desiredAvailable', 'downloadDir', 'downloadedEver', 'error',
'errorString', 'eta', 'haveUnchecked', 'haveValid', 'isFinished',
'leftUntilDone', 'metadataPercentComplete', 'peers', 'peersConnected',
'peersGettingFromUs', 'peersSendingToUs', 'queuePosition',
'rateDownload', 'rateUpload', 'recheckProgress', 'seedRatioLimit',
'seedRatioMode', 'sizeWhenDone', 'status', 'trackerStats',
'uploadedEver', 'uploadRatio', 'webseedsSendingToUs' ]
// tracker stats fields whose values change all the time
Torrent._TrackerStatFields = [
'announce', 'announceState', 'downloadCount', 'hasAnnounced',
'hasScraped', 'host', 'isBackup', 'lastAnnouncePeerCount',
'lastAnnounceResult', 'lastAnnounceSucceeded', 'lastAnnounceTime',
'lastScrapeResult', 'lastScrapeSucceeded', 'lastScrapeTime',
'leecherCount', 'nextAnnounceTime', 'seederCount'
]
/***
****
**** Methods
****
***/
Torrent.prototype =
{
initMetaData: function( data ) {
this._date = data.addedDate;
this._comment = data.comment;
this._creator = data.creator;
this._creator_date = data.dateCreated;
this._is_private = data.isPrivate;
this._name = data.name;
this._name_lc = this._name.toLowerCase( );
this._size = data.totalSize;
this._pieceCount = data.pieceCount;
this._pieceSize = data.pieceSize;
initialize: function(controller, data)
{
this.fields = { }
this._files = [ ]
if( data.files ) {
for( var i=0, row; row=data.files[i]; ++i ) {
this._file_model[i] = {
// these fields are set in the ctor and never change
for(var i=0, key; key=Torrent._StaticFields[i]; ++i)
if(key in data)
this.fields[key] = data[key]
this.initMetaData(data)
this._trackerStats = this.buildTrackerStats(data.trackerStats)
this.refresh(data)
},
buildTrackerStats: function(trackerStats) {
result = []
for(var i=0, tracker; tracker=trackerStats[i]; ++i) {
tier = result[tracker.tier] || []
tier[tier.length] = tracker
result[tracker.tier] = tier
}
return result
},
initMetaData: function(data) {
var f = this.fields
// populate the metadata fields
for(var i=0, key; key=Torrent._MetaDataFields[i]; ++i) {
if(key in data) {
f[key] = data[key]
if(key == 'name')
f.collatedName = data.name.toLowerCase()
}
}
// populate the files array
if(data.files) {
for(var i=0, row; row=data.files[i]; ++i) {
this._files[i] = {
'index': i,
'torrent': this,
'length': row.length,
'name': row.name
};
}
}
}
},
/*
* Constructor
*/
initialize: function( controller, data) {
this._id = data.id;
this._hashString = data.hashString;
this._sizeWhenDone = data.sizeWhenDone;
this._trackerStats = this.buildTrackerStats(data.trackerStats);
this._file_model = [ ];
this.initMetaData( data );
// Update all the labels etc
this.refresh(data);
},
buildTrackerStats: function(trackerStats) {
result = [];
for( var i=0, tracker; tracker=trackerStats[i]; ++i ) {
tier = result[tracker.tier] || [];
tier[tier.length] = {
'host': tracker.host,
'announce': tracker.announce,
'hasAnnounced': tracker.hasAnnounced,
'lastAnnounceTime': tracker.lastAnnounceTime,
'lastAnnounceSucceeded': tracker.lastAnnounceSucceeded,
'lastAnnounceResult': tracker.lastAnnounceResult,
'lastAnnouncePeerCount': tracker.lastAnnouncePeerCount,
'announceState': tracker.announceState,
'nextAnnounceTime': tracker.nextAnnounceTime,
'isBackup': tracker.isBackup,
'hasScraped': tracker.hasScraped,
'lastScrapeTime': tracker.lastScrapeTime,
'lastScrapeSucceeded': tracker.lastScrapeSucceeded,
'lastScrapeResult': tracker.lastScrapeResult,
'seederCount': tracker.seederCount,
'leecherCount': tracker.leecherCount,
'downloadCount': tracker.downloadCount
};
result[tracker.tier] = tier;
}
return result;
},
/*--------------------------------------------
*
* S E T T E R S / G E T T E R S
*
*--------------------------------------------*/
activity: function() { return this.downloadSpeed() + this.uploadSpeed(); },
comment: function() { return this._comment; },
completed: function() { return this._completed; },
creator: function() { return this._creator; },
dateAdded: function() { return this._date; },
downloadSpeed: function() { return this._download_speed; },
downloadTotal: function() { return this._download_total; },
hash: function() { return this._hashString; },
id: function() { return this._id; },
isActiveFilter: function() { return this.peersGettingFromUs() > 0
|| this.peersSendingToUs() > 0
|| this.webseedsSendingToUs() > 0
|| this.state() == Torrent._StatusCheck; },
isStopped: function() { return this.state() === Torrent._StatusStopped; },
isActive: function() { return this.state() != Torrent._StatusStopped; },
isDownloading: function() { return this.state() == Torrent._StatusDownload; },
isFinished: function() { return this._isFinishedSeeding; },
isDone: function() { return this._leftUntilDone < 1; },
isSeeding: function() { return this.state() == Torrent._StatusSeed; },
name: function() { return this._name; },
queuePosition: function() { return this._queue_position; },
webseedsSendingToUs: function() { return this._webseeds_sending_to_us; },
peersSendingToUs: function() { return this._peers_sending_to_us; },
peersGettingFromUs: function() { return this._peers_getting_from_us; },
needsMetaData: function(){ return this._metadataPercentComplete < 1 },
getPercentDone: function() {
if( !this._sizeWhenDone ) return 1.0;
if( !this._leftUntilDone ) return 1.0;
return ( this._sizeWhenDone - this._leftUntilDone ) / this._sizeWhenDone;
},
getPercentDoneStr: function() {
return Transmission.fmt.percentString( 100 * this.getPercentDone() );
},
size: function() { return this._size; },
state: function() { return this._state; },
stateStr: function() {
switch( this.state() ) {
case Torrent._StatusStopped: return this.isFinished() ? 'Seeding complete' : 'Paused';
case Torrent._StatusCheckWait: return 'Queued for verification';
case Torrent._StatusCheck: return 'Verifying local data';
case Torrent._StatusDownloadWait: return 'Queued for download';
case Torrent._StatusDownload: return 'Downloading';
case Torrent._StatusSeedWait: return 'Queued for seeding';
case Torrent._StatusSeed: return 'Seeding';
default: return 'error';
}
},
trackerStats: function() { return this._trackerStats; },
uploadSpeed: function() { return this._upload_speed; },
uploadTotal: function() { return this._upload_total; },
seedRatioLimit: function(controller){
switch( this._seed_ratio_mode ) {
case Torrent._RatioUseGlobal: return controller.seedRatioLimit();
case Torrent._RatioUseLocal: return this._seed_ratio_limit;
default: return -1;
}
},
getErrorMessage: function() {
if( this._error == Torrent._ErrTrackerWarning )
return 'Tracker returned a warning: ' + this._error_string;
if( this._error == Torrent._ErrTrackerError )
return 'Tracker returned an error: ' + this._error_string;
if( this._error == Torrent._ErrLocalError )
return 'Error: ' + this._error_string;
return null;
},
/*--------------------------------------------
*
* I N T E R F A C E F U N C T I O N S
*
*--------------------------------------------*/
fireDataChanged: function()
{
$(this).trigger('dataChanged',[]);
$(this).trigger('dataChanged',[])
},
refreshMetaData: function(data)
{
this.initMetaData( data );
this.fireDataChanged();
this.initMetaData(data)
this.fireDataChanged()
},
refresh: function(data)
{
if( this.needsMetaData() && ( data.metadataPercentComplete >= 1 ) )
transmission.refreshMetaData( [ this._id ] );
// FIXME: unnecessary coupling... this should be handled by transmission.js
if(this.needsMetaData() && (data.metadataPercentComplete >= 1))
transmission.refreshMetaData([ this.getId() ])
this._completed = data.haveUnchecked + data.haveValid;
this._verified = data.haveValid;
this._leftUntilDone = data.leftUntilDone;
this._download_total = data.downloadedEver;
this._upload_total = data.uploadedEver;
this._upload_ratio = data.uploadRatio;
this._seed_ratio_limit = data.seedRatioLimit;
this._seed_ratio_mode = data.seedRatioMode;
this._download_speed = data.rateDownload;
this._upload_speed = data.rateUpload;
this._peers = data.peers;
this._peers_connected = data.peersConnected;
this._peers_getting_from_us = data.peersGettingFromUs;
this._peers_sending_to_us = data.peersSendingToUs;
this._queue_position = data.queuePosition;
this._webseeds_sending_to_us = data.webseedsSendingToUs;
this._sizeWhenDone = data.sizeWhenDone;
this._recheckProgress = data.recheckProgress;
this._error = data.error;
this._error_string = data.errorString;
this._eta = data.eta;
this._trackerStats = this.buildTrackerStats(data.trackerStats);
this._state = data.status;
this._download_dir = data.downloadDir;
this._metadataPercentComplete = data.metadataPercentComplete;
this._isFinishedSeeding = data.isFinished;
this._desiredAvailable = data.desiredAvailable;
var f = this.fields
// refresh the dynamic fields
for(var i=0, key; key=Torrent._DynamicFields[i]; ++i)
if(key in data)
f[key] = data[key]
this._trackerStats = this.buildTrackerStats(data.trackerStats)
if (data.fileStats)
this.refreshFileModel( data );
this.refreshFiles(data)
this.fireDataChanged();
this.fireDataChanged()
},
refreshFileModel: function(data) {
for( var i=0; i<data.fileStats.length; ++i ) {
var src = data.fileStats[i];
var tgt = this._file_model[i];
if( !tgt )
tgt = this._file_model[i] = { };
tgt.wanted = src.wanted;
tgt.priority = src.priority;
tgt.bytesCompleted = src.bytesCompleted;
refreshFiles: function(data) {
for(var i=0; i<data.fileStats.length; ++i) {
var src = data.fileStats[i]
var tgt = this._files[i]
if(!tgt)
tgt = this._files[i] = { }
tgt.wanted = src.wanted
tgt.priority = src.priority
tgt.bytesCompleted = src.bytesCompleted
}
},
/****
*****
****/
// simple accessors
getCollatedName: function() { return this.fields.collatedName },
getComment: function() { return this.fields.comment },
getCreator: function() { return this.fields.creator },
getDateAdded: function() { return this.fields.addedDate },
getDateCreated: function() { return this.fields.dateCreated },
getDesiredAvailable: function() { return this.fields.desiredAvailable },
getDownloadDir: function() { return this.fields.downloadDir },
getDownloadSpeed: function() { return this.fields.rateDownload },
getDownloadedEver: function() { return this.fields.downloadedEver },
getError: function() { return this.fields.error },
getErrorString: function() { return this.fields.errorString },
getETA: function() { return this.fields.eta },
getHashString: function() { return this.fields.hashString },
getHaveValid: function() { return this.fields.haveValid },
getHave: function() { return this.getHaveValid() + this.fields.haveUnchecked },
getId: function() { return this.fields.id },
getLeftUntilDone: function() { return this.fields.leftUntilDone },
getMetadataPercentComplete: function() { return this.fields.metadataPercentComplete },
getName: function() { return this.fields.name },
getPeers: function() { return this.fields.peers },
getPeersConnected: function() { return this.fields.peersConnected },
getPeersGettingFromUs: function() { return this.fields.peersGettingFromUs },
getPeersSendingToUs: function() { return this.fields.peersSendingToUs },
getPieceCount: function() { return this.fields.pieceCount },
getPieceCount: function() { return this.fields.pieceCount },
getPieceSize: function() { return this.fields.pieceSize },
getPrivateFlag: function() { return this.fields.isPrivate },
getQueuePosition: function() { return this.fields.queuePosition },
getRecheckProgress: function() { return this.fields.recheckProgress },
getSeedRatioLimit: function() { return this.fields.seedRatioLimit },
getSeedRatioMode: function() { return this.fields.seedRatioMode },
getSizeWhenDone: function() { return this.fields.sizeWhenDone },
getStatus: function() { return this.fields.status },
getTotalSize: function() { return this.fields.totalSize },
getUploadSpeed: function() { return this.fields.rateUpload },
getUploadRatio: function() { return this.fields.uploadRatio },
getUploadedEver: function() { return this.fields.uploadedEver },
getWebseedsSendingToUs: function() { return this.fields.webseedsSendingToUs },
isFinished: function() { return this.fields.isFinished },
// derived accessors
isSeeding: function() { return this.getStatus() === Torrent._StatusSeed },
isStopped: function() { return this.getStatus() === Torrent._StatusStopped },
isChecking: function() { return this.getStatus() === Torrent._StatusCheck },
isDownloading: function() { return this.getStatus() === Torrent._StatusDownload },
isDone: function() { return this.getLeftUntilDone() < 1 },
needsMetaData: function(){ return this.getMetadataPercentComplete() < 1 },
getActivity: function() { return this.getDownloadSpeed() + this.getUploadSpeed() },
getPercentDoneStr: function() { return Transmission.fmt.percentString(100*this.getPercentDone()) },
getPercentDone: function() {
var finalSize = this.getSizeWhenDone()
if(!finalSize) return 1.0
var left = this.getLeftUntilDone()
if(!left) return 1.0
return (finalSize - left) / finalSize
},
getStateString: function() {
switch(this.getStatus()) {
case Torrent._StatusStopped: return this.isFinished() ? 'Seeding complete' : 'Paused'
case Torrent._StatusCheckWait: return 'Queued for verification'
case Torrent._StatusCheck: return 'Verifying local data'
case Torrent._StatusDownloadWait: return 'Queued for download'
case Torrent._StatusDownload: return 'Downloading'
case Torrent._StatusSeedWait: return 'Queued for seeding'
case Torrent._StatusSeed: return 'Seeding'
default: return 'error'
}
},
trackerStats: function() { return this._trackerStats },
seedRatioLimit: function(controller){
switch(this.getSeedRatioMode()) {
case Torrent._RatioUseGlobal: return controller.seedRatioLimit()
case Torrent._RatioUseLocal: return this.getSeedRatioLimit()
default: return -1
}
},
getErrorMessage: function() {
var str = this.getErrorString()
switch(this.getError()) {
case Torrent._ErrTrackerWarning:
return 'Tracker returned a warning: ' + str
case Torrent._ErrTrackerError:
return 'Tracker returned an error: ' + str
case Torrent._ErrLocalError:
return 'Error: ' + str
default:
return null
}
},
/****
*****
****/
/**
* @param filter one of Prefs._Filter*
* @param search substring to look for, or null
* @return true if it passes the test, false if it fails
*/
test: function( filter, search )
test: function(filter, search)
{
var pass = false;
var s = this.state( );
var pass = false
var s = this.getStatus()
switch( filter )
switch(filter)
{
case Prefs._FilterActive:
pass = this.isActiveFilter();
break;
pass = this.getPeersGettingFromUs() > 0
|| this.getPeersSendingToUs() > 0
|| this.getWebseedsSendingToUs() > 0
|| this.isChecking()
break
case Prefs._FilterSeeding:
pass = ( s == Torrent._StatusSeed ) || ( s == Torrent._StatusSeedWait );
break;
pass = (s == Torrent._StatusSeed) || (s == Torrent._StatusSeedWait)
break
case Prefs._FilterDownloading:
pass = ( s == Torrent._StatusDownload ) || ( s == Torrent._StatusDownloadWait );
break;
pass = (s == Torrent._StatusDownload) || (s == Torrent._StatusDownloadWait)
break
case Prefs._FilterPaused:
pass = !this.isActive();
break;
pass = this.isStopped()
break
case Prefs._FilterFinished:
pass = this.isFinished();
break;
pass = this.isFinished()
break
default:
pass = true;
break;
pass = true
break
}
if( !pass )
return false;
if(!pass)
return false
if( !search || !search.length )
return pass;
if(!search || !search.length)
return pass
return this._name_lc.indexOf( search.toLowerCase() ) !== -1;
return this.getCollatedName().indexOf(search.toLowerCase()) !== -1
}
};
}
/** Helper function for Torrent.sortTorrents(). */
Torrent.compareById = function( a, b ) {
return a.id() - b.id();
};
/** Helper function for sortTorrents(). */
Torrent.compareByName = function( a, b ) {
var i = a._name_lc.compareTo( b._name_lc );
if( i )
return i;
return Torrent.compareById( a, b );
};
/***
****
**** SORTING
****
***/
/** Helper function for sortTorrents(). */
Torrent.compareByQueue = function( a, b )
Torrent.compareById = function(ta, tb)
{
return a.queuePosition( ) - b.queuePosition();
};
/** Helper function for sortTorrents(). */
Torrent.compareByAge = function( a, b )
return ta.getId() - tb.getId()
}
Torrent.compareByName = function(ta, tb)
{
var a_age = a.dateAdded();
var b_age = b.dateAdded();
if( a_age != b_age )
return a_age - b_age;
return Torrent.compareByQueue( a, b );
};
/** Helper function for sortTorrents(). */
Torrent.compareByState = function( a, b )
var i = ta.getCollatedName().compareTo(tb.getCollatedName())
return i || Torrent.compareById(ta, tb)
}
Torrent.compareByQueue = function(ta, tb)
{
var a_state = a.state( );
var b_state = b.state( );
if( a_state != b_state )
return b_state - a_state;
return Torrent.compareByQueue( a, b );
};
/** Helper function for sortTorrents(). */
Torrent.compareByActivity = function( a, b )
return ta.getQueuePosition() - tb.getQueuePosition()
}
Torrent.compareByAge = function(ta, tb)
{
var a_activity = a.activity( );
var b_activity = b.activity( );
if( a_activity != b_activity )
return a_activity - b_activity;
return Torrent.compareByState( a, b );
};
/** Helper function for sortTorrents(). */
Torrent.compareByRatio = function( a, b ) {
var a_ratio = Math.ratio( a._upload_total, a._download_total );
var b_ratio = Math.ratio( b._upload_total, b._download_total );
if( a_ratio != b_ratio )
return a_ratio - b_ratio;
return Torrent.compareByState( a, b );
};
Torrent.compareByProgress = function( a, b ) {
if( a.getPercentDone() !== b.getPercentDone() )
return a.getPercentDone() - b.getPercentDone();
return Torrent.compareByRatio( a, b );
};
var a = ta.getDateAdded()
var b = tb.getDateAdded()
return (b - a) || Torrent.compareByQueue(ta, tb)
}
Torrent.compareByState = function(ta, tb)
{
var a = ta.getStatus()
var b = tb.getStatus()
return (b - a) || Torrent.compareByQueue(ta, tb)
}
Torrent.compareByActivity = function(ta, tb)
{
var a = ta.getActivity()
var b = tb.getActivity()
return (a - b) || Torrent.compareByState(ta, tb)
}
Torrent.compareByRatio = function(a, b)
{
var a = Math.ratio(ta.getUploadedEver(), ta.getDownloadedEver())
var b = Math.ratio(tb.getUploadedEver(), tb.getDownloadedEver())
return (a - b) || Torrent.compareByState(ta, tb)
}
Torrent.compareByProgress = function(ta, tb)
{
var a = ta.getPercentDone()
var b = tb.getPercentDone()
return (a - b) || Torrent.compareByRatio(ta, tb)
}
/**
* @param torrents an array of Torrent objects
* @param sortMethod one of Prefs._SortBy*
* @param sortDirection Prefs._SortAscending or Prefs._SortDescending
*/
Torrent.sortTorrents = function( torrents, sortMethod, sortDirection )
Torrent.sortTorrents = function(torrents, sortMethod, sortDirection)
{
switch( sortMethod )
switch(sortMethod)
{
case Prefs._SortByActivity:
torrents.sort( this.compareByActivity );
break;
torrents.sort(this.compareByActivity)
break
case Prefs._SortByAge:
torrents.sort( this.compareByAge );
break;
torrents.sort(this.compareByAge)
break
case Prefs._SortByQueue:
torrents.sort( this.compareByQueue );
break;
torrents.sort(this.compareByQueue)
break
case Prefs._SortByProgress:
torrents.sort( this.compareByProgress );
break;
torrents.sort(this.compareByProgress)
break
case Prefs._SortByState:
torrents.sort( this.compareByState );
break;
torrents.sort(this.compareByState)
break
case Prefs._SortByName:
torrents.sort( this.compareByName );
break;
torrents.sort(this.compareByName)
break
case Prefs._SortByRatio:
torrents.sort( this.compareByRatio );
break;
torrents.sort(this.compareByRatio)
break
default:
console.warn( "unknown sort method: " + sortMethod );
break;
console.warn("unknown sort method: " + sortMethod)
break
}
if( sortDirection === Prefs._SortDescending )
torrents.reverse( );
if(sortDirection === Prefs._SortDescending)
torrents.reverse()
return torrents;
};
return torrents
}

View file

@ -467,7 +467,7 @@ Transmission.prototype =
ret[ key ] = this._torrents[key];
var sel = this.getSelectedTorrents( );
for( var i=0, tor; tor=sel[i]; ++i )
delete ret[ tor.id() ];
delete ret[ tor.getId() ];
return ret;
},
@ -862,7 +862,7 @@ Transmission.prototype =
toggleFilesWantedDisplay: function(torrent, wanted) {
var rows = [ ];
for( var i=0, row; row=this._files[i]; ++i )
if( row.isEditable() && (torrent._file_model[i].wanted !== wanted) )
if( row.isEditable() && (torrent._files[i].wanted !== wanted) )
rows.push( row );
if( rows.length > 1 ) {
var command = wanted ? 'files-wanted' : 'files-unwanted';
@ -1019,7 +1019,7 @@ Transmission.prototype =
updateSelectedData: function()
{
var ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.id(); } );
var ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.getId(); } );
if( ids.length > 0 )
this.periodicTorrentUpdate( ids );
else
@ -1395,46 +1395,49 @@ Transmission.prototype =
}
name = torrents.length == 1
? torrents[0].name()
? torrents[0].getName()
: torrents.length+' Transfers Selected';
if( torrents.length == 1 )
{
var text
var t = torrents[0];
var err = t.getErrorMessage( );
if( err )
error = err;
if( t._comment)
comment = t._comment ;
if( t._creator )
creator = t._creator ;
if( t._download_dir)
download_dir = t._download_dir;
if(( text = t.getComment()))
comment = text
if(( text = t.getCreator()))
creator = text
if(( text = t.getDownloadDir()))
download_dir = text
hash = t.hash();
pieces = [ t._pieceCount, 'pieces @', Transmission.fmt.mem(t._pieceSize) ].join(' ');
date_created = Transmission.fmt.timestamp( t._creator_date );
hash = t.getHashString();
pieces = [ t.getPieceCount(), 'pieces @', Transmission.fmt.mem(t.getPieceSize()) ].join(' ');
date_created = Transmission.fmt.timestamp( t.getDateCreated() );
}
for( var i=0, t; t=torrents[i]; ++i ) {
sizeWhenDone += t._sizeWhenDone;
sizeDone += t._sizeWhenDone - t._leftUntilDone;
total_completed += t.completed();
total_verified += t._verified;
total_size += t.size();
total_upload += t.uploadTotal();
total_download += t.downloadTotal();
total_upload_speed += t.uploadSpeed();
total_download_speed += t.downloadSpeed();
total_upload_peers += t.peersGettingFromUs();
total_download_peers += t.peersSendingToUs();
total_availability += t._sizeWhenDone - t._leftUntilDone + t._desiredAvailable;
var sizeWhenDone = t.getSizeWhenDone()
var left = t.getLeftUntilDone()
sizeWhenDone += sizeWhenDone
sizeDone += sizeWhenDone - left;
total_completed += t.getHave();
total_verified += t.getHaveValid();
total_size += t.getTotalSize();
total_upload += t.getUploadedEver();
total_download += t.getDownloadedEver();
total_upload_speed += t.getUploadSpeed();
total_download_speed += t.getDownloadSpeed();
total_upload_peers += t.getPeersGettingFromUs();
total_download_peers += t.getPeersSendingToUs();
total_availability += sizeWhenDone - left + t.getDesiredAvailable();
var s = t.stateStr();
var s = t.getStateString();
if( total_state.indexOf( s ) == -1 )
total_state.push( s );
if( t._is_private )
if( t.getPrivateFlag( ) )
have_private = true;
else
have_public = true;
@ -1515,7 +1518,7 @@ Transmission.prototype =
// build the file list
this.clearFileList( );
this._files_torrent = torrent;
var n = torrent._file_model.length;
var n = torrent._files.length;
this._files = new Array( n );
var fragment = document.createDocumentFragment( );
var tr = this;
@ -1541,11 +1544,12 @@ Transmission.prototype =
var torrents = this.getSelectedTorrents( );
if( $(this._inspector_peers_list).is(':visible') ) {
for( var k=0, torrent; torrent=torrents[k]; ++k ) {
var peers = torrent.getPeers()
html.push( '<div class="inspector_group">' );
if( torrents.length > 1 ) {
html.push( '<div class="inspector_torrent_label">', torrent._name, '</div>' );
html.push( '<div class="inspector_torrent_label">', torrent.getName(), '</div>' );
}
if( torrent._peers.length == 0 ) {
if( peers.length == 0 ) {
html.push( '<br></div>' ); // firefox won't paint the top border if the div is empty
continue;
}
@ -1559,7 +1563,7 @@ Transmission.prototype =
'<th class="addressCol">Address</th>',
'<th class="clientCol">Client</th>',
'</tr>' );
for( var i=0, peer; peer=torrent._peers[i]; ++i ) {
for( var i=0, peer; peer=peers[i]; ++i ) {
var parity = ((i+1) % 2 == 0 ? 'even' : 'odd');
html.push( '<tr class="inspector_peer_entry ', parity, '">',
'<td>', (peer.isEncrypted ? '<img src="images/graphics/lock_icon.png" alt="Encrypted"/>' : ''), '</td>',
@ -1588,7 +1592,7 @@ Transmission.prototype =
for( var k=0, torrent; torrent = torrents[k]; ++k ) {
html.push( '<div class="inspector_group">' );
if( torrents.length > 1 ) {
html.push( '<div class="inspector_torrent_label">', torrent._name, '</div>' );
html.push( '<div class="inspector_torrent_label">', torrent.getName(), '</div>' );
}
for( var i=0, tier; tier=torrent._trackerStats[i]; ++i ) {
html.push( '<div class="inspector_group_label">',
@ -1770,7 +1774,7 @@ Transmission.prototype =
if( t ) {
t.refreshMetaData( this );
if( selected_torrents.indexOf(t) != -1 )
refresh_files_for.push( t.id( ) );
refresh_files_for.push( t.getId( ) );
}
} );
if( refresh_files_for.length > 0 )
@ -1798,7 +1802,7 @@ Transmission.prototype =
else {
t.refresh(o);
if( selected_torrents.indexOf(t) != -1 )
refresh_files_for.push(t.id());
refresh_files_for.push(t.getId());
}
}
@ -1822,7 +1826,7 @@ Transmission.prototype =
for( var i=0, o; o=torrents[i]; ++i ) {
var t = this._torrents[o.id];
if( t !== null ) {
t.refreshFileModel( o );
t.refreshFiles( o );
if( t === this._files_torrent )
this.refreshFileView();
}
@ -1888,43 +1892,34 @@ Transmission.prototype =
for( var i=0, row; row=new_torrents[i]; ++i ) {
var t = new Torrent( this, row );
this._torrents[t.id()] = t;
this._torrents[t.getId()] = t;
}
this.refilter( );
},
deleteTorrents: function(torrent_ids){
if(typeof torrent_ids == 'undefined')
return false;
var tr = this;
var removedAny = false;
$.each( torrent_ids, function(index, id){
var torrent = tr._torrents[id];
return false
if(torrent) {
removedAny = true;
var e = torrent.view;
if( e ) {
var row_index;
for( var i=0, row; row = tr._rows[i]; ++i ) {
if( row._id == torrent._id )
{
row_index = i;
e = tr._rows[row_index];
break;
}
}
delete e._torrent; //remove circular refernce to help IE garbage collect
tr._rows.splice(row_index, 1)
e.remove();
}
var keep = [ ]
var elements = [ ]
delete tr._torrents[torrent.id()];
for(var i=0, row; row=this._rows[i]; ++i) {
var tor = row.getTorrent()
var tid = tor ? tor.getId() : -1
if( torrent_ids.indexOf( tid ) == -1 )
keep.push( row )
else {
delete this._torrents[ tid ]
$(row.getElement()).remove()
}
});
}
return removedAny;
this._rows = keep
return remove.length > 0
},
refreshDisplay: function( )
@ -1954,8 +1949,8 @@ Transmission.prototype =
var upSpeed = 0;
var downSpeed = 0;
for( var i=0, row; row=torrents[i]; ++i ) {
upSpeed += row.uploadSpeed( );
downSpeed += row.downloadSpeed( );
upSpeed += row.getUploadSpeed( );
downSpeed += row.getDownloadSpeed( );
}
// update torrent count label
@ -2034,7 +2029,7 @@ Transmission.prototype =
if( torrents.length == 1 )
{
var torrent = torrents[0];
var header = 'Remove ' + torrent.name() + '?';
var header = 'Remove ' + torrent.getName() + '?';
var message = 'Once removed, continuing the transfer will require the torrent file. Are you sure you want to remove it?';
dialog.confirm( header, message, 'Remove', 'transmission.removeTorrents', torrents );
}
@ -2051,7 +2046,7 @@ Transmission.prototype =
if( torrents.length == 1 )
{
var torrent = torrents[0],
header = 'Remove ' + torrent.name() + ' and delete data?',
header = 'Remove ' + torrent.getName() + ' and delete data?',
message = 'All data downloaded for this torrent will be deleted. Are you sure you want to remove it?';
dialog.confirm( header, message, 'Remove', 'transmission.removeTorrentsAndData', torrents );
}
@ -2064,7 +2059,7 @@ Transmission.prototype =
},
removeTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var torrent_ids = jQuery.map(torrents, function(t) { return t.getId(); } );
var tr = this;
this.remote.removeTorrents( torrent_ids, function(){ tr.refreshTorrents() } );
},
@ -2091,7 +2086,7 @@ Transmission.prototype =
this.startTorrents( [ torrent ], false );
},
startTorrents: function( torrents, force ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var torrent_ids = jQuery.map(torrents, function(t) { return t.getId(); } );
var tr = this;
this.remote.startTorrents( torrent_ids, force, function(){ tr.refreshTorrents(torrent_ids) } );
},
@ -2099,7 +2094,7 @@ Transmission.prototype =
this.verifyTorrents( [ torrent ] );
},
verifyTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var torrent_ids = jQuery.map(torrents, function(t) { return t.getId(); } );
var tr = this;
this.remote.verifyTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids) } );
},
@ -2108,7 +2103,7 @@ Transmission.prototype =
this.reannounceTorrents( [ torrent ] );
},
reannounceTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var torrent_ids = jQuery.map(torrents, function(t) { return t.getId(); } );
var tr = this;
this.remote.reannounceTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids) } );
},
@ -2123,7 +2118,7 @@ Transmission.prototype =
this.stopTorrents( [ torrent ] );
},
stopTorrents: function( torrents ) {
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
var torrent_ids = jQuery.map(torrents, function(t) { return t.getId(); } );
var tr = this;
this.remote.stopTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids )} );
},
@ -2148,22 +2143,22 @@ Transmission.prototype =
// Queue
moveTop: function( ) {
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.id(); } );
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.getId(); } );
var tr = this;
this.remote.moveTorrentsToTop( torrent_ids, function(){ tr.refreshTorrents(torrent_ids )} );
},
moveUp: function( ) {
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.id(); } );
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.getId(); } );
var tr = this;
this.remote.moveTorrentsUp( torrent_ids, function(){ tr.refreshTorrents(torrent_ids )} );
},
moveDown: function( ) {
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.id(); } );
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.getId(); } );
var tr = this;
this.remote.moveTorrentsDown( torrent_ids, function(){ tr.refreshTorrents(torrent_ids )} );
},
moveBottom: function( ) {
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.id(); } );
var torrent_ids = jQuery.map(this.getSelectedTorrents( ), function(t) { return t.getId(); } );
var tr = this;
this.remote.moveTorrentsToBottom( torrent_ids, function(){ tr.refreshTorrents(torrent_ids )} );
},
@ -2262,13 +2257,13 @@ Transmission.prototype =
for( var i=0, row; row=this._rows[i]; ++i ) {
if( row.isVisible( ) ) {
var isActive = row.getTorrent().isActive( );
var isStopped = row.getTorrent().isStopped( );
var isSelected = row.isSelected();
if( isActive ) haveActive = true;
if( !isActive ) havePaused = true;
if( !isStopped ) haveActive = true;
if( isStopped ) havePaused = true;
if( isSelected ) haveSelection = true;
if( isSelected && isActive ) haveActiveSelection = true;
if( isSelected && !isActive ) havePausedSelection = true;
if( isSelected && !isStopped ) haveActiveSelection = true;
if( isSelected && isStopped ) havePausedSelection = true;
}
}

View file

@ -191,7 +191,7 @@ TransmissionRemote.prototype =
changeFileCommand: function( command, rows ) {
var remote = this;
var torrent_ids = [ rows[0].getTorrent().id() ];
var torrent_ids = [ rows[0].getTorrent().getId() ];
var files = [ ];
for( var i=0, row; row=rows[i]; ++i )
files.push( row.getIndex( ) );
@ -244,7 +244,7 @@ TransmissionRemote.prototype =
if( torrents != null )
for( var i=0, len=torrents.length; i<len; ++i )
o.arguments.ids.push( torrents[i].id() );
o.arguments.ids.push( torrents[i].getId() );
this.sendRequest( o, function( ) {
remote._controller.refreshTorrents();
} );