1 /*
  2 Script: Deluge.EditTrackers.js
  3     Contains the edit trackers window.
  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 */
 34 
 35 (function() {
 36 	Ext.deluge.AddTracker = Ext.extend(Ext.Window, {
 37 		constructor: function(config) {
 38 			config = Ext.apply({
 39 				title: _('Add Tracker'),
 40 				width: 375,
 41 				height: 150,
 42 				bodyStyle: 'padding: 5px',
 43 				layout: 'fit',
 44 				buttonAlign: 'right',
 45 				closeAction: 'hide',
 46 				closable: true,
 47 				iconCls: 'x-deluge-edit-trackers',
 48 				plain: true,
 49 				resizable: false
 50 			}, config);
 51 			Ext.deluge.AddTracker.superclass.constructor.call(this, config);
 52 		},
 53 		
 54 		initComponent: function() {
 55 			Ext.deluge.AddTracker.superclass.initComponent.call(this);
 56 			
 57 			this.addButton(_('Cancel'), this.onCancel, this);
 58 			this.addButton(_('Add'), this.onAdd, this);
 59 			this.addEvents('add');
 60 			
 61 			this.form = this.add({
 62 				xtype: 'form',
 63 				defaultType: 'textarea',
 64 				baseCls: 'x-plain',
 65 				labelWidth: 55,
 66 				items: [{
 67 					fieldLabel: _('Trackers'),
 68 					name: 'trackers',
 69 					anchor: '100%'
 70 				}]
 71 			})
 72 		},
 73 		
 74 		onCancel: function() {
 75 			this.form.getForm().findField('trackers').setValue('');
 76 			this.hide();
 77 		},
 78 		
 79 		onAdd: function() {
 80 			var trackers = this.form.getForm().findField('trackers').getValue();
 81 			trackers = trackers.split('\n');
 82 			
 83 			var cleaned = [];
 84 			Ext.each(trackers, function(tracker) {
 85 				if (Ext.form.VTypes.url(tracker)) {
 86 					cleaned.push(tracker);
 87 				}
 88 			}, this);
 89 			this.fireEvent('add', cleaned);
 90 			this.hide();
 91 			this.form.getForm().findField('trackers').setValue('');
 92 		}
 93 	});
 94 	
 95 	Ext.deluge.EditTracker = Ext.extend(Ext.Window, {
 96 		constructor: function(config) {
 97 			config = Ext.apply({
 98 				title: _('Edit Tracker'),
 99 				width: 375,
100 				height: 110,
101 				bodyStyle: 'padding: 5px',
102 				layout: 'fit',
103 				buttonAlign: 'right',
104 				closeAction: 'hide',
105 				closable: true,
106 				iconCls: 'x-deluge-edit-trackers',
107 				plain: true,
108 				resizable: false
109 			}, config);
110 			Ext.deluge.EditTracker.superclass.constructor.call(this, config);
111 		},
112 		
113 		initComponent: function() {
114 			Ext.deluge.EditTracker.superclass.initComponent.call(this);
115 			
116 			this.addButton(_('Cancel'), this.onCancel, this);
117 			this.addButton(_('Save'), this.onSave, this);
118 			this.on('hide', this.onHide, this);
119 			
120 			this.form = this.add({
121 				xtype: 'form',
122 				defaultType: 'textfield',
123 				baseCls: 'x-plain',
124 				labelWidth: 55,
125 				items: [{
126 					fieldLabel: _('Tracker'),
127 					name: 'tracker',
128 					anchor: '100%'
129 				}]
130 			});
131 		},
132 		
133 		show: function(record) {
134 			Ext.deluge.EditTracker.superclass.show.call(this);
135 			
136 			this.record = record;
137 			this.form.getForm().findField('tracker').setValue(record.data['url']);
138 		},
139 		
140 		onCancel: function() {
141 			this.hide();
142 		},
143 		
144 		onHide: function() {
145 			this.form.getForm().findField('tracker').setValue('');
146 		},
147 		
148 		onSave: function() {
149 			var url = this.form.getForm().findField('tracker').getValue();
150 			this.record.set('url', url);
151 			this.record.commit();
152 			this.hide();
153 		}
154 	});
155 	
156 	Ext.deluge.EditTrackers = Ext.extend(Ext.Window, {
157 	
158 		constructor: function(config) {
159 			config = Ext.apply({
160 				title: _('Edit Trackers'),
161 				width: 350,
162 				height: 220,
163 				bodyStyle: 'padding: 5px',
164 				layout: 'fit',
165 				buttonAlign: 'right',
166 				closeAction: 'hide',
167 				closable: true,
168 				iconCls: 'x-deluge-edit-trackers',
169 				plain: true,
170 				resizable: true
171 			}, config);
172 			Ext.deluge.EditTrackers.superclass.constructor.call(this, config);
173 		},
174 		
175 		initComponent: function() {
176 			Ext.deluge.EditTrackers.superclass.initComponent.call(this);
177 			
178 			this.addButton(_('Cancel'), this.onCancel, this);
179 			this.addButton(_('Ok'), this.onOk, this);
180 			this.addEvents('save');
181 			
182 			this.on('show', this.onShow, this);
183 			this.on('save', this.onSave, this);
184 			
185 			this.addWindow = new Ext.deluge.AddTracker();
186 			this.addWindow.on('add', this.onAddTrackers, this);
187 			this.editWindow = new Ext.deluge.EditTracker();
188 			
189 			this.grid = this.add({
190 				xtype: 'grid',
191 				store: new Ext.data.SimpleStore({
192 					fields: [
193 						{name: 'tier', mapping: 0},
194 						{name: 'url', mapping: 1}
195 					]
196 				}),
197 				columns: [{
198 					header: _('Tier'),
199 					width: 50,
200 					sortable: true,
201 					renderer: fplain,
202 					dataIndex: 'tier'
203 				}, {
204 					id:'tracker',
205 					header: _('Tracker'),
206 					sortable: true,
207 					renderer: fplain,
208 					dataIndex: 'url'
209 				}],
210 				stripeRows: true,
211 				selModel: new Ext.grid.RowSelectionModel({
212 					singleSelect: true,
213 					listeners: {
214 						'selectionchange': {fn: this.onSelect, scope: this}
215 					}
216 				}),
217 				autoExpandColumn: 'tracker',
218 				deferredRender:false,
219 				autoScroll:true,
220 				margins: '0 0 0 0',
221 				bbar: new Ext.Toolbar({
222 					items: [
223 						{
224 							cls: 'x-btn-text-icon',
225 							text: _('Up'),
226 							icon: '/icons/up.png',
227 							handler: this.onUp,
228 							scope: this
229 						}, {
230 							cls: 'x-btn-text-icon',
231 							text: _('Down'),
232 							icon: '/icons/down.png',
233 							handler: this.onDown,
234 							scope: this
235 						}, '->', {
236 							cls: 'x-btn-text-icon',
237 							text: _('Add'),
238 							icon: '/icons/add.png',
239 							handler: this.onAdd,
240 							scope: this
241 						}, {
242 							cls: 'x-btn-text-icon',
243 							text: _('Edit'),
244 							icon: '/icons/edit_trackers.png',
245 							handler: this.onEdit,
246 							scope: this
247 						}, {
248 							cls: 'x-btn-text-icon',
249 							text: _('Remove'),
250 							icon: '/icons/remove.png',
251 							handler: this.onRemove,
252 							scope: this
253 						}
254 					]
255 				})
256 			});
257 		},
258 		
259 		onAdd: function() {
260 			this.addWindow.show();
261 		},
262 		
263 		onAddTrackers: function(trackers) {
264 			var store = this.grid.getStore();
265 			Ext.each(trackers, function(tracker) {
266 				var duplicate = false, heightestTier = -1;
267 				store.each(function(record) {
268 					if (record.get('tier') > heightestTier) {
269 						heightestTier = record.get('tier');
270 					}
271 					if (tracker == record.get('tracker')) {
272 						duplicate = true;
273 						return false;
274 					}
275 				}, this);
276 				if (!duplicate) {
277 					store.loadData([[heightestTier + 1, tracker]], true);
278 				}
279 			}, this);
280 		},
281 		
282 		onCancel: function() {
283 			this.hide();
284 		},
285 		
286 		onEdit: function() {
287 			var r = this.grid.getSelectionModel().getSelected();
288 			this.editWindow.show(r);
289 		},
290 		
291 		onHide: function() {
292 			this.grid.getStore().removeAll();
293 		},
294 		
295 		onOk: function() {
296 			var trackers = [];
297 			this.grid.getStore().each(function(record) {
298 				trackers.push({
299 					'tier': record.get('tier'),
300 					'url': record.get('url')
301 				})
302 			}, this);
303 			
304 			Deluge.Client.core.set_torrent_trackers(this.torrentId, trackers, {
305 				failure: this.onSaveFail,
306 				scope: this
307 			});
308 
309 			this.hide();
310 		},
311 		
312 		onRemove: function() {
313 			// Remove from the grid
314 			var r = this.grid.getSelectionModel().getSelected();
315 			this.grid.getStore().remove(r);
316 		},
317 		
318 		onRequestComplete: function(status) {
319 			var trackers = [];
320 			Ext.each(status['trackers'], function(tracker) {
321 				trackers.push([tracker['tier'], tracker['url']]);
322 			});
323 			this.grid.getStore().loadData(trackers);
324 		},
325 		
326 		onSaveFail: function() {
327 			
328 		},
329 		
330 		onSelect: function(sm) {
331 			if (sm.hasSelection()) {
332 				this.grid.getBottomToolbar().items.get(4).enable();
333 			}
334 		},
335 		
336 		onShow: function() {
337 			this.grid.getBottomToolbar().items.get(4).disable();
338 			var r = Deluge.Torrents.getSelected();
339 			this.torrentId = r.id;
340 			Deluge.Client.core.get_torrent_status(r.id, ['trackers'], {
341 				success: this.onRequestComplete,
342 				scope: this
343 			});
344 		}
345 	});
346 	Deluge.EditTrackers = new Ext.deluge.EditTrackers();
347 })();