      1 /*
      2 Script: Deluge.Details.Options.js
      3     The options 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
     34
     35 Ext.deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, {
     36
     37 	constructor: function(config) {
     38 		config = Ext.apply({
     39 			autoScroll: true,
     40 			bodyStyle: 'padding: 5px;',
     41 			border: false,
     42 			cls: 'x-deluge-options',
     43 			defaults: {
     44 				autoHeight: true,
     45 				labelWidth: 1,
     46 				defaultType: 'checkbox'
     47 			},
     48 			deferredRender: false,
     49 			layout: 'column',
     50 			title: _('Options')
     51 		}, config);
     52 		Ext.deluge.details.OptionsTab.superclass.constructor.call(this, config);
     53 	},
     54
     55 	initComponent: function() {
     56 		Ext.deluge.details.OptionsTab.superclass.initComponent.call(this);
     57
     58 		this.fieldsets = {}, this.fields = {};
     59 		this.optionsManager = new Deluge.OptionsManager({
     60 			defaults: {
     61 				'max_download_speed': -1,
     62 				'max_upload_speed': -1,
     63 				'max_connections': -1,
     64 				'max_upload_slots': -1,
     65 				'is_auto_managed': false,
     66 				'stop_at_ratio': false,
     67 				'stop_ratio': 2.0,
     68 				'remove_at_ratio': false,
     69 				'move_completed': null,
     70 				'private': false,
     71 				'prioritize_first_last': false
     72 			}
     73 		});
     74 		this.optionsManager.on('changed', this.onOptionChanged, this);
     75
     76 		/*
     77 		 * Bandwidth Options
     78 		 */
     79 		this.fieldsets.bandwidth = this.add({
     80 			xtype: 'fieldset',
     81 			defaultType: 'uxspinner',
     82 			bodyStyle: 'padding: 5px',
     83
     84 			layout: 'table',
     85 			layoutConfig: {columns: 3},
     86 			labelWidth: 150,
     87
     88 			style: 'margin-left: 10px; margin-right: 5px; padding: 5px',
     89 			title: _('Bandwidth'),
     90 			width: 250
     91 		});
     92
     93 		/*
     94 		 * Max Download Speed
     95 		 */
     96 		this.fieldsets.bandwidth.add({
     97 			xtype: 'label',
     98 			text: _('Max Download Speed'),
     99 			forId: 'max_download_speed',
    100 			cls: 'x-deluge-options-label'
    101 		});
    102 		this.fields.max_download_speed = this.fieldsets.bandwidth.add({
    103 			id: 'max_download_speed',
    104 			name: 'max_download_speed',
    105 			width: 70,
    106 			strategy: {
    107 				xtype: 'number',
    108 				decimalPrecision: 1,
    109 				minValue: -1,
    110 				maxValue: 99999
    111 			}
    112 		});
    113 		this.fieldsets.bandwidth.add({
    114 			xtype: 'label',
    115 			text: _('KiB/s'),
    116 			style: 'margin-left: 10px'
    117 		});
    118
    119 		/*
    120 		 * Max Upload Speed
    121 		 */
    122 		this.fieldsets.bandwidth.add({
    123 			xtype: 'label',
    124 			text: _('Max Upload Speed'),
    125 			forId: 'max_upload_speed',
    126 			cls: 'x-deluge-options-label'
    127 		});
    128 		this.fields.max_upload_speed = this.fieldsets.bandwidth.add({
    129 			id: 'max_upload_speed',
    130 			name: 'max_upload_speed',
    131 			width: 70,
    132 			value: -1,
    133 			strategy: {
    134 				xtype: 'number',
    135 				decimalPrecision: 1,
    136 				minValue: -1,
    137 				maxValue: 99999
    138 			}
    139 		});
    140 		this.fieldsets.bandwidth.add({
    141 			xtype: 'label',
    142 			text: _('KiB/s'),
    143 			style: 'margin-left: 10px'
    144 		});
    145
    146 		/*
    147 		 * Max Connections
    148 		 */
    149 		this.fieldsets.bandwidth.add({
    150 			xtype: 'label',
    151 			text: _('Max Connections'),
    152 			forId: 'max_connections',
    153 			cls: 'x-deluge-options-label'
    154 		});
    155 		this.fields.max_connections = this.fieldsets.bandwidth.add({
    156 			id: 'max_connections',
    157 			name: 'max_connections',
    158 			width: 70,
    159 			value: -1,
    160 			strategy: {
    161 				xtype: 'number',
    162 				decimalPrecision: 0,
    163 				minValue: -1,
    164 				maxValue: 99999
    165 			},
    166 			colspan: 2
    167 		});
    168
    169 		/*
    170 		 * Max Upload Slots
    171 		 */
    172 		this.fieldsets.bandwidth.add({
    173 			xtype: 'label',
    174 			text: _('Max Upload Slots'),
    175 			forId: 'max_upload_slots',
    176 			cls: 'x-deluge-options-label'
    177 		});
    178 		this.fields.max_upload_slots = this.fieldsets.bandwidth.add({
    179 			id: 'max_upload_slots',
    180 			name: 'max_upload_slots',
    181 			width: 70,
    182 			value: -1,
    183 			strategy: {
    184 				xtype: 'number',
    185 				decimalPrecision: 0,
    186 				minValue: -1,
    187 				maxValue: 99999
    188 			},
    189 			colspan: 2
    190 		});
    191
    192 		/*
    193 		 * Queue Options
    194 		 */
    195 		this.fieldsets.queue = this.add({
    196 			xtype: 'fieldset',
    197 			title: _('Queue'),
    198 			style: 'margin-left: 5px; margin-right: 5px; padding: 5px',
    199 			width: 210,
    200
    201 			layout: 'table',
    202 			layoutConfig: {columns: 2},
    203 			labelWidth: 0,
    204
    205 			defaults: {
    206 				fieldLabel: '',
    207 				labelSeparator: ''
    208 			}
    209 		});
    210
    211 		this.fields.is_auto_managed = this.fieldsets.queue.add({
    212 			fieldLabel: '',
    213 			labelSeparator: '',
    214 			id: 'is_auto_managed',
    215 			boxLabel: _('Auto Managed'),
    216 			width: 200,
    217 			colspan: 2
    218 		});
    219
    220 		this.fields.stop_at_ratio = this.fieldsets.queue.add({
    221 			fieldLabel: '',
    222 			labelSeparator: '',
    223 			id: 'stop_at_ratio',
    224 			width: 120,
    225 			boxLabel: _('Stop seed at ratio')
    226 		});
    227
    228 		this.fields.stop_ratio = this.fieldsets.queue.add({
    229 			xtype: 'uxspinner',
    230 			id: 'stop_ratio',
    231 			name: 'stop_ratio',
    232 			disabled: true,
    233 			width: 50,
    234 			value: 2.0,
    235 			strategy: {
    236 				xtype: 'number',
    237 				minValue: -1,
    238 				maxValue: 99999,
    239 				incrementValue: 0.1,
    240 				alternateIncrementValue: 1,
    241 				decimalPrecision: 1
    242 			}
    243 		});
    244
    245 		this.fields.remove_at_ratio = this.fieldsets.queue.add({
    246 			fieldLabel: '',
    247 			labelSeparator: '',
    248 			id: 'remove_at_ratio',
    249 			bodyStyle: 'padding-left: 10px',
    250 			boxLabel: _('Remove at ratio'),
    251 			disabled: true,
    252 			colspan: 2
    253 		});
    254
    255 		this.fields.move_completed = this.fieldsets.queue.add({
    256 			fieldLabel: '',
    257 			labelSeparator: '',
    258 			id: 'move_completed',
    259 			boxLabel: _('Move Completed'),
    260 			colspan: 2
    261 		});
    262
    263
    264 		/*
    265 		 * General Options
    266 		 */
    267 		this.rightColumn =  this.add({
    268 			border: false,
    269 			autoHeight: true,
    270 			style: 'margin-left: 5px',
    271 			width: 200
    272 		});
    273
    274 		this.fieldsets.general = this.rightColumn.add({
    275 			xtype: 'fieldset',
    276 			autoHeight: true,
    277 			defaultType: 'checkbox',
    278 			title: _('General'),
    279 			layout: 'form'
    280 		});
    281
    282 		this.fields['private'] = this.fieldsets.general.add({
    283 			fieldLabel: '',
    284 			labelSeparator: '',
    285 			boxLabel: _('Private'),
    286 			id: 'private'
    287 		});
    288
    289 		this.fields.prioritize_first_last = this.fieldsets.general.add({
    290 			fieldLabel: '',
    291 			labelSeparator: '',
    292 			boxLabel: _('Prioritize First/Last'),
    293 			id: 'prioritize_first_last'
    294 		});
    295
    296 		// Bind the fields so the options manager can manage them.
    297 		for (var id in this.fields) {
    298 			this.optionsManager.bind(id, this.fields[id]);
    299 		}
    300
    301 		/*
    302 		 * Buttons
    303 		 */
    304 		this.buttonPanel = this.rightColumn.add({
    305 			layout: 'column',
    306 			xtype: 'panel',
    307 			border: false
    308 		});
    309
    310 		// The buttons below are required to be added to a panel
    311 		// first as simply adding them to the column layout throws an
    312 		// error c.getSize() does not exist. This could be intentional
    313 		// or it may possible be a bug in ext-js. Take care when upgrading
    314 		// to ext-js 3.0.
    315
    316 		/*
    317 		 * Edit Trackers button
    318 		 */
    319 		this.buttonPanel.add({
    320 			xtype: 'panel',
    321 			border: false
    322 		}).add({
    323 			id: 'edit_trackers',
    324 			xtype: 'button',
    325 			text: _('Edit Trackers'),
    326 			cls: 'x-btn-text-icon',
    327 			iconCls: 'x-deluge-edit-trackers',
    328 			border: false,
    329 			width: 100,
    330 			handler: this.onEditTrackers,
    331 			scope: this
    332 		});
    333
    334 		/*
    335 		 * Apply button
    336 		 */
    337 		this.buttonPanel.add({
    338 			xtype: 'panel',
    339 			border: false
    340 		}).add({
    341 			id: 'apply',
    342 			xtype: 'button',
    343 			text: _('Apply'),
    344 			style: 'margin-left: 10px;',
    345 			border: false,
    346 			width: 100,
    347 			handler: this.onApply,
    348 			scope: this
    349 		});
    350 	},
    351
    352 	onRender: function(ct, position) {
    353 		Ext.deluge.details.OptionsTab.superclass.onRender.call(this, ct, position);
    354
    355 		// This is another hack I think, so keep an eye out here when upgrading.
    356 		this.layout = new Ext.layout.ColumnLayout();
    357 		this.layout.setContainer(this);
    358 		this.doLayout();
    359 	},
    360
    361 	clear: function() {
    362 		this.optionsManager.changeId(null);
    363 	},
    364
    365 	reset: function() {
    366 		if (this.torrentId) {
    367 			this.optionsManager.reset(this.torrentId);
    368 		}
    369 	},
    370
    371 	update: function(torrentId) {
    372 		this.torrentId = torrentId;
    373 		Deluge.Client.core.get_torrent_status(torrentId, Deluge.Keys.Options, {
    374 			success: this.onRequestComplete,
    375 			scope: this
    376 		});
    377 	},
    378
    379 	onApply: function() {
    380 		var changed = this.optionsManager.getChanged(this.torrentId);
    381 		if (!Ext.isEmpty(changed['prioritize_first_last'])) {
    382 			var value = changed['prioritize_first_last'];
    383 			Deluge.Client.core.set_torrent_prioritize_first_last(this.torrentId, value, {
    384 				success: function() {
    385 					this.optionsManager.set(this.torrentId, 'prioritize_first_last', value);
    386 				},
    387 				scope: this
    388 			});
    389 		}
    390 		Deluge.Client.core.set_torrent_options([this.torrentId], changed, {
    391 			success: function() {
    392 				this.optionsManager.set(this.torrentId, changed);
    393 				this.optionsManager.reset(this.torrentId);
    394 			},
    395 			scope: this
    396 		});
    397 	},
    398
    399 	onEditTrackers: function() {
    400 		Deluge.EditTrackers.show();
    401 	},
    402
    403 	onOptionChanged: function(id, key, newValue, oldValue) {
    404 		if (key == 'stop_at_ratio') {
    405 			this.fields.remove_at_ratio.setDisabled(!newValue);
    406 			this.fields.stop_ratio.setDisabled(!newValue);
    407 		}
    408 	},
    409
    410 	onRequestComplete: function(torrent, options) {
    411 		this.fields['private'].setDisabled(!torrent['private']);
    412 		delete torrent['private'];
    413
    414 		this.optionsManager.update(this.torrentId, torrent);
    415 	}
    416 });
    417 Deluge.Details.add(new Ext.deluge.details.OptionsTab());
    418