/* * Copyright © Jordan Lee * This code is licensed under the GPL version 2. * */ /**** ***** ***** ****/ function TorrentRendererHelper() { } TorrentRendererHelper.getProgressInfo = function( controller, t ) { var seed_ratio_limit = t.seedRatioLimit( controller ); var pct = 0; if( t.needsMetaData( ) ) pct = t._metadataPercentComplete * 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 ); else pct = 100; var extra; if( t.isStopped( ) ) extra = 'paused'; else if( t.isSeeding( ) ) extra = 'seeding'; else if( t.needsMetaData( ) ) extra = 'magnet'; else extra = 'leeching'; return { percent: pct, complete: [ 'torrent_progress_bar', 'complete', extra ].join(' '), incomplete: [ 'torrent_progress_bar', 'incomplete', extra ].join(' ') }; } TorrentRendererHelper.renderProgressbar = function( controller, t, complete, incomplete ) { var info = TorrentRendererHelper.getProgressInfo( controller, t ); var e; e = complete; e.style.width = '' + info.percent + "%"; e.className = info.complete; e.style.display = info.percent<=0 ? 'none' : 'block'; e = incomplete; e.className = info.incomplete; e.style.display = info.percent>=100 ? 'none' : 'block'; } TorrentRendererHelper.formatUL = function( t ) { return 'UL: ' + Transmission.fmt.speedBps( t.uploadSpeed( ) ); } TorrentRendererHelper.formatDL = function( t ) { return 'DL: ' + Transmission.fmt.speedBps( t.downloadSpeed( ) ); } /**** ***** ***** ****/ function TorrentRendererFull() { } TorrentRendererFull.prototype = { createRow: function( ) { var root = document.createElement( 'li' ); root.className = 'torrent'; var name = document.createElement( 'div' ); name.className = 'torrent_name'; var peers = document.createElement( 'div' ); peers.className = 'torrent_peer_details'; var complete = document.createElement( 'div' ); complete.className = 'torrent_progress_bar complete'; var incomplete = document.createElement( 'div' ); incomplete.className = 'torrent_progress_bar incomplete'; var progressbar = document.createElement( 'div' ); progressbar.className = 'torrent_progress_bar_container full'; progressbar.appendChild( complete ); progressbar.appendChild( incomplete ); var details = document.createElement( 'div' ); details.className = 'torrent_progress_details'; var image = document.createElement( 'div' ); var button = document.createElement( 'a' ); button.appendChild( image ); root.appendChild( name ); root.appendChild( peers ); root.appendChild( button ); root.appendChild( progressbar ); root.appendChild( details ); root._name_container = name; root._peer_details_container = peers; root._progress_details_container = details; root._progress_complete_container = complete; root._progress_incomplete_container = incomplete; root._pause_resume_button_image = image; root._toggle_running_button = button; return root; }, getPeerDetails: function( t ) { var err; if(( err = t.getErrorMessage())) return err; if( t.isDownloading( ) ) return [ 'Downloading from', t.peersSendingToUs(), 'of', t._peers_connected, 'peers', '-', TorrentRendererHelper.formatDL(t), TorrentRendererHelper.formatUL(t) ].join(' '); if( t.isSeeding( ) ) return [ 'Seeding to', t.peersGettingFromUs(), 'of', t._peers_connected, 'peers', '-', TorrentRendererHelper.formatUL(t) ].join(' '); if( t.state() === Torrent._StatusCheck ) return [ 'Verifying local data (', Transmission.fmt.percentString( 100.0 * t._recheckProgress ), '% tested)' ].join(''); return t.stateStr( ); }, getProgressDetails: function( controller, t ) { if( t.needsMetaData() ) { var percent = 100 * t._metadataPercentComplete; return [ "Magnetized transfer - retrieving metadata (", Transmission.fmt.percentString( percent ), "%)" ].join(''); } var c; var is_done = ( t.isDone( ) ) || ( t.state() === Torrent._StatusSeeding ); if( is_done ) { if( t._size == t._sizeWhenDone ) // seed: '698.05 MiB' c = [ Transmission.fmt.size( t._size ) ]; else // partial seed: '127.21 MiB of 698.05 MiB (18.2%)' c = [ Transmission.fmt.size( t._sizeWhenDone ), ' of ', Transmission.fmt.size( t._size ), ' (', t.getPercentDoneStr, '%)' ]; // append UL stats: ', uploaded 8.59 GiB (Ratio: 12.3)' c.push( ', uploaded ', Transmission.fmt.size( t._upload_total ), ' (Ratio ', Transmission.fmt.ratioString( t._upload_ratio ), ')' ); } else { // not done yet c = [ Transmission.fmt.size( t._sizeWhenDone - t._leftUntilDone ), ' of ', Transmission.fmt.size( t._sizeWhenDone ), ' (', t.getPercentDoneStr(), '%)' ]; } // maybe append eta if( t.isActive() && ( !is_done || t.seedRatioLimit(controller)>0 ) ) { c.push(' - '); if (t._eta < 0 || this._eta >= Torrent._InfiniteTimeRemaining ) c.push( 'remaining time unknown' ); else c.push( Transmission.fmt.timeInterval(t._eta), ' remaining' ); } return c.join(''); }, render: function( controller, t, root ) { // name setInnerHTML( root._name_container, t.name() ); // progressbar TorrentRendererHelper.renderProgressbar( controller, t, root._progress_complete_container, root._progress_incomplete_container ); // peer details var has_error = t._error !== Torrent._ErrNone; var e = root._peer_details_container; $(e).toggleClass('error',has_error); setInnerHTML( e, this.getPeerDetails( t ) ); // progress details e = root._progress_details_container; 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'; } }; /**** ***** ***** ****/ function TorrentRendererCompact() { } TorrentRendererCompact.prototype = { createRow: function( ) { var complete = document.createElement( 'div' ); complete.className = 'torrent_progress_bar complete'; var incomplete = document.createElement( 'div' ); incomplete.className = 'torrent_progress_bar incomplete'; var progressbar = document.createElement( 'div' ); progressbar.className = 'torrent_progress_bar_container compact'; progressbar.appendChild( complete ); progressbar.appendChild( incomplete ); var details = document.createElement( 'div' ); details.className = 'torrent_peer_details compact'; var name = document.createElement( 'div' ); name.className = 'torrent_name'; var root = document.createElement( 'li' ); root.appendChild( progressbar ); root.appendChild( details ); root.appendChild( name ); root.className = 'torrent compact'; root._progress_complete_container = complete; root._progress_incomplete_container = incomplete; root._details_container = details; root._name_container = name; return root; }, getPeerDetails: function( t ) { var c; if(( c = t.getErrorMessage())) return c; if( t.isDownloading( ) ) return [ TorrentRendererHelper.formatDL(t), TorrentRendererHelper.formatUL(t) ].join(' '); if( t.isSeeding( ) ) return TorrentRendererHelper.formatUL(t); return t.stateStr( ); }, render: function( controller, t, root ) { // name var is_stopped = t.state() === Torrent._StatusStopped; var e = root._name_container; $(e).toggleClass( 'paused', is_stopped ); setInnerHTML( e, t.name() ); // peer details var has_error = t._error !== Torrent._ErrNone; e = root._details_container; $(e).toggleClass('error', has_error ); setInnerHTML( e, this.getPeerDetails( t ) ); // progressbar TorrentRendererHelper.renderProgressbar( controller, t, root._progress_complete_container, root._progress_incomplete_container ); } }; /**** ***** ***** ****/ function TorrentRow( controller, generator ) { this.initialize( controller, generator ); } TorrentRow.prototype = { initialize: function( controller, generator ) { this._generator = generator; var root = generator.createRow( ); this._element = root; $(root).bind('dblclick', function(e) { controller.toggleInspector(); }); }, getElement: function( ) { return this._element; }, render: function( controller ) { var tor = this.getTorrent( ); if( tor !== null ) this._generator.render( controller, tor, this.getElement( ) ); }, isSelected: function( ) { return this.getElement().className.indexOf('selected') != -1; }, setSelected: function( flag ) { $(this.getElement()).toggleClass( 'selected', flag ); }, getToggleRunningButton: function( ) { return this.getElement()._toggle_running_button; }, setVisible: function( visible ) { this.getElement().style.display = visible ? 'block' : 'none'; if( !visible ) this.setSelected( false ); }, isVisible: function( visible ) { return this.getElement().style.display === 'block'; }, setTorrent: function( controller, t ) { if( this._torrent !== t ) { if( this._torrent ) $(this).unbind('dataChanged.renderer'); if(( this._torrent = t )) $(this).bind('dataChanged.renderer',this.render(controller)); } }, getTorrent: function() { return this._torrent; }, isEven: function() { return this.getElement().className.indexOf('even') != -1; }, setEven: function( even ) { if( this.isEven() != even ) $(this.getElement()).toggleClass('even', even); } };