diff options
Diffstat (limited to 'deluge/ui/web/js/deluge-all/TorrentGrid.js')
-rw-r--r-- | deluge/ui/web/js/deluge-all/TorrentGrid.js | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/deluge/ui/web/js/deluge-all/TorrentGrid.js b/deluge/ui/web/js/deluge-all/TorrentGrid.js new file mode 100644 index 0000000..5db7e9f --- /dev/null +++ b/deluge/ui/web/js/deluge-all/TorrentGrid.js @@ -0,0 +1,516 @@ +/** + * Deluge.TorrentGrid.js + * + * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> + * + * This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with + * the additional special exception to link portions of this program with the OpenSSL library. + * See LICENSE for more details. + */ + +(function () { + /* Renderers for the Torrent Grid */ + function queueRenderer(value) { + return value == -1 ? '' : value + 1; + } + function torrentNameRenderer(value, p, r) { + return String.format( + '<div class="torrent-name x-deluge-{0}">{1}</div>', + r.data['state'].toLowerCase(), + Ext.util.Format.htmlEncode(value) + ); + } + function torrentSpeedRenderer(value) { + if (!value) return; + return fspeed(value); + } + function torrentLimitRenderer(value) { + if (value == -1) return ''; + return fspeed(value * 1024.0); + } + function torrentProgressRenderer(value, p, r) { + value = new Number(value); + var progress = value; + var text = _(r.data['state']) + ' ' + value.toFixed(2) + '%'; + if (this.style) { + var style = this.style; + } else { + var style = p.style; + } + var width = new Number(style.match(/\w+:\s*(\d+)\w+/)[1]); + return Deluge.progressBar(value, width - 8, text); + } + function seedsRenderer(value, p, r) { + if (r.data['total_seeds'] > -1) { + return String.format('{0} ({1})', value, r.data['total_seeds']); + } else { + return value; + } + } + function peersRenderer(value, p, r) { + if (r.data['total_peers'] > -1) { + return String.format('{0} ({1})', value, r.data['total_peers']); + } else { + return value; + } + } + function availRenderer(value, p, r) { + return value < 0 ? '∞' : parseFloat(new Number(value).toFixed(3)); + } + function trackerRenderer(value, p, r) { + return String.format( + '<div style="background: url(' + + deluge.config.base + + 'tracker/{0}) no-repeat; background-size: contain; padding-left: 20px;">{0}</div>', + Ext.util.Format.htmlEncode(value) + ); + } + + function etaSorter(eta) { + if (eta === 0) return Number.MAX_VALUE; + if (eta <= -1) return Number.MAX_SAFE_INTEGER; + return eta; + } + + function dateOrNever(date) { + return date > 0.0 ? fdate(date) : _('Never'); + } + + function timeOrInf(time) { + if (time === 0) return ''; + if (time <= -1) return '∞'; + return ftime(time); + } + + /** + * Deluge.TorrentGrid Class + * + * @author Damien Churchill <damoxc@gmail.com> + * @version 1.3 + * + * @class Deluge.TorrentGrid + * @extends Ext.grid.GridPanel + * @constructor + * @param {Object} config Configuration options + */ + Deluge.TorrentGrid = Ext.extend(Ext.grid.GridPanel, { + // object to store contained torrent ids + torrents: {}, + + columns: [ + { + id: 'queue', + header: '#', + width: 30, + sortable: true, + renderer: queueRenderer, + dataIndex: 'queue', + }, + { + id: 'name', + header: _('Name'), + width: 150, + sortable: true, + renderer: torrentNameRenderer, + dataIndex: 'name', + }, + { + header: _('Size'), + width: 75, + sortable: true, + renderer: fsize, + dataIndex: 'total_wanted', + }, + { + header: _('Progress'), + width: 150, + sortable: true, + renderer: torrentProgressRenderer, + dataIndex: 'progress', + }, + { + header: _('Seeds'), + hidden: true, + width: 60, + sortable: true, + renderer: seedsRenderer, + dataIndex: 'num_seeds', + }, + { + header: _('Peers'), + hidden: true, + width: 60, + sortable: true, + renderer: peersRenderer, + dataIndex: 'num_peers', + }, + { + header: _('Down Speed'), + width: 80, + sortable: true, + renderer: torrentSpeedRenderer, + dataIndex: 'download_payload_rate', + }, + { + header: _('Up Speed'), + width: 80, + sortable: true, + renderer: torrentSpeedRenderer, + dataIndex: 'upload_payload_rate', + }, + { + header: _('ETA'), + width: 60, + sortable: true, + renderer: timeOrInf, + dataIndex: 'eta', + }, + { + header: _('Ratio'), + hidden: true, + width: 60, + sortable: true, + renderer: availRenderer, + dataIndex: 'ratio', + }, + { + header: _('Avail'), + hidden: true, + width: 60, + sortable: true, + renderer: availRenderer, + dataIndex: 'distributed_copies', + }, + { + header: _('Added'), + hidden: true, + width: 80, + sortable: true, + renderer: fdate, + dataIndex: 'time_added', + }, + { + header: _('Complete Seen'), + hidden: true, + width: 80, + sortable: true, + renderer: dateOrNever, + dataIndex: 'last_seen_complete', + }, + { + header: _('Completed'), + hidden: true, + width: 80, + sortable: true, + renderer: dateOrNever, + dataIndex: 'completed_time', + }, + { + header: _('Tracker'), + hidden: true, + width: 120, + sortable: true, + renderer: trackerRenderer, + dataIndex: 'tracker_host', + }, + { + header: _('Download Folder'), + hidden: true, + width: 120, + sortable: true, + renderer: fplain, + dataIndex: 'download_location', + }, + { + header: _('Owner'), + width: 80, + sortable: true, + renderer: fplain, + dataIndex: 'owner', + }, + { + header: _('Public'), + hidden: true, + width: 80, + sortable: true, + renderer: fplain, + dataIndex: 'public', + }, + { + header: _('Shared'), + hidden: true, + width: 80, + sortable: true, + renderer: fplain, + dataIndex: 'shared', + }, + { + header: _('Downloaded'), + hidden: true, + width: 75, + sortable: true, + renderer: fsize, + dataIndex: 'total_done', + }, + { + header: _('Uploaded'), + hidden: true, + width: 75, + sortable: true, + renderer: fsize, + dataIndex: 'total_uploaded', + }, + { + header: _('Remaining'), + hidden: true, + width: 75, + sortable: true, + renderer: fsize, + dataIndex: 'total_remaining', + }, + { + header: _('Down Limit'), + hidden: true, + width: 75, + sortable: true, + renderer: torrentLimitRenderer, + dataIndex: 'max_download_speed', + }, + { + header: _('Up Limit'), + hidden: true, + width: 75, + sortable: true, + renderer: torrentLimitRenderer, + dataIndex: 'max_upload_speed', + }, + { + header: _('Seeds:Peers'), + hidden: true, + width: 75, + sortable: true, + renderer: availRenderer, + dataIndex: 'seeds_peers_ratio', + }, + { + header: _('Last Transfer'), + hidden: true, + width: 75, + sortable: true, + renderer: ftime, + dataIndex: 'time_since_transfer', + }, + ], + + meta: { + root: 'torrents', + idProperty: 'id', + fields: [ + { + name: 'queue', + sortType: Deluge.data.SortTypes.asQueuePosition, + }, + { name: 'name', sortType: Deluge.data.SortTypes.asName }, + { name: 'total_wanted', type: 'int' }, + { name: 'state' }, + { name: 'progress', type: 'float' }, + { name: 'num_seeds', type: 'int' }, + { name: 'total_seeds', type: 'int' }, + { name: 'num_peers', type: 'int' }, + { name: 'total_peers', type: 'int' }, + { name: 'download_payload_rate', type: 'int' }, + { name: 'upload_payload_rate', type: 'int' }, + { name: 'eta', type: 'int', sortType: etaSorter }, + { name: 'ratio', type: 'float' }, + { name: 'distributed_copies', type: 'float' }, + { name: 'time_added', type: 'int' }, + { name: 'last_seen_complete', type: 'int' }, + { name: 'completed_time', type: 'int' }, + { name: 'tracker_host' }, + { name: 'download_location' }, + { name: 'total_done', type: 'int' }, + { name: 'total_uploaded', type: 'int' }, + { name: 'total_remaining', type: 'int' }, + { name: 'max_download_speed', type: 'int' }, + { name: 'max_upload_speed', type: 'int' }, + { name: 'seeds_peers_ratio', type: 'float' }, + { name: 'time_since_transfer', type: 'int' }, + ], + }, + + keys: [ + { + key: 'a', + ctrl: true, + stopEvent: true, + handler: function () { + deluge.torrents.getSelectionModel().selectAll(); + }, + }, + { + key: [46], + stopEvent: true, + handler: function () { + ids = deluge.torrents.getSelectedIds(); + deluge.removeWindow.show(ids); + }, + }, + ], + + constructor: function (config) { + config = Ext.apply( + { + id: 'torrentGrid', + store: new Ext.data.JsonStore(this.meta), + columns: this.columns, + keys: this.keys, + region: 'center', + cls: 'deluge-torrents', + stripeRows: true, + autoExpandColumn: 'name', + autoExpandMin: 150, + deferredRender: false, + autoScroll: true, + stateful: true, + view: new Ext.ux.grid.BufferView({ + rowHeight: 26, + scrollDelay: false, + }), + }, + config + ); + Deluge.TorrentGrid.superclass.constructor.call(this, config); + }, + + initComponent: function () { + Deluge.TorrentGrid.superclass.initComponent.call(this); + deluge.events.on('torrentsRemoved', this.onTorrentsRemoved, this); + deluge.events.on('disconnect', this.onDisconnect, this); + + this.on('rowcontextmenu', function (grid, rowIndex, e) { + e.stopEvent(); + var selection = grid.getSelectionModel(); + if (!selection.isSelected(rowIndex)) { + selection.selectRow(rowIndex); + } + deluge.menus.torrent.showAt(e.getPoint()); + }); + }, + + /** + * Returns the record representing the torrent at the specified index. + * + * @param index {int} The row index of the torrent you wish to retrieve. + * @return {Ext.data.Record} The record representing the torrent. + */ + getTorrent: function (index) { + return this.getStore().getAt(index); + }, + + /** + * Returns the currently selected record. + * @ return {Array/Ext.data.Record} The record(s) representing the rows + */ + getSelected: function () { + return this.getSelectionModel().getSelected(); + }, + + /** + * Returns the currently selected records. + */ + getSelections: function () { + return this.getSelectionModel().getSelections(); + }, + + /** + * Return the currently selected torrent id. + * @return {String} The currently selected id. + */ + getSelectedId: function () { + return this.getSelectionModel().getSelected().id; + }, + + /** + * Return the currently selected torrent ids. + * @return {Array} The currently selected ids. + */ + getSelectedIds: function () { + var ids = []; + Ext.each(this.getSelectionModel().getSelections(), function (r) { + ids.push(r.id); + }); + return ids; + }, + + update: function (torrents, wipe) { + var store = this.getStore(); + + // Need to perform a complete reload of the torrent grid. + if (wipe) { + store.removeAll(); + this.torrents = {}; + } + + var newTorrents = []; + + // Update and add any new torrents. + for (var t in torrents) { + var torrent = torrents[t]; + + if (this.torrents[t]) { + var record = store.getById(t); + record.beginEdit(); + for (var k in torrent) { + if (record.get(k) != torrent[k]) { + record.set(k, torrent[k]); + } + } + record.endEdit(); + } else { + var record = new Deluge.data.Torrent(torrent); + record.id = t; + this.torrents[t] = 1; + newTorrents.push(record); + } + } + store.add(newTorrents); + + // Remove any torrents that should not be in the store. + store.each(function (record) { + if (!torrents[record.id]) { + store.remove(record); + delete this.torrents[record.id]; + } + }, this); + store.commitChanges(); + + var sortState = store.getSortState(); + if (!sortState) return; + store.sort(sortState.field, sortState.direction); + }, + + // private + onDisconnect: function () { + this.getStore().removeAll(); + this.torrents = {}; + }, + + // private + onTorrentsRemoved: function (torrentIds) { + var selModel = this.getSelectionModel(); + Ext.each( + torrentIds, + function (torrentId) { + var record = this.getStore().getById(torrentId); + if (selModel.isSelected(record)) { + selModel.deselectRow(this.getStore().indexOf(record)); + } + this.getStore().remove(record); + delete this.torrents[torrentId]; + }, + this + ); + }, + }); + deluge.torrents = new Deluge.TorrentGrid(); +})(); |