#1435 selective downloading and file prioritization for web ui

This commit is contained in:
Mitchell Livingston 2009-03-14 21:33:08 +00:00
parent f8b1326101
commit 83929f8396
9 changed files with 453 additions and 92 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

View File

@ -14,6 +14,7 @@
<link media="screen and (min-device-width: 481px)" href="./stylesheets/common.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="./javascript/jquery/jquery.transmenu.min.js"></script>
<script type="text/javascript" src="./javascript/jquery/jquery.contextmenu.min.js"></script>
<script type="text/javascript" src="./javascript/jquery/jquery.tinysort.min.js"></script>
<script type="text/javascript" src="./javascript/menu.js"></script>
<script type="text/javascript" src="./javascript/jquery/jquery.form.min.js"></script>
<script type="text/javascript" src="./javascript/jquery/json.min.js"></script>
@ -61,6 +62,7 @@
<div id="inspector_tabs">
<div class="inspector_tab selected" id="inspector_tab_info"><a href="#info"><img src="images/buttons/info_general.png" alt="Information"/></a></div>
<div class="inspector_tab" id="inspector_tab_activity"><a href="#activity"><img src="images/buttons/info_activity.png" alt="Activity"/></a></div>
<div class="inspector_tab" id="inspector_tab_files"><a href="#files"><img src="images/buttons/info_files.png" alt="Files"/></a></div>
</div>
<div id="inspector_header">
@ -168,6 +170,11 @@
</div>
</div><!-- class="inspector_group"-->
</div><!-- id="inspector_tab_activity_container" -->
<div style="display:none;" class="inspector_container" id="inspector_tab_files_container">
<span id="inspector_file_list"></span>
</div><!-- id="inspector_tab_files_container" -->
</div>
<div id="torrent_container">

View File

