      1 /*
      2 Script: Deluge.Details.Files.js
      3     The files tab displayed in the details panel.
      4
      5 Copyright:
      6 	(C) Damien Churchill 2009 <damoxc@gmail.com>
      7 	This program is free software; you can redistribute it and/or modify
      8 	it under the terms of the GNU General Public License as published by
      9 	the Free Software Foundation; either version 3, or (at your option)
     10 	any later version.
     11
     12 	This program is distributed in the hope that it will be useful,
     13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 	GNU General Public License for more details.
     16
     17 	You should have received a copy of the GNU General Public License
     18 	along with this program.  If not, write to:
     19 		The Free Software Foundation, Inc.,
     20 		51 Franklin Street, Fifth Floor
     21 		Boston, MA  02110-1301, USA.
     22
     23     In addition, as a special exception, the copyright holders give
     24     permission to link the code of portions of this program with the OpenSSL
     25     library.
     26     You must obey the GNU General Public License in all respects for all of
     27     the code used other than OpenSSL. If you modify file(s) with this
     28     exception, you may extend this exception to your version of the file(s),
     29     but you are not obligated to do so. If you do not wish to do so, delete
     30     this exception statement from your version. If you delete this exception
     31     statement from all source files in the program, then also delete it here.
     32 */
     33 (function() {
     34 	/* Renderers for the column tree */
     35 	function fileProgressRenderer(value) {
     36 		var progress = value * 100;
     37 		return Deluge.progressBar(progress, this.width - 50, progress.toFixed(2) + '%', 0);
     38 	}
     39 	function priorityRenderer(value) {
     40 		return String.format('<div class="{0}">{1}</div>', FILE_PRIORITY_CSS[value], _(FILE_PRIORITY[value]));
     41 	}
     42
     43 	Ext.deluge.details.FilesTab = Ext.extend(Ext.tree.ColumnTree, {
     44
     45 		constructor: function(config) {
     46 			config = Ext.apply({
     47 				title: _('Files'),
     48 				rootVisible: false,
     49 				autoScroll: true,
     50 				selModel: new Ext.tree.MultiSelectionModel(),
     51
     52 				columns: [{
     53 					header: _('Filename'),
     54 					width: 330,
     55 					dataIndex: 'filename'
     56 				}, {
     57 					header: _('Size'),
     58 					width: 150,
     59 					dataIndex: 'size',
     60 					renderer: fsize
     61 				}, {
     62 					header: _('Progress'),
     63 					width: 150,
     64 					dataIndex: 'progress',
     65 					renderer: fileProgressRenderer
     66 				}, {
     67 					header: _('Priority'),
     68 					width: 150,
     69 					dataIndex: 'priority',
     70 					renderer: priorityRenderer
     71 				}],
     72
     73 				root: new Ext.tree.TreeNode({
     74 					text: 'Files'
     75 				})
     76 			}, config);
     77 			Ext.deluge.details.FilesTab.superclass.constructor.call(this, config);
     78 		},
     79
     80 		onRender: function(ct, position) {
     81 			Ext.deluge.details.FilesTab.superclass.onRender.call(this, ct, position);
     82 			Deluge.Menus.FilePriorities.on('itemclick', this.onItemClick, this);
     83 			this.on('contextmenu', this.onContextMenu, this);
     84 			this.sorter = new Ext.tree.TreeSorter(this, {
     85 				folderSort: true
     86 			});
     87 		},
     88
     89 		clear: function() {
     90 			var root = this.getRootNode();
     91 			if (!root.hasChildNodes()) return;
     92 			root.cascade(function(node) {
     93 				var parent = node.parentNode;
     94 				if (!parent) return;
     95 				if (!parent.ownerTree) return;
     96 				parent.removeChild(node);
     97 			});
     98 		},
     99
    100 		update: function(torrentId) {
    101 			if (this.torrentId != torrentId) {
    102 				this.clear();
    103 				this.torrentId = torrentId;
    104 			}
    105
    106 			Deluge.Client.web.get_torrent_files(torrentId, {
    107 				success: this.onRequestComplete,
    108 				scope: this,
    109 				torrentId: torrentId
    110 			});
    111 		},
    112
    113 		onContextMenu: function(node, e) {
    114 			e.stopEvent();
    115 			var selModel = this.getSelectionModel();
    116 			if (selModel.getSelectedNodes().length < 2) {
    117 				selModel.clearSelections();
    118 				node.select();
    119 			}
    120 			Deluge.Menus.FilePriorities.showAt(e.getPoint());
    121 		},
    122
    123 		onItemClick: function(baseItem, e) {
    124 			switch (baseItem.id) {
    125 				case 'expandAll':
    126 					this.expandAll();
    127 					break;
    128 				default:
    129 					var indexes = {};
    130 					function walk(node) {
    131 						if (Ext.isEmpty(node.attributes.fileIndex)) return;
    132 						indexes[node.attributes.fileIndex] = node.attributes.priority;
    133 					}
    134 					this.getRootNode().cascade(walk);
    135
    136 					var nodes = this.getSelectionModel().getSelectedNodes();
    137 					Ext.each(nodes, function(node) {
    138 						if (Ext.isEmpty(node.attributes.fileIndex)) return;
    139 						indexes[node.attributes.fileIndex] = baseItem.filePriority;
    140 					});
    141
    142 					var priorities = new Array(Ext.keys(indexes).length);
    143 					for (var index in indexes) {
    144 						priorities[index] = indexes[index];
    145 					}
    146
    147 					Deluge.Client.core.set_torrent_file_priorities(this.torrentId, priorities, {
    148 						success: function() {
    149 							Ext.each(nodes, function(node) {
    150 								node.setColumnValue(3, baseItem.filePriority);
    151 							});
    152 						},
    153 						scope: this
    154 					});
    155 					break;
    156 			}
    157 		},
    158
    159 		onRequestComplete: function(files, options) {
    160 			function walk(files, parent) {
    161 				for (var file in files) {
    162 					var item = files[file];
    163 					var child = parent.findChild('id', file);
    164 					if (Ext.type(item) == 'object') {
    165 						if (!child) {
    166 							child = new Ext.tree.TreeNode({
    167 								id: file,
    168 								text: file
    169 							});
    170 							parent.appendChild(child);
    171 						}
    172 						walk(item, child);
    173 					} else {
    174 						if (!child) {
    175 							child = new Ext.tree.ColumnTreeNode({
    176 								id: file,
    177 								filename: file,
    178 								text: file, // this needs to be here for sorting
    179 								fileIndex: item[0],
    180 								size: item[1],
    181 								progress: item[2],
    182 								priority: item[3],
    183 								leaf: true,
    184 								iconCls: 'x-deluge-file',
    185 								uiProvider: Ext.tree.ColumnNodeUI
    186 							});
    187 							parent.appendChild(child);
    188 						}
    189 						child.setColumnValue(1, item[1]);
    190 						child.setColumnValue(2, item[2]);
    191 						child.setColumnValue(3, item[3]);
    192 					}
    193 				}
    194 			}
    195 			var root = this.getRootNode();
    196 			walk(files, root);
    197 			root.firstChild.expand();
    198 		}
    199 	});
    200 	Deluge.Details.add(new Ext.deluge.details.FilesTab());
    201 })();
    202