@ -42,11 +42,6 @@ $(document).ready( function() {
transmission = new Transmission();
if ($.browser.safari) {
// Fix div height problem - causes scrollbar flash in
// firefox so have to be safari-specific
$('#torrent_inspector').css('height', '100%');
// Move search field's margin down for the styled input
$('#torrent_search').css('margin-top', 3);
}
@ -88,7 +83,7 @@ Array.prototype.clone = function () {
/**
* "innerHTML = html" is pretty slow in FF. Happily a lot of our innerHTML
* changes are triggered by periodic refreshes on torrents whose state hasn't
* changed sine the last update, so even this simple test helps a lot.
* changed since the last update, so even this simple test helps a lot.
*/
function setInnerHTML( e, html )
{

View File

@ -23,8 +23,7 @@ Torrent.prototype =
/*
* Constructor
*/
initialize: function(controller,data)
{
initialize: function(controller, data) {
// Create a new <li> element
var element = $('<li/>');
element.addClass('torrent');
@ -77,7 +76,7 @@ Torrent.prototype =
e.addClass('torrent_peer_details');
element.append( e );
element._peer_details_container = e;
// Set the torrent click observer
element.bind('click', {element: element}, this.clickTorrent);
if (!iPhone) element.bind('contextmenu', {element: element}, this.rightClickTorrent);
@ -89,12 +88,39 @@ Torrent.prototype =
// insert the element
$('#torrent_list').append(this._element);
this.initializeTorrentFilesInspectorGroup();
for (var i = 0; i < data.files.length; i++) {
var file = data.files[i];
file.index = i;
file.torrent = this;
file.priority = data.priorities[i];
file.wanted = data.wanted[i];
var torrentFile = new TorrentFile(file);
this._files.push(torrentFile);
this._fileList.append(
torrentFile.element().addClass(i % 2 ? 'even' : 'odd').addClass('inspector_torrent_file_list_entry')
);
}
// Update all the labels etc
this.refresh(data);
},
initializeTorrentFilesInspectorGroup: function() {
this._files = [];
this._fileList = $('<ul/>').addClass('inspector_torrent_file_list').addClass('inspector_group').hide().
append($('<li/>').addClass('inspector_group_label').append(
$('<div/>').append(this.name())
)
);
$('#inspector_file_list').append(this._fileList);
},
fileList: function() {
return this._fileList;
},
/*--------------------------------------------
*
* S E T T E R S / G E T T E R S
@ -131,8 +157,7 @@ Torrent.prototype =
getPercentDone: function() {
if( !this._sizeWhenDone ) return 1.0;
if( !this._leftUntilDone ) return 1.0;
return ( this._sizeWhenDone - this._leftUntilDone )
/ this._sizeWhenDone;
return ( this._sizeWhenDone - this._leftUntilDone ) / this._sizeWhenDone;
},
getPercentDoneStr: function() {
return Math.ratio( 100 * ( this._sizeWhenDone - this._leftUntilDone ),
@ -155,7 +180,9 @@ Torrent.prototype =
totalSeeders: function() { return this._total_seeders; },
uploadSpeed: function() { return this._upload_speed; },
uploadTotal: function() { return this._upload_total; },
showFileList: function() { if (this.fileList()) return this.fileList().show(); },
hideFileList: function() { if (this.fileList()) return this.fileList().hide(); },
/*--------------------------------------------
*
* E V E N T F U N C T I O N S
@ -252,8 +279,7 @@ Torrent.prototype =
/*
* Refresh display
*/
refreshData: function(data)
{
refreshData: function(data) {
// These variables never change after the inital load
if (data.isPrivate) this._is_private = data.isPrivate;
if (data.hashString) this._hashString = data.hashString;
@ -263,8 +289,8 @@ Torrent.prototype =
if (data.comment) this._comment = data.comment;
if (data.creator) this._creator = data.creator;
if (data.dateCreated) this._creator_date = data.dateCreated;
if (data.leftUntilDone) this._leftUntilDone = data.leftUntilDone;
if (data.sizeWhenDone) this._sizeWhenDone = data.sizeWhenDone;
if (data.leftUntilDone) this._leftUntilDone = data.leftUntilDone;
if (data.sizeWhenDone) this._sizeWhenDone = data.sizeWhenDone;
if (data.path) this._torrent_file = data.path;//FIXME
if (data.name) {
this._name = data.name;
@ -289,10 +315,18 @@ Torrent.prototype =
this._total_leechers = Math.max( 0, data.leechers );
this._total_seeders = Math.max( 0, data.seeders );
this._state = data.status;
if (data.files) {
for (var i = 0; i < data.files.length; i++) {
var file_data = data.files[i];
if (data.priorities) { file_data.priority = data.priorities[i]; }
if (data.wanted) { file_data.wanted = data.wanted[i]; }
this._files[i].readAttributes(file_data);
}
}
},
refreshHTML: function()
{
refreshHTML: function() {
var progress_details;
var peer_details;
var root = this._element;
@ -426,6 +460,12 @@ Torrent.prototype =
}
setInnerHTML( root._peer_details_container[0], peer_details );
// Update individual files within a torrent
jQuery.each(this._files, function () {
this.refreshHTML();
} );
},
/*
@ -587,3 +627,127 @@ Torrent.lookup = function( torrents, id )
var pos = Torrent.indexOf( torrents, id );
return pos >= 0 ? torrents[pos] : null;
};
function TorrentFile(file_data) {
this.initialize(file_data);
}
TorrentFile.prototype = {
initialize: function(file_data) {
this._torrent = file_data.torrent;
var pos = file_data.name.indexOf('/');
if (pos >= 0)
this.name = file_data.name.substring(pos + 1);
else
this.name = file_data.name;
this.readAttributes(file_data);
this._element = $('<li/>').append(
$('<div/>').addClass('file_wanted_control').
bind('click', { file: this }, this.fileWantedControlClicked)
).append(
this._priority_control = $('<div/>').addClass('file_priority_control').
bind('click', { file: this }, this.filePriorityControlClicked)
).append(
$('<div/>').addClass('inspector_torrent_file_list_entry_name').
append(this.name)
).append(
this._progress = $('<div/>').addClass('inspector_torrent_file_list_entry_progress')
)
},
readAttributes: function(file_data) {
if (undefined != file_data.index) this._index = file_data.index;
if (undefined != file_data.bytesCompleted) this._done = file_data.bytesCompleted;
if (undefined != file_data.length) this._size = file_data.length;
if (undefined != file_data.priority) this._prio = file_data.priority;
if (undefined != file_data.wanted) this._wanted = file_data.wanted;
},
element: function() {
return this._element;
},
setPriority: function(priority) {
var priority_level = { high: 1, normal: 0, low: -1 }[priority];
if (this._prio == priority_level) { return; }
this._prio = priority_level;
this._torrent._controller.changeFileCommand("priority-" + priority, this._torrent, this);
this.refreshPriorityHTML();
},
setWanted: function(wanted) {
this._wanted = wanted;
var command;
if (wanted) {
this.element().removeClass('skip');
command = 'files-wanted'
} else {
this.element().addClass('skip');
command = 'files-unwanted';
}
this._torrent._controller.changeFileCommand(command, this._torrent, this);
},
toggleWanted: function() {
this.setWanted(!this._wanted);
},
refreshHTML: function() {
this.refreshProgressHTML();
this.refreshWantedHTML();
this.refreshPriorityHTML();
},
refreshProgressHTML: function() {
progress_details = Math.formatBytes(this._done) + ' of ' +
Math.formatBytes(this._size) + ' (' +
Math.ratio(100 * this._done, this._size) + '%)';
setInnerHTML(this._progress[0], progress_details);
},
refreshWantedHTML: function() {
var element = this.element();
if (this._wanted && element.hasClass('skip'))
this.element().removeClass('skip');
else if (!this._wanted && !element.hasClass('skip'))
this.element().addClass('skip');
if (this._done < this._size && this.element().hasClass('complete'))
this.element().removeClass('complete');
else if (!this.element().hasClass('complete'))
this.element().addClass('complete');
},
refreshPriorityHTML: function() {
if (this['_last_refreshed_prio'] == this._prio) { return; }
var priority = { '1': 'high', '0': 'normal', '-1': 'low' }[new String(this._prio)];
var off_priorities = [ 'high', 'normal', 'low' ].sort(function(a,b) { return (a == priority) ? 1 : -1; } );
this._priority_control.addClass(priority).
removeClass(off_priorities[0]).
removeClass(off_priorities[1]);
this._last_refreshed_prio = this._prio;
},
fileWantedControlClicked: function(event) {
event.data.file.toggleWanted();
},
filePriorityControlClicked: function(event) {
var x = event.pageX;
var target = this;
while (target != null) {
x = x - target.offsetLeft;
target = target.offsetParent;
}
var file = event.data.file;
if (x < 8) { file.setPriority('low'); }
else if (x < 16) { file.setPriority('normal'); }
else { file.setPriority('high'); }
}
};

View File

@ -58,6 +58,7 @@ Transmission.prototype =
$('#prefs_cancel_button').bind('click', this.cancelPrefsClicked);
$('#inspector_tab_info').bind('click', this.inspectorTabClicked);
$('#inspector_tab_activity').bind('click', this.inspectorTabClicked);
$('#inspector_tab_files').bind('click', this.inspectorTabClicked);
if (iPhone) {
$('#torrent_inspector').bind('click', this.hideInspector);
$('#preferences_link').bind('click', this.releaseClutchPreferencesButton);
@ -83,28 +84,31 @@ Transmission.prototype =
// Get preferences & torrents from the daemon
this.remote.loadDaemonPrefs( );
this.remote.loadTorrents( );
this.remote.loadTorrents( true );
this.togglePeriodicRefresh( true );
},
preloadImages: function() {
if (iPhone) {
this.loadImages(
'images/buttons/info_activity.png',
'images/buttons/info_general.png',
'images/buttons/info_activity.png',
'images/buttons/info_files.png',
'images/buttons/toolbar_buttons.png',
'images/graphics/filter_bar.png',
'images/graphics/iphone_chrome.png',
'images/graphics/logo.png',
'images/progress/progress.png'
'images/graphics/logo.png'
);
} else {
this.loadImages(
'images/buttons/info_activity.png',
'images/buttons/info_general.png',
'images/buttons/info_activity.png',
'images/buttons/info_files.png',
'images/buttons/tab_backgrounds.png',
'images/buttons/toolbar_buttons.png',
'images/buttons/torrent_buttons.png',
'images/buttons/file_wanted_buttons.png',
'images/buttons/file_priority_buttons.png',
'images/graphics/chrome.png',
'images/graphics/filter_bar.png',
'images/graphics/logo.png',
@ -292,7 +296,18 @@ Transmission.prototype =
s.push( v[i] );
return s;
},
getDeselectedTorrents: function() {
var visible_torrent_ids = jQuery.map(this.getVisibleTorrents(), function(t) { return t.id(); } );
var s = [ ];
jQuery.each( this.getAllTorrents( ), function() {
var visible = (-1 != jQuery.inArray(this.id(), visible_torrent_ids));
if (!this.isSelected() || !visible)
s.push( this );
} );
return s;
},
getVisibleRows: function()
{
var rows = [ ];
@ -409,7 +424,7 @@ Transmission.prototype =
if( doUpdate )
this.selectionChanged( );
},
selectionChanged: function()
{
this.updateButtonStates();
@ -579,7 +594,9 @@ Transmission.prototype =
// Select the clicked tab, unselect the others,
// and display the appropriate info
var tab_ids = ['inspector_tab_info', 'inspector_tab_activity'];
var tab_ids = $(this).parent('#inspector_tabs').find('.inspector_tab').map(
function() { return $(this).attr('id'); }
);
for( var i=0; i<tab_ids.length; ++i ) {
if (this.id == tab_ids[i]) {
$('#' + tab_ids[i]).addClass('selected');
@ -643,12 +660,25 @@ Transmission.prototype =
// sanity check
if( !this[Prefs._RefreshRate] )
this[Prefs._RefreshRate] = 5;
this._periodic_refresh = setInterval('transmission.remote.loadTorrents()', this[Prefs._RefreshRate] * 1000 );
remote = this.remote;
this._periodic_refresh = setInterval(this.periodicRefresh, this[Prefs._RefreshRate] * 1000 );
} else {
clearInterval(this._periodic_refresh);
this._periodic_refresh = null;
}
},
periodicRefresh: function() {
// Note: 'this' != 'transmission instance' since it is being called by setInterval
if (!transmission._periodicRefreshIterations)
transmission._periodicRefreshIterations = 0;
remote.loadTorrents(transmission._periodicRefreshIterations++ % 10 == 0);
},
scheduleFileRefresh: function() {
this._periodicRefreshIterations = 0;
},
/*--------------------------------------------
*
@ -656,8 +686,7 @@ Transmission.prototype =
*
*--------------------------------------------*/
showPrefsDialog: function( )
{
showPrefsDialog: function( ) {
$('body').addClass('prefs_showing');
$('#prefs_container').show();
transmission.hideiPhoneAddressbar();
@ -865,7 +894,7 @@ Transmission.prototype =
var na = 'N/A';
$("#torrent_inspector_size, .inspector_row div").css('color', '#222');
if( torrents.length == 0 )
{
var ti = '#torrent_inspector_';
@ -890,7 +919,8 @@ Transmission.prototype =
setInnerHTML( $(ti+'progress')[0], na );
setInnerHTML( $(ti+'comment')[0], na );
setInnerHTML( $(ti+'creator')[0], na );
setInnerHTML( $(ti+'error')[0], na );
setInnerHTML( $(ti+'error')[0], na );
this.updateVisibleFileLists();
$("#torrent_inspector_size, .inspector_row > div:contains('N/A')").css('color', '#666');
return;
}
@ -918,7 +948,7 @@ Transmission.prototype =
date_created = Math.formatTimestamp( t._creator_date );
}
for( i=0; i<torrents.length; ++i ) {
for(i = 0; i < torrents.length; ++i ) {
var t = torrents[i];
sizeWhenDone += t._sizeWhenDone;
sizeDone += t._sizeWhenDone - t._leftUntilDone;
@ -979,6 +1009,16 @@ Transmission.prototype =
$(ti+'error')[0].innerHTML = error;
$(".inspector_row > div:contains('N/A')").css('color', '#666');
this.updateVisibleFileLists();
},
updateVisibleFileLists: function() {
jQuery.each( this.getSelectedTorrents(), function() {
this.showFileList();
} );
jQuery.each( this.getDeselectedTorrents(), function() {
this.hideFileList();
} );
},
/*
@ -990,7 +1030,7 @@ Transmission.prototype =
else
this.showInspector( );
},
showInspector: function() {
$('#torrent_inspector').show();
if (iPhone) {
@ -1054,36 +1094,53 @@ Transmission.prototype =
this.setFilter( Prefs._FilterAll );
},
updateTorrentsData: function( torrent_list ) {
var tr = this;
jQuery.each( torrent_list, function() {
var t = Torrent.lookup(tr._torrents, this.id);
if (t) t.refresh(this);
} );
},
/*
* Process got some new torrent data from the server
*/
updateTorrents: function( torrent_list )
{
updateAllTorrents: function( torrent_list ) {
var torrent_data;
var new_torrents = [];
var torrent_ids = [];
var handled = [];
// refresh existing torrents
this.updateTorrentsData( torrent_list );
// partition existing and new torrents
for( var i=0, len=torrent_list.length; i<len; ++i ) {
var data = torrent_list[i];
var t = Torrent.lookup( this._torrents, data.id );
if( !t )
new_torrents.push( data );
else {
t.refresh( data );
handled.push( t );
}
}
// Add any torrents that aren't already being displayed
// if file data is available
if( new_torrents.length ) {
for( var i=0, len=new_torrents.length; i<len; ++i ) {
var t = new Torrent( this, new_torrents[i] );
this._torrents.push( t );
handled.push( t );
if (data.files) {
for( var i=0, len=new_torrents.length; i<len; ++i ) {
var t = new Torrent( this, new_torrents[i] );
this._torrents.push( t );
handled.push( t );
}
this._torrents.sort( Torrent.compareById );
} else {
// There are new torrents available
// pick them up on the next refresh
this.scheduleFileRefresh();
}
this._torrents.sort( Torrent.compareById );
}
// Remove any torrents that weren't in the refresh list
@ -1099,6 +1156,7 @@ Transmission.prototype =
delete e._torrent;
e.hide( );
}
t.hideFileList();
this._torrents.splice( pos, 1 );
removedAny = true;
}
@ -1192,10 +1250,10 @@ Transmission.prototype =
args.dataType = 'xml';
args.iframe = true;
args.success = function( data ) {
tr.remote.loadTorrents( );
tr.remote.loadTorrents( true );
tr.togglePeriodicRefresh( true );
};
this.togglePeriodicRefresh( false );
tr.togglePeriodicRefresh( false );
$('#torrent_upload_form').ajaxSubmit( args );
}
}
@ -1290,6 +1348,9 @@ Transmission.prototype =
stopTorrents: function( torrents ) {
this.remote.stopTorrents( torrents );
},
changeFileCommand: function(command, torrent, file) {
this.remote.changeFileCommand(command, torrent, file)
},
hideiPhoneAddressbar: function(timeInSeconds) {
if( iPhone ) {

View File

@ -55,63 +55,92 @@ TransmissionRemote.prototype =
'Dismiss');
transmission.togglePeriodicRefresh(false);
},
sendRequest: function( url, data, success, contentType )
{
var o = { };
o.cache = false;
o.contentType = contentType;
o.data = data;
o.dataType = 'json';
o.error = this.ajaxError;
o.success = success;
o.type = 'POST';
o.url = url;
$.ajax( o );
sendRequest: function( data, success ) {
$.ajax( {
url: RPC._Root,
type: 'POST',
contentType: 'json',
dataType: 'json',
cache: false,
data: $.toJSON(data),
error: this.ajaxError,
success: success
} );
},
loadDaemonPrefs: function() {
var tr = this._controller;
var o = { };
o.method = 'session-get';
this.sendRequest( RPC._Root, $.toJSON(o), function(data) {
var o = { method: 'session-get' };
this.sendRequest( o, function(data) {
var o = data.arguments;
Prefs.getClutchPrefs( o );
tr.updatePrefs( o );
}, "json" );
} );
},
loadTorrents: function() {
loadTorrents: function(update_files) {
var tr = this._controller;
var o = { };
o.method = 'torrent-get'
o.arguments = { };
o.arguments.fields = [
'addedDate', 'announceURL', 'comment', 'creator',
'dateCreated', 'downloadedEver', 'error', 'errorString',
'eta', 'hashString', 'haveUnchecked', 'haveValid', 'id',
'isPrivate', 'leechers', 'leftUntilDone', 'name',
'peersConnected', 'peersGettingFromUs', 'peersSendingToUs',
'rateDownload', 'rateUpload', 'seeders', 'sizeWhenDone',
'status', 'swarmSpeed', 'totalSize', 'uploadedEver' ];
this.sendRequest( RPC._Root, $.toJSON(o), function(data) {
tr.updateTorrents( data.arguments.torrents );
}, "json" );
var o = {
method: 'torrent-get',
arguments: { fields: [
'addedDate', 'announceURL', 'comment', 'creator',
'dateCreated', 'downloadedEver', 'error', 'errorString',
'eta', 'hashString', 'haveUnchecked', 'haveValid', 'id',
'isPrivate', 'leechers', 'leftUntilDone', 'name',
'peersConnected', 'peersGettingFromUs', 'peersSendingToUs',
'rateDownload', 'rateUpload', 'seeders', 'sizeWhenDone',
'status', 'swarmSpeed', 'totalSize', 'uploadedEver' ]
}
};
if (update_files) {
o.arguments.fields.push('files');
o.arguments.fields.push('wanted');
o.arguments.fields.push('priorities');
}
this.sendRequest( o, function(data) {
tr.updateAllTorrents( data.arguments.torrents );
} );
},
loadTorrentFiles: function( torrent_ids ) {
var tr = this._controller;
this.sendRequest( {
method: 'torrent-get',
arguments: { fields: [ 'files', 'wanted', 'priorities'] },
ids: torrent_ids
}, function(data) {
tr.updateTorrentsData( data.arguments.torrents );
} );
},
changeFileCommand: function( command, torrent, file ) {
var remote = this;
var torrent_ids = [ torrent.id() ];
var o = {
method: 'torrent-set',
arguments: { ids: torrent_ids }
};
o.arguments[command] = [ file._index ];
this.sendRequest( o, function( ) {
remote.loadTorrentFiles( torrent_ids );
} );
},
sendTorrentCommand: function( method, torrents ) {
var remote = this;
var o = { };
o.method = method;
o.arguments = { };
o.arguments.ids = [ ];
var o = {
method: method,
arguments: { ids: [ ] }
};
if( torrents != null )
for( var i=0, len=torrents.length; i<len; ++i )
o.arguments.ids.push( torrents[i].id() );
this.sendRequest( RPC._Root, $.toJSON(o), function( ) {
this.sendRequest( o, function( ) {
remote.loadTorrents();
}, "json" );
} );
},
startTorrents: function( torrents ) {
this.sendTorrentCommand( 'torrent-start', torrents );
},
@ -149,11 +178,12 @@ TransmissionRemote.prototype =
},
savePrefs: function( args ) {
var remote = this;
var o = { };
o.method = 'session-set';
o.arguments = args;
this.sendRequest( RPC._Root, $.toJSON(o), function(){
var o = {
method: 'session-set',
arguments: args
};
this.sendRequest( o, function() {
remote.loadDaemonPrefs();
}, "json" );
} );
}
};

View File

@ -514,6 +514,7 @@ div#torrent_inspector {
border-left: 1px solid #888;
z-index: 2;
text-align: left;
overflow: auto;
}
div#torrent_inspector #torrent_inspector_name {
margin: 0;
@ -532,9 +533,9 @@ div#inspector_header {
padding-right: 10px;
}
div#inspector_tabs {
width: 189px;
margin: 0 auto;
padding-top: 10px;
width: 140px;
}
.inspector_tab {
float: left;
@ -548,8 +549,8 @@ div#inspector_tabs {
background-position: left -26px; /* the highlighted part of the image */
}
.inspector_container {
margin: 10px;
width: 330px; /* inspector_width==350 - ((margin==10)*2) */
margin: 3%;
width: 96%;
}
.inspector_group {
display: table;
@ -575,6 +576,109 @@ div#inspector_tabs {
width: 230px; /* inspector_container_width==330 - inspector_label_width==100 */
}
/* Files Inspector Tab */
#inspector_file_list {
padding: 0 0 0 0;
margin: 0 0 0 0;
text-align: left;
cursor: default;
overflow: hidden;
}
ul.inspector_torrent_file_list {
width: 100%;
margin: 0 0 0 0;
padding-bottom: 10px;
text-align: left;
display: block;
cursor: default;
list-style-type: none;
list-style: none;
list-style-image: none;
}
li.inspector_torrent_file_list_entry {
padding: 3px 0 3px 2px;
display: block;
}
li.inspector_torrent_file_list_entry.skip {
color: #666;
}
li.inspector_torrent_file_list_entry.even {
background-color: #EEEEEE;
}
div.inspector_torrent_file_list_entry_name {
font-size: 1.2em;
font-weight: bold;
color: #222;
margin-left: 20px;
}
li.inspector_torrent_file_list_entry.skip>.inspector_torrent_file_list_entry_name {
color: #666;
}
li.inspector_torrent_file_list_entry.even {
background-color: #EEEEEE;
}
div.inspector_torrent_file_list_entry_progress {
font-size: 1em;
color: #666;
margin-left: 20px;
}
div.file_wanted_control {
background-position: left -16px;
float: left;
position: absolute;
cursor: pointer;
margin: 0 0 0 0;
width: 16px;
height: 16px;
background-image: url('../images/buttons/file_wanted_buttons.png');
background-repeat: no-repeat;
background-color: transparent;
}
li.inspector_torrent_file_list_entry.skip>.file_wanted_control {
background-position: left 0px;
}
li.inspector_torrent_file_list_entry.complete>.file_wanted_control {
background-position: -16px -16px;
}
li.inspector_torrent_file_list_entry.complete.skip>.file_wanted_control {
background-position: -16px 0px;
}
div.file_priority_control {
float: right;
margin: 0 0 0 0;
width: 24px;
height: 12px;
background-image: url('../images/buttons/file_priority_buttons.png');
background-repeat: no-repeat;
background-color: transparent;
cursor: pointer;
}
div.file_priority_control.high {
background-position: left -12px;
}
div.file_priority_control.high:hover {
background-position: right -12px;
}
div.file_priority_control.normal {
background-position: left -24px;
}
div.file_priority_control.normal:hover {
background-position: right -24px;
}
div.file_priority_control.low {
background-position: left 0px;
}
div.file_priority_control.low:hover {
background-position: right 0px;
}
/*--------------------------------------
*
* T O R R E N T F O O T E R