diff options
Diffstat (limited to 'deluge/ui/web/js')
-rw-r--r-- | deluge/ui/web/js/deluge-all-debug.js | 9969 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all.js | 291 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/ConnectionManager.js | 21 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/Sidebar.js | 18 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/UI.js | 31 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/details/FilesTab.js | 4 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/details/OptionsTab.js | 4 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/preferences/BandwidthPage.js | 2 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/preferences/DaemonPage.js | 2 | ||||
-rw-r--r-- | deluge/ui/web/js/deluge-all/preferences/InterfacePage.js | 2 | ||||
-rw-r--r-- | deluge/ui/web/js/extjs/ext-extensions-debug.js | 2927 | ||||
-rw-r--r-- | deluge/ui/web/js/extjs/ext-extensions.js | 84 | ||||
-rw-r--r-- | deluge/ui/web/js/gettext.js | 326 |
13 files changed, 60 insertions, 13621 deletions
diff --git a/deluge/ui/web/js/deluge-all-debug.js b/deluge/ui/web/js/deluge-all-debug.js deleted file mode 100644 index 67bb83a..0000000 --- a/deluge/ui/web/js/deluge-all-debug.js +++ /dev/null @@ -1,9969 +0,0 @@ -/** - * Deluge.add.Window.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. - */ -Ext.ns('Deluge.add'); - -/** - * @class Deluge.add.Window - * @extends Ext.Window - * Base class for an add Window - */ -Deluge.add.Window = Ext.extend(Ext.Window, { - initComponent: function () { - Deluge.add.Window.superclass.initComponent.call(this); - this.addEvents('beforeadd', 'add', 'addfailed'); - }, - - /** - * Create an id for the torrent before we have any info about it. - */ - createTorrentId: function () { - return new Date().getTime().toString(); - }, -}); -/** - * Deluge.add.AddWindow.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. - */ - -Ext.namespace('Deluge.add'); - -// This override allows file upload buttons to contain icons -Ext.override(Ext.ux.form.FileUploadField, { - onRender: function (ct, position) { - Ext.ux.form.FileUploadField.superclass.onRender.call( - this, - ct, - position - ); - - this.wrap = this.el.wrap({ cls: 'x-form-field-wrap x-form-file-wrap' }); - this.el.addClass('x-form-file-text'); - this.el.dom.removeAttribute('name'); - this.createFileInput(); - - var btnCfg = Ext.applyIf(this.buttonCfg || {}, { - text: this.buttonText, - }); - this.button = new Ext.Button( - Ext.apply(btnCfg, { - renderTo: this.wrap, - cls: - 'x-form-file-btn' + - (btnCfg.iconCls ? ' x-btn-text-icon' : ''), - }) - ); - - if (this.buttonOnly) { - this.el.hide(); - this.wrap.setWidth(this.button.getEl().getWidth()); - } - - this.bindListeners(); - this.resizeEl = this.positionEl = this.wrap; - }, -}); - -Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, { - title: _('Add Torrents'), - layout: 'border', - width: 470, - height: 450, - bodyStyle: 'padding: 10px 5px;', - buttonAlign: 'right', - closeAction: 'hide', - closable: true, - plain: true, - iconCls: 'x-deluge-add-window-icon', - - initComponent: function () { - Deluge.add.AddWindow.superclass.initComponent.call(this); - - this.addButton(_('Cancel'), this.onCancelClick, this); - this.addButton(_('Add'), this.onAddClick, this); - - this.list = new Ext.list.ListView({ - store: new Ext.data.SimpleStore({ - fields: [ - { name: 'info_hash', mapping: 1 }, - { name: 'text', mapping: 2 }, - ], - id: 0, - }), - columns: [ - { - id: 'torrent', - width: 150, - sortable: true, - dataIndex: 'text', - tpl: new Ext.XTemplate( - '<div class="x-deluge-add-torrent-name">{text:htmlEncode}</div>' - ), - }, - ], - stripeRows: true, - singleSelect: true, - listeners: { - selectionchange: { - fn: this.onSelect, - scope: this, - }, - }, - hideHeaders: true, - autoExpandColumn: 'torrent', - height: '100%', - autoScroll: true, - }); - - this.add({ - region: 'center', - items: [this.list], - border: false, - bbar: new Ext.Toolbar({ - items: [ - { - id: 'fileUploadForm', - xtype: 'form', - layout: 'fit', - baseCls: 'x-plain', - fileUpload: true, - items: [ - { - buttonOnly: true, - xtype: 'fileuploadfield', - id: 'torrentFile', - name: 'file', - multiple: true, - buttonCfg: { - iconCls: 'x-deluge-add-file', - text: _('File'), - }, - listeners: { - scope: this, - fileselected: this.onFileSelected, - }, - }, - ], - }, - { - text: _('Url'), - iconCls: 'icon-add-url', - handler: this.onUrl, - scope: this, - }, - { - text: _('Infohash'), - iconCls: 'icon-magnet-add', - hidden: true, - disabled: true, - }, - '->', - { - text: _('Remove'), - iconCls: 'icon-remove', - handler: this.onRemove, - scope: this, - }, - ], - }), - }); - - this.fileUploadForm = Ext.getCmp('fileUploadForm').getForm(); - this.optionsPanel = this.add(new Deluge.add.OptionsPanel()); - this.on('hide', this.onHide, this); - this.on('show', this.onShow, this); - }, - - clear: function () { - this.list.getStore().removeAll(); - this.optionsPanel.clear(); - // Reset upload form so handler fires when a canceled file is reselected - this.fileUploadForm.reset(); - }, - - onAddClick: function () { - var torrents = []; - if (!this.list) return; - this.list.getStore().each(function (r) { - var id = r.get('info_hash'); - torrents.push({ - path: this.optionsPanel.getFilename(id), - options: this.optionsPanel.getOptions(id), - }); - }, this); - - deluge.client.web.add_torrents(torrents, { - success: function (result) {}, - }); - this.clear(); - this.hide(); - }, - - onCancelClick: function () { - this.clear(); - this.hide(); - }, - - onFile: function () { - if (!this.file) this.file = new Deluge.add.FileWindow(); - this.file.show(); - }, - - onHide: function () { - this.optionsPanel.setActiveTab(0); - this.optionsPanel.files.setDisabled(true); - this.optionsPanel.form.setDisabled(true); - }, - - onRemove: function () { - if (!this.list.getSelectionCount()) return; - var torrent = this.list.getSelectedRecords()[0]; - if (!torrent) return; - this.list.getStore().remove(torrent); - this.optionsPanel.clear(); - - if (this.torrents && this.torrents[torrent.id]) - delete this.torrents[torrent.id]; - }, - - onSelect: function (list, selections) { - if (selections.length) { - var record = this.list.getRecord(selections[0]); - this.optionsPanel.setTorrent(record.get('info_hash')); - } else { - this.optionsPanel.files.setDisabled(true); - this.optionsPanel.form.setDisabled(true); - } - }, - - onShow: function () { - if (!this.url) { - this.url = new Deluge.add.UrlWindow(); - this.url.on('beforeadd', this.onTorrentBeforeAdd, this); - this.url.on('add', this.onTorrentAdd, this); - this.url.on('addfailed', this.onTorrentAddFailed, this); - } - - this.optionsPanel.form.getDefaults(); - }, - - onFileSelected: function () { - if (this.fileUploadForm.isValid()) { - var torrentIds = []; - var files = this.fileUploadForm.findField('torrentFile').value; - var randomId = this.createTorrentId(); - Array.prototype.forEach.call( - files, - function (file, i) { - // Append index for batch of unique torrentIds. - var torrentId = randomId + i.toString(); - torrentIds.push(torrentId); - this.onTorrentBeforeAdd(torrentId, file.name); - }.bind(this) - ); - this.fileUploadForm.submit({ - url: deluge.config.base + 'upload', - waitMsg: _('Uploading your torrent...'), - success: this.onUploadSuccess, - failure: this.onUploadFailure, - scope: this, - torrentIds: torrentIds, - }); - } - }, - - onUploadSuccess: function (fp, upload) { - if (!upload.result.success) { - this.clear(); - return; - } - - upload.result.files.forEach( - function (filename, i) { - deluge.client.web.get_torrent_info(filename, { - success: this.onGotInfo, - scope: this, - filename: filename, - torrentId: upload.options.torrentIds[i], - }); - }.bind(this) - ); - this.fileUploadForm.reset(); - }, - - onUploadFailure: function (form, action) { - this.hide(); - Ext.MessageBox.show({ - title: _('Error'), - msg: _('Failed to upload torrent'), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - this.fireEvent('addfailed', this.torrentId); - }, - - onGotInfo: function (info, obj, response, request) { - info.filename = request.options.filename; - torrentId = request.options.torrentId; - this.onTorrentAdd(torrentId, info); - }, - - onTorrentBeforeAdd: function (torrentId, text) { - var store = this.list.getStore(); - store.loadData([[torrentId, null, text]], true); - }, - - onTorrentAdd: function (torrentId, info) { - var r = this.list.getStore().getById(torrentId); - if (!info) { - Ext.MessageBox.show({ - title: _('Error'), - msg: _('Not a valid torrent'), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - this.list.getStore().remove(r); - } else { - r.set('info_hash', info['info_hash']); - r.set('text', info['name']); - this.list.getStore().commitChanges(); - this.optionsPanel.addTorrent(info); - this.list.select(r); - } - }, - - onTorrentAddFailed: function (torrentId) { - var store = this.list.getStore(); - var torrentRecord = store.getById(torrentId); - if (torrentRecord) { - store.remove(torrentRecord); - } - }, - - onUrl: function (button, event) { - this.url.show(); - }, -}); -/** - * Deluge.add.FilesTab.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. - */ -Ext.ns('Deluge.add'); - -/** - * @class Deluge.add.FilesTab - * @extends Ext.ux.tree.TreeGrid - */ -Deluge.add.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { - layout: 'fit', - title: _('Files'), - - autoScroll: false, - animate: false, - border: false, - disabled: true, - rootVisible: false, - - columns: [ - { - header: _('Filename'), - width: 295, - dataIndex: 'filename', - tpl: new Ext.XTemplate('{filename:htmlEncode}'), - }, - { - header: _('Size'), - width: 60, - dataIndex: 'size', - tpl: new Ext.XTemplate('{size:this.fsize}', { - fsize: function (v) { - return fsize(v); - }, - }), - }, - { - header: _('Download'), - width: 65, - dataIndex: 'download', - tpl: new Ext.XTemplate('{download:this.format}', { - format: function (v) { - return ( - '<div rel="chkbox" class="x-grid3-check-col' + - (v ? '-on' : '') + - '"> </div>' - ); - }, - }), - }, - ], - - initComponent: function () { - Deluge.add.FilesTab.superclass.initComponent.call(this); - this.on('click', this.onNodeClick, this); - }, - - clearFiles: function () { - var root = this.getRootNode(); - if (!root.hasChildNodes()) return; - root.cascade(function (node) { - if (!node.parentNode || !node.getOwnerTree()) return; - node.remove(); - }); - }, - - setDownload: function (node, value, suppress) { - node.attributes.download = value; - node.ui.updateColumns(); - - if (node.isLeaf()) { - if (!suppress) { - return this.fireEvent('fileschecked', [node], value, !value); - } - } else { - var nodes = [node]; - node.cascade(function (n) { - n.attributes.download = value; - n.ui.updateColumns(); - nodes.push(n); - }, this); - if (!suppress) { - return this.fireEvent('fileschecked', nodes, value, !value); - } - } - }, - - onNodeClick: function (node, e) { - var el = new Ext.Element(e.target); - if (el.getAttribute('rel') == 'chkbox') { - this.setDownload(node, !node.attributes.download); - } - }, -}); -/** - * Deluge.add.Infohash.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. - */ -Ext.namespace('Ext.deluge.add'); -/** - * Deluge.add.OptionsPanel.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. - */ -Ext.ns('Deluge.add'); - -Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, { - torrents: {}, - - // layout options - region: 'south', - border: false, - activeTab: 0, - height: 265, - - initComponent: function () { - Deluge.add.OptionsPanel.superclass.initComponent.call(this); - this.files = this.add(new Deluge.add.FilesTab()); - this.form = this.add(new Deluge.add.OptionsTab()); - - this.files.on('fileschecked', this.onFilesChecked, this); - }, - - addTorrent: function (torrent) { - this.torrents[torrent['info_hash']] = torrent; - var fileIndexes = {}; - this.walkFileTree( - torrent['files_tree'], - function (filename, type, entry, parent) { - if (type != 'file') return; - fileIndexes[entry.index] = entry.download; - }, - this - ); - - var priorities = []; - Ext.each(Ext.keys(fileIndexes), function (index) { - priorities[index] = fileIndexes[index]; - }); - - var oldId = this.form.optionsManager.changeId( - torrent['info_hash'], - true - ); - this.form.optionsManager.setDefault('file_priorities', priorities); - this.form.optionsManager.changeId(oldId, true); - }, - - clear: function () { - this.files.clearFiles(); - this.form.optionsManager.resetAll(); - }, - - getFilename: function (torrentId) { - return this.torrents[torrentId]['filename']; - }, - - getOptions: function (torrentId) { - var oldId = this.form.optionsManager.changeId(torrentId, true); - var options = this.form.optionsManager.get(); - this.form.optionsManager.changeId(oldId, true); - Ext.each(options['file_priorities'], function (priority, index) { - options['file_priorities'][index] = priority ? 1 : 0; - }); - return options; - }, - - setTorrent: function (torrentId) { - if (!torrentId) return; - - this.torrentId = torrentId; - this.form.optionsManager.changeId(torrentId); - - this.files.clearFiles(); - var root = this.files.getRootNode(); - var priorities = this.form.optionsManager.get('file_priorities'); - - this.form.setDisabled(false); - - if (this.torrents[torrentId]['files_tree']) { - this.walkFileTree( - this.torrents[torrentId]['files_tree'], - function (filename, type, entry, parentNode) { - var node = new Ext.tree.TreeNode({ - download: entry.index ? priorities[entry.index] : true, - filename: filename, - fileindex: entry.index, - leaf: type != 'dir', - size: entry.length, - }); - parentNode.appendChild(node); - if (type == 'dir') return node; - }, - this, - root - ); - root.firstChild.expand(); - this.files.setDisabled(false); - this.files.show(); - } else { - // Files tab is empty so show options tab - this.form.show(); - this.files.setDisabled(true); - } - }, - - walkFileTree: function (files, callback, scope, parentNode) { - for (var filename in files.contents) { - var entry = files.contents[filename]; - var type = entry.type; - - if (scope) { - var ret = callback.apply(scope, [ - filename, - type, - entry, - parentNode, - ]); - } else { - var ret = callback(filename, type, entry, parentNode); - } - - if (type == 'dir') this.walkFileTree(entry, callback, scope, ret); - } - }, - - onFilesChecked: function (nodes, newValue, oldValue) { - Ext.each( - nodes, - function (node) { - if (node.attributes.fileindex < 0) return; - var priorities = - this.form.optionsManager.get('file_priorities'); - priorities[node.attributes.fileindex] = newValue; - this.form.optionsManager.update('file_priorities', priorities); - }, - this - ); - }, -}); -/** - * Deluge.add.OptionsPanel.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. - */ -Ext.ns('Deluge.add'); - -/** - * @class Deluge.add.OptionsTab - * @extends Ext.form.FormPanel - */ -Deluge.add.OptionsTab = Ext.extend(Ext.form.FormPanel, { - title: _('Options'), - height: 170, - border: false, - bodyStyle: 'padding: 5px', - disabled: true, - labelWidth: 1, - - initComponent: function () { - Deluge.add.OptionsTab.superclass.initComponent.call(this); - - this.optionsManager = new Deluge.MultiOptionsManager(); - - var fieldset = this.add({ - xtype: 'fieldset', - title: _('Download Folder'), - border: false, - autoHeight: true, - defaultType: 'textfield', - labelWidth: 1, - fieldLabel: '', - style: 'padding: 5px 0; margin-bottom: 0;', - }); - this.optionsManager.bind( - 'download_location', - fieldset.add({ - fieldLabel: '', - name: 'download_location', - anchor: '95%', - labelSeparator: '', - }) - ); - var fieldset = this.add({ - xtype: 'fieldset', - title: _('Move Completed Folder'), - border: false, - autoHeight: true, - defaultType: 'togglefield', - labelWidth: 1, - fieldLabel: '', - style: 'padding: 5px 0; margin-bottom: 0;', - }); - var field = fieldset.add({ - fieldLabel: '', - name: 'move_completed_path', - anchor: '98%', - }); - this.optionsManager.bind('move_completed', field.toggle); - this.optionsManager.bind('move_completed_path', field.input); - - var panel = this.add({ - border: false, - layout: 'column', - defaultType: 'fieldset', - }); - - fieldset = panel.add({ - title: _('Bandwidth'), - border: false, - autoHeight: true, - bodyStyle: 'padding: 2px 5px', - labelWidth: 105, - width: 200, - defaultType: 'spinnerfield', - style: 'padding-right: 10px;', - }); - this.optionsManager.bind( - 'max_download_speed', - fieldset.add({ - fieldLabel: _('Max Down Speed'), - name: 'max_download_speed', - width: 60, - }) - ); - this.optionsManager.bind( - 'max_upload_speed', - fieldset.add({ - fieldLabel: _('Max Up Speed'), - name: 'max_upload_speed', - width: 60, - }) - ); - this.optionsManager.bind( - 'max_connections', - fieldset.add({ - fieldLabel: _('Max Connections'), - name: 'max_connections', - width: 60, - }) - ); - this.optionsManager.bind( - 'max_upload_slots', - fieldset.add({ - fieldLabel: _('Max Upload Slots'), - name: 'max_upload_slots', - width: 60, - }) - ); - - fieldset = panel.add({ - // title: _('General'), - border: false, - autoHeight: true, - defaultType: 'checkbox', - }); - this.optionsManager.bind( - 'add_paused', - fieldset.add({ - name: 'add_paused', - boxLabel: _('Add In Paused State'), - fieldLabel: '', - labelSeparator: '', - }) - ); - this.optionsManager.bind( - 'prioritize_first_last_pieces', - fieldset.add({ - name: 'prioritize_first_last_pieces', - boxLabel: _('Prioritize First/Last Pieces'), - fieldLabel: '', - labelSeparator: '', - }) - ); - this.optionsManager.bind( - 'sequential_download', - fieldset.add({ - name: 'sequential_download', - boxLabel: _('Sequential Download'), - fieldLabel: '', - labelSeparator: '', - }) - ); - this.optionsManager.bind( - 'seed_mode', - fieldset.add({ - name: 'seed_mode', - boxLabel: _('Skip File Hash Check'), - fieldLabel: '', - labelSeparator: '', - }) - ); - this.optionsManager.bind( - 'super_seeding', - fieldset.add({ - name: 'super_seeding', - boxLabel: _('Super Seed'), - fieldLabel: '', - labelSeparator: '', - }) - ); - this.optionsManager.bind( - 'pre_allocate_storage', - fieldset.add({ - name: 'pre_allocate_storage', - boxLabel: _('Preallocate Disk Space'), - fieldLabel: '', - labelSeparator: '', - }) - ); - }, - - getDefaults: function () { - var keys = [ - 'add_paused', - 'pre_allocate_storage', - 'download_location', - 'max_connections_per_torrent', - 'max_download_speed_per_torrent', - 'move_completed', - 'move_completed_path', - 'max_upload_slots_per_torrent', - 'max_upload_speed_per_torrent', - 'prioritize_first_last_pieces', - 'sequential_download', - ]; - - deluge.client.core.get_config_values(keys, { - success: function (config) { - var options = { - file_priorities: [], - add_paused: config.add_paused, - sequential_download: config.sequential_download, - pre_allocate_storage: config.pre_allocate_storage, - download_location: config.download_location, - move_completed: config.move_completed, - move_completed_path: config.move_completed_path, - max_connections: config.max_connections_per_torrent, - max_download_speed: config.max_download_speed_per_torrent, - max_upload_slots: config.max_upload_slots_per_torrent, - max_upload_speed: config.max_upload_speed_per_torrent, - prioritize_first_last_pieces: - config.prioritize_first_last_pieces, - seed_mode: false, - super_seeding: false, - }; - this.optionsManager.options = options; - this.optionsManager.resetAll(); - }, - scope: this, - }); - }, -}); -/** - * Deluge.add.UrlWindow.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. - */ - -Ext.namespace('Deluge.add'); -Deluge.add.UrlWindow = Ext.extend(Deluge.add.Window, { - title: _('Add from Url'), - modal: true, - plain: true, - layout: 'fit', - width: 350, - height: 155, - - buttonAlign: 'center', - closeAction: 'hide', - bodyStyle: 'padding: 10px 5px;', - iconCls: 'x-deluge-add-url-window-icon', - - initComponent: function () { - Deluge.add.UrlWindow.superclass.initComponent.call(this); - this.addButton(_('Add'), this.onAddClick, this); - - var form = this.add({ - xtype: 'form', - defaultType: 'textfield', - baseCls: 'x-plain', - labelWidth: 55, - }); - - this.urlField = form.add({ - fieldLabel: _('Url'), - id: 'url', - name: 'url', - width: '97%', - }); - this.urlField.on('specialkey', this.onAdd, this); - - this.cookieField = form.add({ - fieldLabel: _('Cookies'), - id: 'cookies', - name: 'cookies', - width: '97%', - }); - this.cookieField.on('specialkey', this.onAdd, this); - }, - - onAddClick: function (field, e) { - if ( - (field.id == 'url' || field.id == 'cookies') && - e.getKey() != e.ENTER - ) - return; - - var field = this.urlField; - var url = field.getValue(); - var cookies = this.cookieField.getValue(); - var torrentId = this.createTorrentId(); - - if (url.indexOf('magnet:?') == 0 && url.indexOf('xt=urn:btih') > -1) { - deluge.client.web.get_magnet_info(url, { - success: this.onGotInfo, - scope: this, - filename: url, - torrentId: torrentId, - }); - } else { - deluge.client.web.download_torrent_from_url(url, cookies, { - success: this.onDownload, - failure: this.onDownloadFailed, - scope: this, - torrentId: torrentId, - }); - } - - this.hide(); - this.urlField.setValue(''); - this.fireEvent('beforeadd', torrentId, url); - }, - - onDownload: function (filename, obj, resp, req) { - deluge.client.web.get_torrent_info(filename, { - success: this.onGotInfo, - failure: this.onDownloadFailed, - scope: this, - filename: filename, - torrentId: req.options.torrentId, - }); - }, - - onDownloadFailed: function (obj, resp, req) { - Ext.MessageBox.show({ - title: _('Error'), - msg: _('Failed to download torrent'), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - this.fireEvent('addfailed', req.options.torrentId); - }, - - onGotInfo: function (info, obj, response, request) { - info['filename'] = request.options.filename; - this.fireEvent('add', request.options.torrentId, info); - }, -}); -/** - * Deluge.data.SortTypes.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. - */ -Ext.namespace('Deluge.data'); - -/** - * Common sort functions that can be used for data Stores. - * - * @author Damien Churchill <damoxc@gmail.com> - * @version 1.3 - * - * @class Deluge.data.SortTypes - * @singleton - */ -Deluge.data.SortTypes = { - // prettier-ignore - asIPAddress: function(value) { - var d = value.match( - /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\:(\d+)/ - ); - return ((+d[1] * 256 + (+d[2])) * 256 + (+d[3])) * 256 + (+d[4]); - }, - - asQueuePosition: function (value) { - return value > -1 ? value : Number.MAX_VALUE; - }, - - asName: function (value) { - return String(value).toLowerCase(); - }, -}; -/** - * Deluge.data.PeerRecord.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. - */ -Ext.namespace('Deluge.data'); - -/** - * Deluge.data.Peer record - * - * @author Damien Churchill <damoxc@gmail.com> - * @version 1.3 - * - * @class Deluge.data.Peer - * @extends Ext.data.Record - * @constructor - * @param {Object} data The peer data - */ -Deluge.data.Peer = Ext.data.Record.create([ - { - name: 'country', - type: 'string', - }, - { - name: 'ip', - type: 'string', - sortType: Deluge.data.SortTypes.asIPAddress, - }, - { - name: 'client', - type: 'string', - }, - { - name: 'progress', - type: 'float', - }, - { - name: 'down_speed', - type: 'int', - }, - { - name: 'up_speed', - type: 'int', - }, - { - name: 'seed', - type: 'int', - }, -]); -/** - * Deluge.data.TorrentRecord.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. - */ -Ext.namespace('Deluge.data'); - -/** - * Deluge.data.Torrent record - * - * @author Damien Churchill <damoxc@gmail.com> - * @version 1.3 - * - * @class Deluge.data.Torrent - * @extends Ext.data.Record - * @constructor - * @param {Object} data The torrents data - */ -Deluge.data.Torrent = Ext.data.Record.create([ - { - name: 'queue', - type: 'int', - }, - { - name: 'name', - type: 'string', - sortType: Deluge.data.SortTypes.asName, - }, - { - name: 'total_wanted', - type: 'int', - }, - { - name: 'state', - type: 'string', - }, - { - name: 'progress', - type: 'int', - }, - { - 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', - }, - { - name: 'ratio', - type: 'float', - }, - { - name: 'distributed_copies', - type: 'float', - }, - { - name: 'time_added', - type: 'int', - }, - { - name: 'tracker_host', - type: 'string', - }, - { - name: 'save_path', - type: 'string', - }, - { - 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', - }, -]); -/** - * Deluge.details.DetailsPanel.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. - */ -Ext.namespace('Deluge.details'); - -/** - * @class Deluge.details.DetailsPanel - */ -Deluge.details.DetailsPanel = Ext.extend(Ext.TabPanel, { - id: 'torrentDetails', - activeTab: 0, - - initComponent: function () { - Deluge.details.DetailsPanel.superclass.initComponent.call(this); - this.add(new Deluge.details.StatusTab()); - this.add(new Deluge.details.DetailsTab()); - this.add(new Deluge.details.FilesTab()); - this.add(new Deluge.details.PeersTab()); - this.add(new Deluge.details.OptionsTab()); - }, - - clear: function () { - this.items.each(function (panel) { - if (panel.clear) { - panel.clear.defer(100, panel); - panel.disable(); - } - }); - }, - - update: function (tab) { - var torrent = deluge.torrents.getSelected(); - if (!torrent) { - this.clear(); - return; - } - - this.items.each(function (tab) { - if (tab.disabled) tab.enable(); - }); - - tab = tab || this.getActiveTab(); - if (tab.update) tab.update(torrent.id); - }, - - /* Event Handlers */ - - // We need to add the events in onRender since Deluge.Torrents has not been created yet. - onRender: function (ct, position) { - Deluge.details.DetailsPanel.superclass.onRender.call( - this, - ct, - position - ); - deluge.events.on('disconnect', this.clear, this); - deluge.torrents.on('rowclick', this.onTorrentsClick, this); - this.on('tabchange', this.onTabChange, this); - - deluge.torrents.getSelectionModel().on( - 'selectionchange', - function (selModel) { - if (!selModel.hasSelection()) this.clear(); - }, - this - ); - }, - - onTabChange: function (panel, tab) { - this.update(tab); - }, - - onTorrentsClick: function (grid, rowIndex, e) { - this.update(); - }, -}); -/** - * Deluge.Details.Details.js - * The details tab displayed in the details panel. - * - * 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. - */ - -Deluge.details.DetailsTab = Ext.extend(Ext.Panel, { - title: _('Details'), - - fields: {}, - autoScroll: true, - queuedItems: {}, - - oldData: {}, - - initComponent: function () { - Deluge.details.DetailsTab.superclass.initComponent.call(this); - this.addItem('torrent_name', _('Name:')); - this.addItem('hash', _('Hash:')); - this.addItem('path', _('Download Folder:')); - this.addItem('size', _('Total Size:')); - this.addItem('files', _('Total Files:')); - this.addItem('comment', _('Comment:')); - this.addItem('status', _('Status:')); - this.addItem('tracker', _('Tracker:')); - this.addItem('creator', _('Created By:')); - }, - - onRender: function (ct, position) { - Deluge.details.DetailsTab.superclass.onRender.call(this, ct, position); - this.body.setStyle('padding', '10px'); - this.dl = Ext.DomHelper.append(this.body, { tag: 'dl' }, true); - - for (var id in this.queuedItems) { - this.doAddItem(id, this.queuedItems[id]); - } - }, - - addItem: function (id, label) { - if (!this.rendered) { - this.queuedItems[id] = label; - } else { - this.doAddItem(id, label); - } - }, - - // private - doAddItem: function (id, label) { - Ext.DomHelper.append(this.dl, { tag: 'dt', cls: id, html: label }); - this.fields[id] = Ext.DomHelper.append( - this.dl, - { tag: 'dd', cls: id, html: '' }, - true - ); - }, - - clear: function () { - if (!this.fields) return; - for (var k in this.fields) { - this.fields[k].dom.innerHTML = ''; - } - this.oldData = {}; - }, - - update: function (torrentId) { - deluge.client.web.get_torrent_status(torrentId, Deluge.Keys.Details, { - success: this.onRequestComplete, - scope: this, - torrentId: torrentId, - }); - }, - - onRequestComplete: function (torrent, request, response, options) { - var data = { - torrent_name: torrent.name, - hash: options.options.torrentId, - path: torrent.download_location, - size: fsize(torrent.total_size), - files: torrent.num_files, - status: torrent.message, - tracker: torrent.tracker_host, - comment: torrent.comment, - creator: torrent.creator, - }; - - for (var field in this.fields) { - if (!Ext.isDefined(data[field])) continue; // This is a field we are not responsible for. - if (data[field] == this.oldData[field]) continue; - this.fields[field].dom.innerHTML = Ext.util.Format.htmlEncode( - data[field] - ); - } - this.oldData = data; - }, -}); -/** - * Deluge.details.FilesTab.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. - */ - -Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { - title: _('Files'), - - rootVisible: false, - - columns: [ - { - header: _('Filename'), - width: 330, - dataIndex: 'filename', - tpl: new Ext.XTemplate('{filename:htmlEncode}'), - }, - { - header: _('Size'), - width: 150, - dataIndex: 'size', - tpl: new Ext.XTemplate('{size:this.fsize}', { - fsize: function (v) { - return fsize(v); - }, - }), - }, - { - xtype: 'tgrendercolumn', - header: _('Progress'), - width: 150, - dataIndex: 'progress', - renderer: function (v) { - var progress = v * 100; - return Deluge.progressBar( - progress, - this.col.width, - progress.toFixed(2) + '%', - 0 - ); - }, - }, - { - header: _('Priority'), - width: 150, - dataIndex: 'priority', - tpl: new Ext.XTemplate( - '<tpl if="!isNaN(priority)">' + - '<div class="{priority:this.getClass}">' + - '{priority:this.getName}' + - '</div></tpl>', - { - getClass: function (v) { - return FILE_PRIORITY_CSS[v]; - }, - - getName: function (v) { - return _(FILE_PRIORITY[v]); - }, - } - ), - }, - ], - - selModel: new Ext.tree.MultiSelectionModel(), - - initComponent: function () { - Deluge.details.FilesTab.superclass.initComponent.call(this); - this.setRootNode(new Ext.tree.TreeNode({ text: _('Files') })); - }, - - clear: function () { - var root = this.getRootNode(); - if (!root.hasChildNodes()) return; - root.cascade(function (node) { - var parentNode = node.parentNode; - if (!parentNode) return; - if (!parentNode.ownerTree) return; - parentNode.removeChild(node); - }); - }, - - createFileTree: function (files) { - function walk(files, parentNode) { - for (var file in files.contents) { - var item = files.contents[file]; - if (item.type == 'dir') { - walk( - item, - parentNode.appendChild( - new Ext.tree.TreeNode({ - text: file, - filename: file, - size: item.size, - progress: item.progress, - priority: item.priority, - }) - ) - ); - } else { - parentNode.appendChild( - new Ext.tree.TreeNode({ - text: file, - filename: file, - fileIndex: item.index, - size: item.size, - progress: item.progress, - priority: item.priority, - leaf: true, - iconCls: 'x-deluge-file', - uiProvider: Ext.ux.tree.TreeGridNodeUI, - }) - ); - } - } - } - var root = this.getRootNode(); - walk(files, root); - root.firstChild.expand(); - }, - - update: function (torrentId) { - if (this.torrentId != torrentId) { - this.clear(); - this.torrentId = torrentId; - } - - deluge.client.web.get_torrent_files(torrentId, { - success: this.onRequestComplete, - scope: this, - torrentId: torrentId, - }); - }, - - updateFileTree: function (files) { - function walk(files, parentNode) { - for (var file in files.contents) { - var item = files.contents[file]; - var node = parentNode.findChild('filename', file); - node.attributes.size = item.size; - node.attributes.progress = item.progress; - node.attributes.priority = item.priority; - node.ui.updateColumns(); - if (item.type == 'dir') { - walk(item, node); - } - } - } - walk(files, this.getRootNode()); - }, - - onRender: function (ct, position) { - Deluge.details.FilesTab.superclass.onRender.call(this, ct, position); - deluge.menus.filePriorities.on('itemclick', this.onItemClick, this); - this.on('contextmenu', this.onContextMenu, this); - this.sorter = new Ext.tree.TreeSorter(this, { - folderSort: true, - }); - }, - - onContextMenu: function (node, e) { - e.stopEvent(); - var selModel = this.getSelectionModel(); - if (selModel.getSelectedNodes().length < 2) { - selModel.clearSelections(); - node.select(); - } - deluge.menus.filePriorities.showAt(e.getPoint()); - }, - - onItemClick: function (baseItem, e) { - switch (baseItem.id) { - case 'expandAll': - this.expandAll(); - break; - default: - var indexes = {}; - var walk = function (node) { - if (Ext.isEmpty(node.attributes.fileIndex)) return; - indexes[node.attributes.fileIndex] = - node.attributes.priority; - }; - this.getRootNode().cascade(walk); - - var nodes = this.getSelectionModel().getSelectedNodes(); - Ext.each(nodes, function (node) { - if (!node.isLeaf()) { - var setPriorities = function (node) { - if (Ext.isEmpty(node.attributes.fileIndex)) return; - indexes[node.attributes.fileIndex] = - baseItem.filePriority; - }; - node.cascade(setPriorities); - } else if (!Ext.isEmpty(node.attributes.fileIndex)) { - indexes[node.attributes.fileIndex] = - baseItem.filePriority; - return; - } - }); - - var priorities = new Array(Ext.keys(indexes).length); - for (var index in indexes) { - priorities[index] = indexes[index]; - } - - deluge.client.core.set_torrent_options( - [this.torrentId], - { file_priorities: priorities }, - { - success: function () { - Ext.each(nodes, function (node) { - node.setColumnValue(3, baseItem.filePriority); - }); - }, - scope: this, - } - ); - break; - } - }, - - onRequestComplete: function (files, options) { - if (!this.getRootNode().hasChildNodes()) { - this.createFileTree(files); - } else { - this.updateFileTree(files); - } - }, -}); -/** - * Deluge.details.OptionsTab.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. - */ - -Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, { - constructor: function (config) { - config = Ext.apply( - { - autoScroll: true, - bodyStyle: 'padding: 5px;', - border: false, - cls: 'x-deluge-options', - defaults: { - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }, - deferredRender: false, - layout: 'column', - title: _('Options'), - }, - config - ); - Deluge.details.OptionsTab.superclass.constructor.call(this, config); - }, - - initComponent: function () { - Deluge.details.OptionsTab.superclass.initComponent.call(this); - - (this.fieldsets = {}), (this.fields = {}); - this.optionsManager = new Deluge.MultiOptionsManager({ - options: { - max_download_speed: -1, - max_upload_speed: -1, - max_connections: -1, - max_upload_slots: -1, - auto_managed: false, - stop_at_ratio: false, - stop_ratio: 2.0, - remove_at_ratio: false, - move_completed: false, - move_completed_path: '', - private: false, - prioritize_first_last: false, - super_seeding: false, - }, - }); - - /* - * Bandwidth Options - */ - this.fieldsets.bandwidth = this.add({ - xtype: 'fieldset', - defaultType: 'spinnerfield', - bodyStyle: 'padding: 5px', - - layout: 'table', - layoutConfig: { columns: 3 }, - labelWidth: 150, - - style: 'margin-left: 10px; margin-right: 5px; padding: 5px', - title: _('Bandwidth'), - width: 250, - }); - - /* - * Max Download Speed - */ - this.fieldsets.bandwidth.add({ - xtype: 'label', - text: _('Max Download Speed:'), - forId: 'max_download_speed', - cls: 'x-deluge-options-label', - }); - this.fields.max_download_speed = this.fieldsets.bandwidth.add({ - id: 'max_download_speed', - name: 'max_download_speed', - width: 70, - strategy: { - xtype: 'number', - decimalPrecision: 1, - minValue: -1, - maxValue: 99999, - }, - }); - this.fieldsets.bandwidth.add({ - xtype: 'label', - text: _('KiB/s'), - style: 'margin-left: 10px', - }); - - /* - * Max Upload Speed - */ - this.fieldsets.bandwidth.add({ - xtype: 'label', - text: _('Max Upload Speed:'), - forId: 'max_upload_speed', - cls: 'x-deluge-options-label', - }); - this.fields.max_upload_speed = this.fieldsets.bandwidth.add({ - id: 'max_upload_speed', - name: 'max_upload_speed', - width: 70, - value: -1, - strategy: { - xtype: 'number', - decimalPrecision: 1, - minValue: -1, - maxValue: 99999, - }, - }); - this.fieldsets.bandwidth.add({ - xtype: 'label', - text: _('KiB/s'), - style: 'margin-left: 10px', - }); - - /* - * Max Connections - */ - this.fieldsets.bandwidth.add({ - xtype: 'label', - text: _('Max Connections:'), - forId: 'max_connections', - cls: 'x-deluge-options-label', - }); - this.fields.max_connections = this.fieldsets.bandwidth.add({ - id: 'max_connections', - name: 'max_connections', - width: 70, - value: -1, - strategy: { - xtype: 'number', - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }, - colspan: 2, - }); - - /* - * Max Upload Slots - */ - this.fieldsets.bandwidth.add({ - xtype: 'label', - text: _('Max Upload Slots:'), - forId: 'max_upload_slots', - cls: 'x-deluge-options-label', - }); - this.fields.max_upload_slots = this.fieldsets.bandwidth.add({ - id: 'max_upload_slots', - name: 'max_upload_slots', - width: 70, - value: -1, - strategy: { - xtype: 'number', - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }, - colspan: 2, - }); - - /* - * Queue Options - */ - this.fieldsets.queue = this.add({ - xtype: 'fieldset', - title: _('Queue'), - style: 'margin-left: 5px; margin-right: 5px; padding: 5px', - width: 210, - - layout: 'table', - layoutConfig: { columns: 2 }, - labelWidth: 0, - - defaults: { - fieldLabel: '', - labelSeparator: '', - }, - }); - - this.fields.auto_managed = this.fieldsets.queue.add({ - xtype: 'checkbox', - fieldLabel: '', - labelSeparator: '', - name: 'is_auto_managed', - boxLabel: _('Auto Managed'), - width: 200, - colspan: 2, - }); - - this.fields.stop_at_ratio = this.fieldsets.queue.add({ - fieldLabel: '', - labelSeparator: '', - id: 'stop_at_ratio', - width: 120, - boxLabel: _('Stop seed at ratio:'), - handler: this.onStopRatioChecked, - scope: this, - }); - - this.fields.stop_ratio = this.fieldsets.queue.add({ - xtype: 'spinnerfield', - id: 'stop_ratio', - name: 'stop_ratio', - disabled: true, - width: 50, - value: 2.0, - strategy: { - xtype: 'number', - minValue: -1, - maxValue: 99999, - incrementValue: 0.1, - alternateIncrementValue: 1, - decimalPrecision: 1, - }, - }); - - this.fields.remove_at_ratio = this.fieldsets.queue.add({ - fieldLabel: '', - labelSeparator: '', - id: 'remove_at_ratio', - ctCls: 'x-deluge-indent-checkbox', - bodyStyle: 'padding-left: 10px', - boxLabel: _('Remove at ratio'), - disabled: true, - colspan: 2, - }); - - this.fields.move_completed = this.fieldsets.queue.add({ - fieldLabel: '', - labelSeparator: '', - id: 'move_completed', - boxLabel: _('Move Completed:'), - colspan: 2, - handler: this.onMoveCompletedChecked, - scope: this, - }); - - this.fields.move_completed_path = this.fieldsets.queue.add({ - xtype: 'textfield', - fieldLabel: '', - id: 'move_completed_path', - colspan: 3, - bodyStyle: 'margin-left: 20px', - width: 180, - disabled: true, - }); - - /* - * General Options - */ - this.rightColumn = this.add({ - border: false, - autoHeight: true, - style: 'margin-left: 5px', - width: 210, - }); - - this.fieldsets.general = this.rightColumn.add({ - xtype: 'fieldset', - autoHeight: true, - defaultType: 'checkbox', - title: _('General'), - layout: 'form', - }); - - this.fields['private'] = this.fieldsets.general.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Private'), - id: 'private', - disabled: true, - }); - - this.fields.prioritize_first_last = this.fieldsets.general.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Prioritize First/Last'), - id: 'prioritize_first_last', - }); - - this.fields.super_seeding = this.fieldsets.general.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Super Seeding'), - id: 'super_seeding', - }); - - // Bind the fields so the options manager can manage them. - for (var id in this.fields) { - this.optionsManager.bind(id, this.fields[id]); - } - - /* - * Buttons - */ - this.buttonPanel = this.rightColumn.add({ - layout: 'hbox', - xtype: 'panel', - border: false, - }); - - /* - * Edit Trackers button - */ - this.buttonPanel.add({ - id: 'edit_trackers', - xtype: 'button', - text: _('Edit Trackers'), - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-edit-trackers', - border: false, - width: 100, - handler: this.onEditTrackers, - scope: this, - }); - - /* - * Apply button - */ - this.buttonPanel.add({ - id: 'apply', - xtype: 'button', - text: _('Apply'), - style: 'margin-left: 10px;', - border: false, - width: 100, - handler: this.onApply, - scope: this, - }); - }, - - onRender: function (ct, position) { - Deluge.details.OptionsTab.superclass.onRender.call(this, ct, position); - - // This is another hack I think, so keep an eye out here when upgrading. - this.layout = new Ext.layout.ColumnLayout(); - this.layout.setContainer(this); - this.doLayout(); - }, - - clear: function () { - if (this.torrentId == null) return; - this.torrentId = null; - this.optionsManager.changeId(null); - }, - - reset: function () { - if (this.torrentId) this.optionsManager.reset(); - }, - - update: function (torrentId) { - if (this.torrentId && !torrentId) this.clear(); // we want to clear the pane if we get a null torrent torrentIds - - if (!torrentId) return; // We do not care about null torrentIds. - - if (this.torrentId != torrentId) { - this.torrentId = torrentId; - this.optionsManager.changeId(torrentId); - } - deluge.client.web.get_torrent_status(torrentId, Deluge.Keys.Options, { - success: this.onRequestComplete, - scope: this, - }); - }, - - onApply: function () { - var changed = this.optionsManager.getDirty(); - deluge.client.core.set_torrent_options([this.torrentId], changed, { - success: function () { - this.optionsManager.commit(); - }, - scope: this, - }); - }, - - onEditTrackers: function () { - deluge.editTrackers.show(); - }, - - onMoveCompletedChecked: function (checkbox, checked) { - this.fields.move_completed_path.setDisabled(!checked); - - if (!checked) return; - this.fields.move_completed_path.focus(); - }, - - onStopRatioChecked: function (checkbox, checked) { - this.fields.remove_at_ratio.setDisabled(!checked); - this.fields.stop_ratio.setDisabled(!checked); - }, - - onRequestComplete: function (torrent, options) { - this.fields['private'].setValue(torrent['private']); - this.fields['private'].setDisabled(true); - delete torrent['private']; - torrent['auto_managed'] = torrent['is_auto_managed']; - torrent['prioritize_first_last_pieces'] = - torrent['prioritize_first_last']; - this.optionsManager.setDefault(torrent); - var stop_at_ratio = this.optionsManager.get('stop_at_ratio'); - this.fields.remove_at_ratio.setDisabled(!stop_at_ratio); - this.fields.stop_ratio.setDisabled(!stop_at_ratio); - this.fields.move_completed_path.setDisabled( - !this.optionsManager.get('move_completed') - ); - }, -}); -/** - * Deluge.details.PeersTab.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 () { - function flagRenderer(value) { - if (!value.replace(' ', '').replace(' ', '')) { - return ''; - } - return String.format( - '<img alt="{1}" title="{1}" src="{0}flag/{1}" />', - deluge.config.base, - value - ); - } - function peerAddressRenderer(value, p, record) { - var seed = - record.data['seed'] == 1024 ? 'x-deluge-seed' : 'x-deluge-peer'; - // Modify display of IPv6 to include brackets - var peer_ip = value.split(':'); - if (peer_ip.length > 2) { - var port = peer_ip.pop(); - var ip = peer_ip.join(':'); - value = '[' + ip + ']:' + port; - } - return String.format('<div class="{0}">{1}</div>', seed, value); - } - function peerProgressRenderer(value) { - var progress = (value * 100).toFixed(0); - return Deluge.progressBar(progress, this.width - 8, progress + '%'); - } - - Deluge.details.PeersTab = Ext.extend(Ext.grid.GridPanel, { - // fast way to figure out if we have a peer already. - peers: {}, - - constructor: function (config) { - config = Ext.apply( - { - title: _('Peers'), - cls: 'x-deluge-peers', - store: new Ext.data.Store({ - reader: new Ext.data.JsonReader( - { - idProperty: 'ip', - root: 'peers', - }, - Deluge.data.Peer - ), - }), - columns: [ - { - header: ' ', - width: 30, - sortable: true, - renderer: flagRenderer, - dataIndex: 'country', - }, - { - header: _('Address'), - width: 125, - sortable: true, - renderer: peerAddressRenderer, - dataIndex: 'ip', - }, - { - header: _('Client'), - width: 125, - sortable: true, - renderer: 'htmlEncode', - dataIndex: 'client', - }, - { - header: _('Progress'), - width: 150, - sortable: true, - renderer: peerProgressRenderer, - dataIndex: 'progress', - }, - { - header: _('Down Speed'), - width: 100, - sortable: true, - renderer: fspeed, - dataIndex: 'down_speed', - }, - { - header: _('Up Speed'), - width: 100, - sortable: true, - renderer: fspeed, - dataIndex: 'up_speed', - }, - ], - stripeRows: true, - deferredRender: false, - autoScroll: true, - }, - config - ); - Deluge.details.PeersTab.superclass.constructor.call(this, config); - }, - - clear: function () { - this.getStore().removeAll(); - this.peers = {}; - }, - - update: function (torrentId) { - deluge.client.web.get_torrent_status(torrentId, Deluge.Keys.Peers, { - success: this.onRequestComplete, - scope: this, - }); - }, - - onRequestComplete: function (torrent, options) { - if (!torrent) return; - - var store = this.getStore(); - var newPeers = []; - var addresses = {}; - - // Go through the peers updating and creating peer records - Ext.each( - torrent.peers, - function (peer) { - if (this.peers[peer.ip]) { - var record = store.getById(peer.ip); - record.beginEdit(); - for (var k in peer) { - if (record.get(k) != peer[k]) { - record.set(k, peer[k]); - } - } - record.endEdit(); - } else { - this.peers[peer.ip] = 1; - newPeers.push(new Deluge.data.Peer(peer, peer.ip)); - } - addresses[peer.ip] = 1; - }, - this - ); - store.add(newPeers); - - // Remove any peers that should not be left in the store. - store.each(function (record) { - if (!addresses[record.id]) { - store.remove(record); - delete this.peers[record.id]; - } - }, this); - store.commitChanges(); - - var sortState = store.getSortState(); - if (!sortState) return; - store.sort(sortState.field, sortState.direction); - }, - }); -})(); -/** - * Deluge.details.StatusTab.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. - */ -Ext.ns('Deluge.details'); - -/** - * @class Deluge.details.StatusTab - * @extends Ext.Panel - */ -Deluge.details.StatusTab = Ext.extend(Ext.Panel, { - title: _('Status'), - autoScroll: true, - - onRender: function (ct, position) { - Deluge.details.StatusTab.superclass.onRender.call(this, ct, position); - - this.progressBar = this.add({ - xtype: 'progress', - cls: 'x-deluge-status-progressbar', - }); - - this.status = this.add({ - cls: 'x-deluge-status', - id: 'deluge-details-status', - - border: false, - width: 1000, - listeners: { - render: { - fn: function (panel) { - panel.load({ - url: deluge.config.base + 'render/tab_status.html', - text: _('Loading') + '...', - }); - panel - .getUpdater() - .on('update', this.onPanelUpdate, this); - }, - scope: this, - }, - }, - }); - }, - - clear: function () { - this.progressBar.updateProgress(0, ' '); - for (var k in this.fields) { - this.fields[k].innerHTML = ''; - } - }, - - update: function (torrentId) { - if (!this.fields) this.getFields(); - deluge.client.web.get_torrent_status(torrentId, Deluge.Keys.Status, { - success: this.onRequestComplete, - scope: this, - }); - }, - - onPanelUpdate: function (el, response) { - this.fields = {}; - Ext.each( - Ext.query('dd', this.status.body.dom), - function (field) { - this.fields[field.className] = field; - }, - this - ); - }, - - onRequestComplete: function (status) { - seeds = - status.total_seeds > -1 - ? status.num_seeds + ' (' + status.total_seeds + ')' - : status.num_seeds; - peers = - status.total_peers > -1 - ? status.num_peers + ' (' + status.total_peers + ')' - : status.num_peers; - last_seen_complete = - status.last_seen_complete > 0.0 - ? fdate(status.last_seen_complete) - : 'Never'; - completed_time = - status.completed_time > 0.0 ? fdate(status.completed_time) : ''; - - var data = { - downloaded: fsize(status.total_done, true), - uploaded: fsize(status.total_uploaded, true), - share: status.ratio == -1 ? '∞' : status.ratio.toFixed(3), - announce: ftime(status.next_announce), - tracker_status: status.tracker_status, - downspeed: status.download_payload_rate - ? fspeed(status.download_payload_rate) - : '0.0 KiB/s', - upspeed: status.upload_payload_rate - ? fspeed(status.upload_payload_rate) - : '0.0 KiB/s', - eta: status.eta < 0 ? '∞' : ftime(status.eta), - pieces: status.num_pieces + ' (' + fsize(status.piece_length) + ')', - seeds: seeds, - peers: peers, - avail: status.distributed_copies.toFixed(3), - active_time: ftime(status.active_time), - seeding_time: ftime(status.seeding_time), - seed_rank: status.seed_rank, - time_added: fdate(status.time_added), - last_seen_complete: last_seen_complete, - completed_time: completed_time, - time_since_transfer: ftime(status.time_since_transfer), - }; - data.auto_managed = _(status.is_auto_managed ? 'True' : 'False'); - - var translate_tracker_status = { - Error: _('Error'), - Warning: _('Warning'), - 'Announce OK': _('Announce OK'), - 'Announce Sent': _('Announce Sent'), - }; - for (var key in translate_tracker_status) { - if (data.tracker_status.indexOf(key) != -1) { - data.tracker_status = data.tracker_status.replace( - key, - translate_tracker_status[key] - ); - break; - } - } - - data.downloaded += - ' (' + - (status.total_payload_download - ? fsize(status.total_payload_download) - : '0.0 KiB') + - ')'; - data.uploaded += - ' (' + - (status.total_payload_upload - ? fsize(status.total_payload_upload) - : '0.0 KiB') + - ')'; - - for (var field in this.fields) { - this.fields[field].innerHTML = data[field]; - } - var text = status.state + ' ' + status.progress.toFixed(2) + '%'; - this.progressBar.updateProgress(status.progress / 100.0, text); - }, -}); -/** - * Deluge.preferences.BandwidthPage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Bandwidth - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Bandwidth = Ext.extend(Ext.form.FormPanel, { - constructor: function (config) { - config = Ext.apply( - { - border: false, - title: _('Bandwidth'), - header: false, - layout: 'form', - labelWidth: 10, - }, - config - ); - Deluge.preferences.Bandwidth.superclass.constructor.call(this, config); - }, - - initComponent: function () { - Deluge.preferences.Bandwidth.superclass.initComponent.call(this); - - var om = deluge.preferences.getOptionsManager(); - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Global Bandwidth Usage'), - labelWidth: 200, - defaultType: 'spinnerfield', - defaults: { - minValue: -1, - maxValue: 99999, - }, - style: 'margin-bottom: 0px; padding-bottom: 0px;', - autoHeight: true, - }); - om.bind( - 'max_connections_global', - fieldset.add({ - name: 'max_connections_global', - fieldLabel: _('Maximum Connections:'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - om.bind( - 'max_upload_slots_global', - fieldset.add({ - name: 'max_upload_slots_global', - fieldLabel: _('Maximum Upload Slots'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - om.bind( - 'max_download_speed', - fieldset.add({ - name: 'max_download_speed', - fieldLabel: _('Maximum Download Speed (KiB/s):'), - labelSeparator: '', - width: 80, - value: -1.0, - decimalPrecision: 1, - }) - ); - om.bind( - 'max_upload_speed', - fieldset.add({ - name: 'max_upload_speed', - fieldLabel: _('Maximum Upload Speed (KiB/s):'), - labelSeparator: '', - width: 80, - value: -1.0, - decimalPrecision: 1, - }) - ); - om.bind( - 'max_half_open_connections', - fieldset.add({ - name: 'max_half_open_connections', - fieldLabel: _('Maximum Half-Open Connections:'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - om.bind( - 'max_connections_per_second', - fieldset.add({ - name: 'max_connections_per_second', - fieldLabel: _('Maximum Connection Attempts per Second:'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: '', - defaultType: 'checkbox', - style: 'padding-top: 0px; padding-bottom: 5px; margin-top: 0px; margin-bottom: 0px;', - autoHeight: true, - }); - om.bind( - 'ignore_limits_on_local_network', - fieldset.add({ - name: 'ignore_limits_on_local_network', - height: 22, - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Ignore limits on local network'), - }) - ); - om.bind( - 'rate_limit_ip_overhead', - fieldset.add({ - name: 'rate_limit_ip_overhead', - height: 22, - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Rate limit IP overhead'), - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Per Torrent Bandwidth Usage'), - style: 'margin-bottom: 0px; padding-bottom: 0px;', - defaultType: 'spinnerfield', - labelWidth: 200, - defaults: { - minValue: -1, - maxValue: 99999, - }, - autoHeight: true, - }); - om.bind( - 'max_connections_per_torrent', - fieldset.add({ - name: 'max_connections_per_torrent', - fieldLabel: _('Maximum Connections:'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - om.bind( - 'max_upload_slots_per_torrent', - fieldset.add({ - name: 'max_upload_slots_per_torrent', - fieldLabel: _('Maximum Upload Slots:'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - om.bind( - 'max_download_speed_per_torrent', - fieldset.add({ - name: 'max_download_speed_per_torrent', - fieldLabel: _('Maximum Download Speed (KiB/s):'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - om.bind( - 'max_upload_speed_per_torrent', - fieldset.add({ - name: 'max_upload_speed_per_torrent', - fieldLabel: _('Maximum Upload Speed (KiB/s):'), - labelSeparator: '', - width: 80, - value: -1, - decimalPrecision: 0, - }) - ); - }, -}); -/** - * Deluge.preferences.CachePage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Cache - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Cache = Ext.extend(Ext.form.FormPanel, { - border: false, - title: _('Cache'), - header: false, - layout: 'form', - - initComponent: function () { - Deluge.preferences.Cache.superclass.initComponent.call(this); - - var om = deluge.preferences.getOptionsManager(); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Settings'), - autoHeight: true, - labelWidth: 180, - defaultType: 'spinnerfield', - defaults: { - decimalPrecision: 0, - minValue: -1, - maxValue: 999999, - }, - }); - om.bind( - 'cache_size', - fieldset.add({ - fieldLabel: _('Cache Size (16 KiB Blocks):'), - labelSeparator: '', - name: 'cache_size', - width: 60, - value: 512, - }) - ); - om.bind( - 'cache_expiry', - fieldset.add({ - fieldLabel: _('Cache Expiry (seconds):'), - labelSeparator: '', - name: 'cache_expiry', - width: 60, - value: 60, - }) - ); - }, -}); -/** - * Deluge.preferences.DaemonPage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Daemon - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Daemon = Ext.extend(Ext.form.FormPanel, { - border: false, - title: _('Daemon'), - header: false, - layout: 'form', - - initComponent: function () { - Deluge.preferences.Daemon.superclass.initComponent.call(this); - - var om = deluge.preferences.getOptionsManager(); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Port'), - autoHeight: true, - defaultType: 'spinnerfield', - }); - om.bind( - 'daemon_port', - fieldset.add({ - fieldLabel: _('Daemon port:'), - labelSeparator: '', - name: 'daemon_port', - value: 58846, - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Connections'), - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - om.bind( - 'allow_remote', - fieldset.add({ - fieldLabel: '', - height: 22, - labelSeparator: '', - boxLabel: _('Allow Remote Connections'), - name: 'allow_remote', - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Other'), - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - om.bind( - 'new_release_check', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - height: 40, - boxLabel: _('Periodically check the website for new releases'), - id: 'new_release_check', - }) - ); - }, -}); -/** - * Deluge.preferences.DownloadsPage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Downloads - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Downloads = Ext.extend(Ext.FormPanel, { - constructor: function (config) { - config = Ext.apply( - { - border: false, - title: _('Downloads'), - header: false, - layout: 'form', - autoHeight: true, - width: 320, - }, - config - ); - Deluge.preferences.Downloads.superclass.constructor.call(this, config); - }, - - initComponent: function () { - Deluge.preferences.Downloads.superclass.initComponent.call(this); - - var optMan = deluge.preferences.getOptionsManager(); - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Folders'), - labelWidth: 150, - defaultType: 'togglefield', - autoHeight: true, - labelAlign: 'top', - width: 300, - style: 'margin-bottom: 5px; padding-bottom: 5px;', - }); - - optMan.bind( - 'download_location', - fieldset.add({ - xtype: 'textfield', - name: 'download_location', - fieldLabel: _('Download to:'), - labelSeparator: '', - width: 280, - }) - ); - - var field = fieldset.add({ - name: 'move_completed_path', - fieldLabel: _('Move completed to:'), - labelSeparator: '', - width: 280, - }); - optMan.bind('move_completed', field.toggle); - optMan.bind('move_completed_path', field.input); - - field = fieldset.add({ - name: 'torrentfiles_location', - fieldLabel: _('Copy of .torrent files to:'), - labelSeparator: '', - width: 280, - }); - optMan.bind('copy_torrent_file', field.toggle); - optMan.bind('torrentfiles_location', field.input); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Options'), - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - style: 'margin-bottom: 0; padding-bottom: 0;', - width: 280, - }); - optMan.bind( - 'prioritize_first_last_pieces', - fieldset.add({ - name: 'prioritize_first_last_pieces', - labelSeparator: '', - height: 22, - boxLabel: _('Prioritize first and last pieces of torrent'), - }) - ); - optMan.bind( - 'sequential_download', - fieldset.add({ - name: 'sequential_download', - labelSeparator: '', - height: 22, - boxLabel: _('Sequential download'), - }) - ); - optMan.bind( - 'add_paused', - fieldset.add({ - name: 'add_paused', - labelSeparator: '', - height: 22, - boxLabel: _('Add torrents in Paused state'), - }) - ); - optMan.bind( - 'pre_allocate_storage', - fieldset.add({ - name: 'pre_allocate_storage', - labelSeparator: '', - height: 22, - boxLabel: _('Pre-allocate disk space'), - }) - ); - }, -}); -/** - * Deluge.preferences.EncryptionPage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Encryption - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Encryption = Ext.extend(Ext.form.FormPanel, { - border: false, - title: _('Encryption'), - header: false, - - initComponent: function () { - Deluge.preferences.Encryption.superclass.initComponent.call(this); - - var optMan = deluge.preferences.getOptionsManager(); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Settings'), - header: false, - autoHeight: true, - defaultType: 'combo', - width: 300, - }); - optMan.bind( - 'enc_in_policy', - fieldset.add({ - fieldLabel: _('Incoming:'), - labelSeparator: '', - mode: 'local', - width: 150, - store: new Ext.data.ArrayStore({ - fields: ['id', 'text'], - data: [ - [0, _('Forced')], - [1, _('Enabled')], - [2, _('Disabled')], - ], - }), - editable: false, - triggerAction: 'all', - valueField: 'id', - displayField: 'text', - }) - ); - optMan.bind( - 'enc_out_policy', - fieldset.add({ - fieldLabel: _('Outgoing:'), - labelSeparator: '', - mode: 'local', - width: 150, - store: new Ext.data.SimpleStore({ - fields: ['id', 'text'], - data: [ - [0, _('Forced')], - [1, _('Enabled')], - [2, _('Disabled')], - ], - }), - editable: false, - triggerAction: 'all', - valueField: 'id', - displayField: 'text', - }) - ); - optMan.bind( - 'enc_level', - fieldset.add({ - fieldLabel: _('Level:'), - labelSeparator: '', - mode: 'local', - width: 150, - store: new Ext.data.SimpleStore({ - fields: ['id', 'text'], - data: [ - [0, _('Handshake')], - [1, _('Full Stream')], - [2, _('Either')], - ], - }), - editable: false, - triggerAction: 'all', - valueField: 'id', - displayField: 'text', - }) - ); - }, -}); -/** - * Deluge.preferences.InstallPluginWindow.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.InstallPluginWindow - * @extends Ext.Window - */ -Deluge.preferences.InstallPluginWindow = Ext.extend(Ext.Window, { - title: _('Install Plugin'), - layout: 'fit', - height: 115, - width: 350, - constrainHeader: true, - bodyStyle: 'padding: 10px 5px;', - buttonAlign: 'center', - closeAction: 'hide', - iconCls: 'x-deluge-install-plugin', - modal: true, - plain: true, - - initComponent: function () { - Deluge.preferences.InstallPluginWindow.superclass.initComponent.call( - this - ); - this.addButton(_('Install'), this.onInstall, this); - - this.form = this.add({ - xtype: 'form', - baseCls: 'x-plain', - labelWidth: 70, - autoHeight: true, - fileUpload: true, - items: [ - { - xtype: 'fileuploadfield', - width: 240, - emptyText: _('Select an egg'), - fieldLabel: _('Plugin Egg'), - name: 'file', - buttonCfg: { - text: _('Browse...'), - }, - }, - ], - }); - }, - - onInstall: function (field, e) { - this.form.getForm().submit({ - url: deluge.config.base + 'upload', - waitMsg: _('Uploading your plugin...'), - success: this.onUploadSuccess, - scope: this, - }); - }, - - onUploadPlugin: function (info, obj, response, request) { - this.fireEvent('pluginadded'); - }, - - onUploadSuccess: function (fp, upload) { - this.hide(); - if (upload.result.success) { - var filename = this.form.getForm().getFieldValues().file; - filename = filename.split('\\').slice(-1)[0]; - var path = upload.result.files[0]; - this.form.getForm().setValues({ file: '' }); - deluge.client.web.upload_plugin(filename, path, { - success: this.onUploadPlugin, - scope: this, - filename: filename, - }); - } - }, -}); -/** - * Deluge.preferences.InterfacePage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Interface - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, { - border: false, - title: _('Interface'), - header: false, - layout: 'form', - - initComponent: function () { - Deluge.preferences.Interface.superclass.initComponent.call(this); - - var om = (this.optionsManager = new Deluge.OptionsManager()); - this.on('show', this.onPageShow, this); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Interface'), - style: 'margin-bottom: 0px; padding-bottom: 5px; padding-top: 5px', - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - defaults: { - height: 17, - fieldLabel: '', - labelSeparator: '', - }, - }); - om.bind( - 'show_session_speed', - fieldset.add({ - name: 'show_session_speed', - boxLabel: _('Show session speed in titlebar'), - }) - ); - om.bind( - 'sidebar_show_zero', - fieldset.add({ - name: 'sidebar_show_zero', - boxLabel: _('Show filters with zero torrents'), - }) - ); - om.bind( - 'sidebar_multiple_filters', - fieldset.add({ - name: 'sidebar_multiple_filters', - boxLabel: _('Allow the use of multiple filters at once'), - }) - ); - - var languagePanel = this.add({ - xtype: 'fieldset', - border: false, - title: _('Language'), - style: 'margin-bottom: 0px; padding-bottom: 5px; padding-top: 5px', - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - this.language = om.bind( - 'language', - languagePanel.add({ - xtype: 'combo', - labelSeparator: '', - name: 'language', - mode: 'local', - width: 200, - store: new Ext.data.ArrayStore({ - fields: ['id', 'text'], - }), - editable: false, - triggerAction: 'all', - valueField: 'id', - displayField: 'text', - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('WebUI Password'), - style: 'margin-bottom: 0px; padding-bottom: 5px; padding-top: 5px', - autoHeight: true, - labelWidth: 100, - defaultType: 'textfield', - defaults: { - width: 100, - inputType: 'password', - labelStyle: 'padding-left: 5px', - height: 20, - labelSeparator: '', - }, - }); - - this.oldPassword = fieldset.add({ - name: 'old_password', - fieldLabel: _('Old:'), - }); - this.newPassword = fieldset.add({ - name: 'new_password', - fieldLabel: _('New:'), - }); - this.confirmPassword = fieldset.add({ - name: 'confirm_password', - fieldLabel: _('Confirm:'), - }); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Server'), - style: 'padding-top: 5px; margin-bottom: 0px; padding-bottom: 5px', - autoHeight: true, - labelWidth: 100, - defaultType: 'spinnerfield', - defaults: { - labelSeparator: '', - labelStyle: 'padding-left: 5px', - height: 20, - width: 80, - }, - }); - om.bind( - 'session_timeout', - fieldset.add({ - name: 'session_timeout', - fieldLabel: _('Session Timeout:'), - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }) - ); - om.bind( - 'port', - fieldset.add({ - name: 'port', - fieldLabel: _('Port:'), - decimalPrecision: 0, - minValue: 1, - maxValue: 65535, - }) - ); - this.httpsField = om.bind( - 'https', - fieldset.add({ - xtype: 'checkbox', - name: 'https', - hideLabel: true, - width: 300, - style: 'margin-left: 5px', - boxLabel: _( - 'Enable SSL (paths relative to Deluge config folder)' - ), - }) - ); - this.httpsField.on('check', this.onSSLCheck, this); - this.pkeyField = om.bind( - 'pkey', - fieldset.add({ - xtype: 'textfield', - disabled: true, - name: 'pkey', - width: 180, - fieldLabel: _('Private Key:'), - }) - ); - this.certField = om.bind( - 'cert', - fieldset.add({ - xtype: 'textfield', - disabled: true, - name: 'cert', - width: 180, - fieldLabel: _('Certificate:'), - }) - ); - }, - - onApply: function () { - var changed = this.optionsManager.getDirty(); - if (!Ext.isObjectEmpty(changed)) { - deluge.client.web.set_config(changed, { - success: this.onSetConfig, - scope: this, - }); - - for (var key in deluge.config) { - deluge.config[key] = this.optionsManager.get(key); - } - if ('language' in changed) { - Ext.Msg.show({ - title: _('WebUI Language Changed'), - msg: _( - 'Do you want to refresh the page now to use the new language?' - ), - buttons: { - yes: _('Refresh'), - no: _('Close'), - }, - multiline: false, - fn: function (btnText) { - if (btnText === 'yes') location.reload(); - }, - icon: Ext.MessageBox.QUESTION, - }); - } - } - if (this.oldPassword.getValue() || this.newPassword.getValue()) { - this.onPasswordChange(); - } - }, - - onOk: function () { - this.onApply(); - }, - - onGotConfig: function (config) { - this.optionsManager.set(config); - }, - - onGotLanguages: function (info, obj, response, request) { - info.unshift(['', _('System Default')]); - this.language.store.loadData(info); - this.language.setValue(this.optionsManager.get('language')); - }, - - onPasswordChange: function () { - var newPassword = this.newPassword.getValue(); - if (newPassword != this.confirmPassword.getValue()) { - Ext.MessageBox.show({ - title: _('Invalid Password'), - msg: _("Your passwords don't match!"), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - return; - } - - var oldPassword = this.oldPassword.getValue(); - deluge.client.auth.change_password(oldPassword, newPassword, { - success: function (result) { - if (!result) { - Ext.MessageBox.show({ - title: _('Password'), - msg: _('Your old password was incorrect!'), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - this.oldPassword.setValue(''); - } else { - Ext.MessageBox.show({ - title: _('Change Successful'), - msg: _('Your password was successfully changed!'), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.INFO, - iconCls: 'x-deluge-icon-info', - }); - this.oldPassword.setValue(''); - this.newPassword.setValue(''); - this.confirmPassword.setValue(''); - } - }, - scope: this, - }); - }, - - onSetConfig: function () { - this.optionsManager.commit(); - }, - - onPageShow: function () { - deluge.client.web.get_config({ - success: this.onGotConfig, - scope: this, - }); - deluge.client.webutils.get_languages({ - success: this.onGotLanguages, - scope: this, - }); - }, - - onSSLCheck: function (e, checked) { - this.pkeyField.setDisabled(!checked); - this.certField.setDisabled(!checked); - }, -}); -/** - * Deluge.preferences.NetworkPage.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. - */ -Ext.namespace('Deluge.preferences'); - -// custom Vtype for vtype:'IPAddress' -Ext.apply(Ext.form.VTypes, { - IPAddress: function (v) { - return /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(v); - }, - IPAddressText: 'Must be a numeric IP address', - IPAddressMask: /[\d\.]/i, -}); - -/** - * @class Deluge.preferences.Network - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Network = Ext.extend(Ext.form.FormPanel, { - border: false, - layout: 'form', - title: _('Network'), - header: false, - - initComponent: function () { - Deluge.preferences.Network.superclass.initComponent.call(this); - var optMan = deluge.preferences.getOptionsManager(); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Incoming Address'), - style: 'margin-bottom: 5px; padding-bottom: 0px;', - autoHeight: true, - labelWidth: 1, - defaultType: 'textfield', - }); - optMan.bind( - 'listen_interface', - fieldset.add({ - name: 'listen_interface', - fieldLabel: '', - labelSeparator: '', - width: 200, - vtype: 'IPAddress', - }) - ); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Incoming Port'), - style: 'margin-bottom: 5px; padding-bottom: 0px;', - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - optMan.bind( - 'random_port', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Use Random Port'), - name: 'random_port', - height: 22, - listeners: { - check: { - fn: function (e, checked) { - this.listenPort.setDisabled(checked); - }, - scope: this, - }, - }, - }) - ); - - this.listenPort = fieldset.add({ - xtype: 'spinnerfield', - name: 'listen_port', - fieldLabel: '', - labelSeparator: '', - width: 75, - strategy: { - xtype: 'number', - decimalPrecision: 0, - minValue: 0, - maxValue: 65535, - }, - }); - optMan.bind('listen_ports', this.listenPort); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Outgoing Interface'), - style: 'margin-bottom: 5px; padding-bottom: 0px;', - autoHeight: true, - labelWidth: 1, - defaultType: 'textfield', - }); - optMan.bind( - 'outgoing_interface', - fieldset.add({ - name: 'outgoing_interface', - fieldLabel: '', - labelSeparator: '', - width: 40, - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Outgoing Ports'), - style: 'margin-bottom: 5px; padding-bottom: 0px;', - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - optMan.bind( - 'random_outgoing_ports', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Use Random Ports'), - name: 'random_outgoing_ports', - height: 22, - listeners: { - check: { - fn: function (e, checked) { - this.outgoingPorts.setDisabled(checked); - }, - scope: this, - }, - }, - }) - ); - this.outgoingPorts = fieldset.add({ - xtype: 'spinnergroup', - name: 'outgoing_ports', - fieldLabel: '', - labelSeparator: '', - colCfg: { - labelWidth: 40, - style: 'margin-right: 10px;', - }, - items: [ - { - fieldLabel: _('From:'), - labelSeparator: '', - strategy: { - xtype: 'number', - decimalPrecision: 0, - minValue: 0, - maxValue: 65535, - }, - }, - { - fieldLabel: _('To:'), - labelSeparator: '', - strategy: { - xtype: 'number', - decimalPrecision: 0, - minValue: 0, - maxValue: 65535, - }, - }, - ], - }); - optMan.bind('outgoing_ports', this.outgoingPorts); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Network Extras'), - autoHeight: true, - layout: 'table', - layoutConfig: { - columns: 3, - }, - defaultType: 'checkbox', - }); - optMan.bind( - 'upnp', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('UPnP'), - name: 'upnp', - }) - ); - optMan.bind( - 'natpmp', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('NAT-PMP'), - ctCls: 'x-deluge-indent-checkbox', - name: 'natpmp', - }) - ); - optMan.bind( - 'utpex', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('Peer Exchange'), - ctCls: 'x-deluge-indent-checkbox', - name: 'utpex', - }) - ); - optMan.bind( - 'lsd', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('LSD'), - name: 'lsd', - }) - ); - optMan.bind( - 'dht', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - boxLabel: _('DHT'), - ctCls: 'x-deluge-indent-checkbox', - name: 'dht', - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Type Of Service'), - style: 'margin-bottom: 5px; padding-bottom: 0px;', - bodyStyle: 'margin: 0px; padding: 0px', - autoHeight: true, - defaultType: 'textfield', - }); - optMan.bind( - 'peer_tos', - fieldset.add({ - name: 'peer_tos', - fieldLabel: _('Peer TOS Byte:'), - labelSeparator: '', - width: 40, - }) - ); - }, -}); -/** - * Deluge.preferences.OtherPage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Other - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Other = Ext.extend(Ext.form.FormPanel, { - constructor: function (config) { - config = Ext.apply( - { - border: false, - title: _('Other'), - header: false, - layout: 'form', - }, - config - ); - Deluge.preferences.Other.superclass.constructor.call(this, config); - }, - - initComponent: function () { - Deluge.preferences.Other.superclass.initComponent.call(this); - - var optMan = deluge.preferences.getOptionsManager(); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Updates'), - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - optMan.bind( - 'new_release_check', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - height: 22, - name: 'new_release_check', - boxLabel: _('Be alerted about new releases'), - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('System Information'), - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - fieldset.add({ - xtype: 'panel', - border: false, - bodyCfg: { - html: _( - 'Help us improve Deluge by sending us your Python version, PyGTK version, OS and processor types. Absolutely no other information is sent.' - ), - }, - }); - optMan.bind( - 'send_info', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - height: 22, - boxLabel: _('Yes, please send anonymous statistics'), - name: 'send_info', - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('GeoIP Database'), - autoHeight: true, - labelWidth: 80, - defaultType: 'textfield', - }); - optMan.bind( - 'geoip_db_location', - fieldset.add({ - name: 'geoip_db_location', - fieldLabel: _('Path:'), - labelSeparator: '', - width: 200, - }) - ); - }, -}); -/** - * Deluge.preferences.PluginsPage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Plugins - * @extends Ext.Panel - */ -Deluge.preferences.Plugins = Ext.extend(Ext.Panel, { - layout: 'border', - title: _('Plugins'), - header: false, - border: false, - cls: 'x-deluge-plugins', - - pluginTemplate: new Ext.Template( - '<dl class="singleline">' + - '<dt>' + - _('Author:') + - '</dt><dd>{author}</dd>' + - '<dt>' + - _('Version:') + - '</dt><dd>{version}</dd>' + - '<dt>' + - _('Author Email:') + - '</dt><dd>{email}</dd>' + - '<dt>' + - _('Homepage:') + - '</dt><dd>{homepage}</dd>' + - '<dt>' + - _('Details:') + - '</dt><dd style="white-space:normal">{details}</dd>' + - '</dl>' - ), - - initComponent: function () { - Deluge.preferences.Plugins.superclass.initComponent.call(this); - this.defaultValues = { - version: '', - email: '', - homepage: '', - details: '', - }; - this.pluginTemplate.compile(); - - var checkboxRenderer = function (v, p, record) { - p.css += ' x-grid3-check-col-td'; - return ( - '<div class="x-grid3-check-col' + (v ? '-on' : '') + '"> </div>' - ); - }; - - this.list = this.add({ - xtype: 'listview', - store: new Ext.data.ArrayStore({ - fields: [ - { name: 'enabled', mapping: 0 }, - { name: 'plugin', mapping: 1, sortType: 'asUCString' }, - ], - }), - columns: [ - { - id: 'enabled', - header: _('Enabled'), - width: 0.2, - sortable: true, - tpl: new Ext.XTemplate('{enabled:this.getCheckbox}', { - getCheckbox: function (v) { - return ( - '<div class="x-grid3-check-col' + - (v ? '-on' : '') + - '" rel="chkbox"> </div>' - ); - }, - }), - dataIndex: 'enabled', - }, - { - id: 'plugin', - header: _('Plugin'), - width: 0.8, - sortable: true, - dataIndex: 'plugin', - }, - ], - singleSelect: true, - autoExpandColumn: 'plugin', - listeners: { - selectionchange: { fn: this.onPluginSelect, scope: this }, - }, - }); - - this.panel = this.add({ - region: 'center', - autoScroll: true, - items: [this.list], - bbar: new Ext.Toolbar({ - items: [ - { - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-install-plugin', - text: _('Install'), - handler: this.onInstallPluginWindow, - scope: this, - }, - '->', - { - cls: 'x-btn-text-icon', - text: _('Find More'), - iconCls: 'x-deluge-find-more', - handler: this.onFindMorePlugins, - scope: this, - }, - ], - }), - }); - - var pp = (this.pluginInfo = this.add({ - xtype: 'panel', - border: false, - height: 100, - region: 'south', - padding: '5', - autoScroll: true, - bodyCfg: { - style: 'white-space: nowrap', - }, - })); - - this.pluginInfo.on('render', this.onPluginInfoRender, this); - this.list.on('click', this.onNodeClick, this); - deluge.preferences.on('show', this.onPreferencesShow, this); - deluge.events.on('PluginDisabledEvent', this.onPluginDisabled, this); - deluge.events.on('PluginEnabledEvent', this.onPluginEnabled, this); - }, - - disablePlugin: function (plugin) { - deluge.client.core.disable_plugin(plugin); - }, - - enablePlugin: function (plugin) { - deluge.client.core.enable_plugin(plugin); - }, - - setInfo: function (plugin) { - if (!this.pluginInfo.rendered) return; - var values = plugin || this.defaultValues; - this.pluginInfo.body.dom.innerHTML = this.pluginTemplate.apply(values); - }, - - updatePlugins: function () { - var onGotAvailablePlugins = function (plugins) { - this.availablePlugins = plugins.sort(function (a, b) { - return a.toLowerCase().localeCompare(b.toLowerCase()); - }); - - deluge.client.core.get_enabled_plugins({ - success: onGotEnabledPlugins, - scope: this, - }); - }; - - var onGotEnabledPlugins = function (plugins) { - this.enabledPlugins = plugins; - this.onGotPlugins(); - }; - - deluge.client.core.get_available_plugins({ - success: onGotAvailablePlugins, - scope: this, - }); - }, - - updatePluginsGrid: function () { - var plugins = []; - Ext.each( - this.availablePlugins, - function (plugin) { - if (this.enabledPlugins.indexOf(plugin) > -1) { - plugins.push([true, plugin]); - } else { - plugins.push([false, plugin]); - } - }, - this - ); - this.list.getStore().loadData(plugins); - }, - - onNodeClick: function (dv, index, node, e) { - var el = new Ext.Element(e.target); - if (el.getAttribute('rel') != 'chkbox') return; - - var r = dv.getStore().getAt(index); - if (r.get('plugin') == 'WebUi') return; - r.set('enabled', !r.get('enabled')); - r.commit(); - if (r.get('enabled')) { - this.enablePlugin(r.get('plugin')); - } else { - this.disablePlugin(r.get('plugin')); - } - }, - - onFindMorePlugins: function () { - window.open('http://dev.deluge-torrent.org/wiki/Plugins'); - }, - - onGotPlugins: function () { - this.setInfo(); - this.updatePluginsGrid(); - }, - - onGotPluginInfo: function (info) { - var values = { - author: info['Author'], - version: info['Version'], - email: info['Author-email'], - homepage: info['Home-page'], - details: info['Description'], - }; - this.setInfo(values); - delete info; - }, - - onInstallPluginWindow: function () { - if (!this.installWindow) { - this.installWindow = new Deluge.preferences.InstallPluginWindow(); - this.installWindow.on('pluginadded', this.onPluginInstall, this); - } - this.installWindow.show(); - }, - - onPluginEnabled: function (pluginName) { - var index = this.list.getStore().find('plugin', pluginName); - if (index == -1) return; - var plugin = this.list.getStore().getAt(index); - plugin.set('enabled', true); - plugin.commit(); - }, - - onPluginDisabled: function (pluginName) { - var index = this.list.getStore().find('plugin', pluginName); - if (index == -1) return; - var plugin = this.list.getStore().getAt(index); - plugin.set('enabled', false); - plugin.commit(); - }, - - onPluginInstall: function () { - this.updatePlugins(); - }, - - onPluginSelect: function (dv, selections) { - if (selections.length == 0) return; - var r = dv.getRecords(selections)[0]; - deluge.client.web.get_plugin_info(r.get('plugin'), { - success: this.onGotPluginInfo, - scope: this, - }); - }, - - onPreferencesShow: function () { - this.updatePlugins(); - }, - - onPluginInfoRender: function (ct, position) { - this.setInfo(); - }, -}); -/** - * Deluge.preferences.PreferencesWindow.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. - */ -Ext.namespace('Deluge.preferences'); - -PreferencesRecord = Ext.data.Record.create([{ name: 'name', type: 'string' }]); - -/** - * @class Deluge.preferences.PreferencesWindow - * @extends Ext.Window - */ -Deluge.preferences.PreferencesWindow = Ext.extend(Ext.Window, { - /** - * @property {String} currentPage The currently selected page. - */ - currentPage: null, - - title: _('Preferences'), - layout: 'border', - width: 485, - height: 500, - border: false, - constrainHeader: true, - buttonAlign: 'right', - closeAction: 'hide', - closable: true, - iconCls: 'x-deluge-preferences', - plain: true, - resizable: false, - - pages: {}, - - initComponent: function () { - Deluge.preferences.PreferencesWindow.superclass.initComponent.call( - this - ); - - this.list = new Ext.list.ListView({ - store: new Ext.data.Store(), - columns: [ - { - id: 'name', - dataIndex: 'name', - }, - ], - singleSelect: true, - listeners: { - selectionchange: { - fn: this.onPageSelect, - scope: this, - }, - }, - hideHeaders: true, - autoExpandColumn: 'name', - deferredRender: false, - autoScroll: true, - collapsible: true, - }); - this.add({ - region: 'west', - items: [this.list], - width: 120, - margins: '0 5 0 0', - cmargins: '0 5 0 0', - }); - - this.configPanel = this.add({ - type: 'container', - autoDestroy: false, - region: 'center', - layout: 'card', - layoutConfig: { - deferredRender: true, - }, - autoScroll: true, - width: 300, - }); - - this.addButton(_('Close'), this.onClose, this); - this.addButton(_('Apply'), this.onApply, this); - this.addButton(_('OK'), this.onOk, this); - - this.optionsManager = new Deluge.OptionsManager(); - this.on('afterrender', this.onAfterRender, this); - this.on('show', this.onShow, this); - - this.initPages(); - }, - - initPages: function () { - deluge.preferences = this; - this.addPage(new Deluge.preferences.Downloads()); - this.addPage(new Deluge.preferences.Network()); - this.addPage(new Deluge.preferences.Encryption()); - this.addPage(new Deluge.preferences.Bandwidth()); - this.addPage(new Deluge.preferences.Interface()); - this.addPage(new Deluge.preferences.Other()); - this.addPage(new Deluge.preferences.Daemon()); - this.addPage(new Deluge.preferences.Queue()); - this.addPage(new Deluge.preferences.Proxy()); - this.addPage(new Deluge.preferences.Cache()); - this.addPage(new Deluge.preferences.Plugins()); - }, - - onApply: function (e) { - var changed = this.optionsManager.getDirty(); - if (!Ext.isObjectEmpty(changed)) { - // Workaround for only displaying single listen port but still pass array to core. - if ('listen_ports' in changed) { - changed.listen_ports = [ - changed.listen_ports, - changed.listen_ports, - ]; - } - deluge.client.core.set_config(changed, { - success: this.onSetConfig, - scope: this, - }); - } - - for (var page in this.pages) { - if (this.pages[page].onApply) this.pages[page].onApply(); - } - }, - - /** - * Return the options manager for the preferences window. - * @returns {Deluge.OptionsManager} the options manager - */ - getOptionsManager: function () { - return this.optionsManager; - }, - - /** - * Adds a page to the preferences window. - * @param {Mixed} page - */ - addPage: function (page) { - var store = this.list.getStore(); - var name = page.title; - store.add([new PreferencesRecord({ name: name })]); - page['bodyStyle'] = 'padding: 5px'; - page.preferences = this; - this.pages[name] = this.configPanel.add(page); - this.pages[name].index = -1; - return this.pages[name]; - }, - - /** - * Removes a preferences page from the window. - * @param {mixed} name - */ - removePage: function (page) { - var name = page.title; - var store = this.list.getStore(); - store.removeAt(store.find('name', name)); - this.configPanel.remove(page); - delete this.pages[page.title]; - }, - - /** - * Select which preferences page is displayed. - * @param {String} page The page name to change to - */ - selectPage: function (page) { - if (this.pages[page].index < 0) { - this.pages[page].index = this.configPanel.items.indexOf( - this.pages[page] - ); - } - this.list.select(this.pages[page].index); - }, - - // private - doSelectPage: function (page) { - if (this.pages[page].index < 0) { - this.pages[page].index = this.configPanel.items.indexOf( - this.pages[page] - ); - } - this.configPanel.getLayout().setActiveItem(this.pages[page].index); - this.currentPage = page; - }, - - // private - onGotConfig: function (config) { - this.getOptionsManager().set(config); - }, - - // private - onPageSelect: function (list, selections) { - var r = list.getRecord(selections[0]); - this.doSelectPage(r.get('name')); - }, - - // private - onSetConfig: function () { - this.getOptionsManager().commit(); - }, - - // private - onAfterRender: function () { - if (!this.list.getSelectionCount()) { - this.list.select(0); - } - this.configPanel.getLayout().setActiveItem(0); - }, - - // private - onShow: function () { - if (!deluge.client.core) return; - deluge.client.core.get_config({ - success: this.onGotConfig, - scope: this, - }); - }, - - // private - onClose: function () { - this.hide(); - }, - - // private - onOk: function () { - var changed = this.optionsManager.getDirty(); - if (!Ext.isObjectEmpty(changed)) { - deluge.client.core.set_config(changed, { - success: this.onSetConfig, - scope: this, - }); - } - - for (var page in this.pages) { - if (this.pages[page].onOk) this.pages[page].onOk(); - } - - this.hide(); - }, -}); -/** - * Deluge.preferences.ProxyField.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. - */ -Ext.ns('Deluge.preferences'); - -/** - * @class Deluge.preferences.ProxyField - * @extends Ext.form.FieldSet - */ -Deluge.preferences.ProxyField = Ext.extend(Ext.form.FieldSet, { - border: false, - autoHeight: true, - labelWidth: 70, - - initComponent: function () { - Deluge.preferences.ProxyField.superclass.initComponent.call(this); - this.proxyType = this.add({ - xtype: 'combo', - fieldLabel: _('Type:'), - labelSeparator: '', - name: 'proxytype', - mode: 'local', - width: 150, - store: new Ext.data.ArrayStore({ - fields: ['id', 'text'], - data: [ - [0, _('None')], - [1, _('Socks4')], - [2, _('Socks5')], - [3, _('Socks5 Auth')], - [4, _('HTTP')], - [5, _('HTTP Auth')], - [6, _('I2P')], - ], - }), - editable: false, - triggerAction: 'all', - valueField: 'id', - displayField: 'text', - }); - this.proxyType.on('change', this.onFieldChange, this); - this.proxyType.on('select', this.onTypeSelect, this); - - this.hostname = this.add({ - xtype: 'textfield', - name: 'hostname', - fieldLabel: _('Host:'), - labelSeparator: '', - width: 220, - }); - this.hostname.on('change', this.onFieldChange, this); - - this.port = this.add({ - xtype: 'spinnerfield', - name: 'port', - fieldLabel: _('Port:'), - labelSeparator: '', - width: 80, - decimalPrecision: 0, - minValue: 0, - maxValue: 65535, - }); - this.port.on('change', this.onFieldChange, this); - - this.username = this.add({ - xtype: 'textfield', - name: 'username', - fieldLabel: _('Username:'), - labelSeparator: '', - width: 220, - }); - this.username.on('change', this.onFieldChange, this); - - this.password = this.add({ - xtype: 'textfield', - name: 'password', - fieldLabel: _('Password:'), - labelSeparator: '', - inputType: 'password', - width: 220, - }); - this.password.on('change', this.onFieldChange, this); - - this.proxy_host_resolve = this.add({ - xtype: 'checkbox', - name: 'proxy_host_resolve', - fieldLabel: '', - boxLabel: _('Proxy Hostnames'), - width: 220, - }); - this.proxy_host_resolve.on('change', this.onFieldChange, this); - - this.proxy_peer_conn = this.add({ - xtype: 'checkbox', - name: 'proxy_peer_conn', - fieldLabel: '', - boxLabel: _('Proxy Peers'), - width: 220, - }); - this.proxy_peer_conn.on('change', this.onFieldChange, this); - - this.proxy_tracker_conn = this.add({ - xtype: 'checkbox', - name: 'proxy_tracker_conn', - fieldLabel: '', - boxLabel: _('Proxy Trackers'), - width: 220, - }); - this.proxy_tracker_conn.on('change', this.onFieldChange, this); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Force Proxy'), - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - style: 'padding-left: 0px; margin-top: 10px', - }); - - this.force_proxy = fieldset.add({ - fieldLabel: '', - labelSeparator: '', - height: 20, - name: 'force_proxy', - boxLabel: _('Force Use of Proxy'), - }); - this.force_proxy.on('change', this.onFieldChange, this); - - this.anonymous_mode = fieldset.add({ - fieldLabel: '', - labelSeparator: '', - height: 20, - name: 'anonymous_mode', - boxLabel: _('Hide Client Identity'), - }); - this.anonymous_mode.on('change', this.onFieldChange, this); - - this.setting = false; - }, - - getName: function () { - return this.initialConfig.name; - }, - - getValue: function () { - return { - type: this.proxyType.getValue(), - hostname: this.hostname.getValue(), - port: Number(this.port.getValue()), - username: this.username.getValue(), - password: this.password.getValue(), - proxy_hostnames: this.proxy_host_resolve.getValue(), - proxy_peer_connections: this.proxy_peer_conn.getValue(), - proxy_tracker_connections: this.proxy_tracker_conn.getValue(), - force_proxy: this.force_proxy.getValue(), - anonymous_mode: this.anonymous_mode.getValue(), - }; - }, - - // Set the values of the proxies - setValue: function (value) { - this.setting = true; - this.proxyType.setValue(value['type']); - var index = this.proxyType.getStore().find('id', value['type']); - var record = this.proxyType.getStore().getAt(index); - - this.hostname.setValue(value['hostname']); - this.port.setValue(value['port']); - this.username.setValue(value['username']); - this.password.setValue(value['password']); - this.proxy_host_resolve.setValue(value['proxy_hostnames']); - this.proxy_peer_conn.setValue(value['proxy_peer_connections']); - this.proxy_tracker_conn.setValue(value['proxy_tracker_connections']); - this.force_proxy.setValue(value['force_proxy']); - this.anonymous_mode.setValue(value['anonymous_mode']); - - this.onTypeSelect(this.type, record, index); - this.setting = false; - }, - - onFieldChange: function (field, newValue, oldValue) { - if (this.setting) return; - var newValues = this.getValue(); - var oldValues = Ext.apply({}, newValues); - oldValues[field.getName()] = oldValue; - - this.fireEvent('change', this, newValues, oldValues); - }, - - onTypeSelect: function (combo, record, index) { - var typeId = record.get('id'); - if (typeId > 0) { - this.hostname.show(); - this.port.show(); - this.proxy_peer_conn.show(); - this.proxy_tracker_conn.show(); - if (typeId > 1 && typeId < 6) { - this.proxy_host_resolve.show(); - } else { - this.proxy_host_resolve.hide(); - } - } else { - this.hostname.hide(); - this.port.hide(); - this.proxy_host_resolve.hide(); - this.proxy_peer_conn.hide(); - this.proxy_tracker_conn.hide(); - } - - if (typeId == 3 || typeId == 5) { - this.username.show(); - this.password.show(); - } else { - this.username.hide(); - this.password.hide(); - } - }, -}); -/** - * Deluge.preferences.ProxyPage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Proxy - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Proxy = Ext.extend(Ext.form.FormPanel, { - constructor: function (config) { - config = Ext.apply( - { - border: false, - title: _('Proxy'), - header: false, - layout: 'form', - autoScroll: true, - }, - config - ); - Deluge.preferences.Proxy.superclass.constructor.call(this, config); - }, - - initComponent: function () { - Deluge.preferences.Proxy.superclass.initComponent.call(this); - this.proxy = this.add( - new Deluge.preferences.ProxyField({ - title: _('Proxy'), - name: 'proxy', - }) - ); - this.proxy.on('change', this.onProxyChange, this); - deluge.preferences.getOptionsManager().bind('proxy', this.proxy); - }, - - getValue: function () { - return { - proxy: this.proxy.getValue(), - }; - }, - - setValue: function (value) { - for (var proxy in value) { - this[proxy].setValue(value[proxy]); - } - }, - - onProxyChange: function (field, newValue, oldValue) { - var newValues = this.getValue(); - var oldValues = Ext.apply({}, newValues); - oldValues[field.getName()] = oldValue; - - this.fireEvent('change', this, newValues, oldValues); - }, -}); -/** - * Deluge.preferences.QueuePage.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. - */ -Ext.namespace('Deluge.preferences'); - -/** - * @class Deluge.preferences.Queue - * @extends Ext.form.FormPanel - */ -Deluge.preferences.Queue = Ext.extend(Ext.form.FormPanel, { - border: false, - title: _('Queue'), - header: false, - layout: 'form', - - initComponent: function () { - Deluge.preferences.Queue.superclass.initComponent.call(this); - - var om = deluge.preferences.getOptionsManager(); - - var fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('New Torrents'), - style: 'padding-top: 5px; margin-bottom: 0px;', - autoHeight: true, - labelWidth: 1, - defaultType: 'checkbox', - }); - om.bind( - 'queue_new_to_top', - fieldset.add({ - fieldLabel: '', - labelSeparator: '', - height: 22, - boxLabel: _('Queue to top'), - name: 'queue_new_to_top', - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Active Torrents'), - autoHeight: true, - labelWidth: 150, - defaultType: 'spinnerfield', - style: 'padding-top: 5px; margin-bottom: 0px', - }); - om.bind( - 'max_active_limit', - fieldset.add({ - fieldLabel: _('Total:'), - labelSeparator: '', - name: 'max_active_limit', - value: 8, - width: 80, - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }) - ); - om.bind( - 'max_active_downloading', - fieldset.add({ - fieldLabel: _('Downloading:'), - labelSeparator: '', - name: 'max_active_downloading', - value: 3, - width: 80, - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }) - ); - om.bind( - 'max_active_seeding', - fieldset.add({ - fieldLabel: _('Seeding:'), - labelSeparator: '', - name: 'max_active_seeding', - value: 5, - width: 80, - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }) - ); - om.bind( - 'dont_count_slow_torrents', - fieldset.add({ - xtype: 'checkbox', - name: 'dont_count_slow_torrents', - height: 22, - hideLabel: true, - boxLabel: _('Ignore slow torrents'), - }) - ); - om.bind( - 'auto_manage_prefer_seeds', - fieldset.add({ - xtype: 'checkbox', - name: 'auto_manage_prefer_seeds', - hideLabel: true, - boxLabel: _('Prefer seeding torrents'), - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - title: _('Seeding Rotation'), - autoHeight: true, - labelWidth: 150, - defaultType: 'spinnerfield', - style: 'padding-top: 5px; margin-bottom: 0px', - }); - om.bind( - 'share_ratio_limit', - fieldset.add({ - fieldLabel: _('Share Ratio:'), - labelSeparator: '', - name: 'share_ratio_limit', - value: 8, - width: 80, - incrementValue: 0.1, - minValue: -1, - maxValue: 99999, - alternateIncrementValue: 1, - decimalPrecision: 2, - }) - ); - om.bind( - 'seed_time_ratio_limit', - fieldset.add({ - fieldLabel: _('Time Ratio:'), - labelSeparator: '', - name: 'seed_time_ratio_limit', - value: 3, - width: 80, - incrementValue: 0.1, - minValue: -1, - maxValue: 99999, - alternateIncrementValue: 1, - decimalPrecision: 2, - }) - ); - om.bind( - 'seed_time_limit', - fieldset.add({ - fieldLabel: _('Time (m):'), - labelSeparator: '', - name: 'seed_time_limit', - value: 5, - width: 80, - decimalPrecision: 0, - minValue: -1, - maxValue: 99999, - }) - ); - - fieldset = this.add({ - xtype: 'fieldset', - border: false, - autoHeight: true, - style: 'padding-top: 5px; margin-bottom: 0px', - title: _('Share Ratio Reached'), - - layout: 'table', - layoutConfig: { columns: 2 }, - labelWidth: 0, - defaultType: 'checkbox', - - defaults: { - fieldLabel: '', - labelSeparator: '', - }, - }); - this.stopAtRatio = fieldset.add({ - name: 'stop_seed_at_ratio', - boxLabel: _('Share Ratio:'), - }); - this.stopAtRatio.on('check', this.onStopRatioCheck, this); - om.bind('stop_seed_at_ratio', this.stopAtRatio); - - this.stopRatio = fieldset.add({ - xtype: 'spinnerfield', - name: 'stop_seed_ratio', - ctCls: 'x-deluge-indent-checkbox', - disabled: true, - value: '2.0', - width: 60, - incrementValue: 0.1, - minValue: -1, - maxValue: 99999, - alternateIncrementValue: 1, - decimalPrecision: 2, - }); - om.bind('stop_seed_ratio', this.stopRatio); - - this.removeAtRatio = fieldset.add({ - xtype: 'radiogroup', - columns: 1, - colspan: 2, - disabled: true, - style: 'margin-left: 10px', - items: [ - { - boxLabel: _('Pause torrent'), - name: 'at_ratio', - inputValue: false, - checked: true, - }, - { - boxLabel: _('Remove torrent'), - name: 'at_ratio', - inputValue: true, - }, - ], - }); - om.bind('remove_seed_at_ratio', this.removeAtRatio); - }, - - onStopRatioCheck: function (e, checked) { - this.stopRatio.setDisabled(!checked); - this.removeAtRatio.setDisabled(!checked); - }, -}); -/** - * Deluge.StatusbarMenu.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. - */ -Ext.ns('Deluge'); - -/** - * Menu that handles setting the statusbar limits correctly. - * @class Deluge.StatusbarMenu - * @extends Ext.menu.Menu - */ -Deluge.StatusbarMenu = Ext.extend(Ext.menu.Menu, { - initComponent: function () { - Deluge.StatusbarMenu.superclass.initComponent.call(this); - this.otherWin = new Deluge.OtherLimitWindow( - this.initialConfig.otherWin || {} - ); - - this.items.each(function (item) { - if (item.getXType() != 'menucheckitem') return; - if (item.value == 'other') { - item.on('click', this.onOtherClicked, this); - } else { - item.on('checkchange', this.onLimitChanged, this); - } - }, this); - }, - - setValue: function (value) { - var beenSet = false; - // set the new value - this.value = value = value == 0 ? -1 : value; - - var other = null; - // uncheck all items - this.items.each(function (item) { - if (item.setChecked) { - item.suspendEvents(); - if (item.value == value) { - item.setChecked(true); - beenSet = true; - } else { - item.setChecked(false); - } - item.resumeEvents(); - } - - if (item.value == 'other') other = item; - }); - - if (beenSet) return; - - other.suspendEvents(); - other.setChecked(true); - other.resumeEvents(); - }, - - onLimitChanged: function (item, checked) { - if (!checked || item.value == 'other') return; // We do not care about unchecked or other. - var config = {}; - config[item.group] = item.value; - deluge.client.core.set_config(config, { - success: function () { - deluge.ui.update(); - }, - }); - }, - - onOtherClicked: function (item, e) { - this.otherWin.group = item.group; - this.otherWin.setValue(this.value); - this.otherWin.show(); - }, -}); -/** - * Deluge.OptionsManager.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. - */ -Ext.namespace('Deluge'); - -/** - * @class Deluge.OptionsManager - * @extends Ext.util.Observable - * A class that can be used to manage options throughout the ui. - * @constructor - * Creates a new OptionsManager - * @param {Object} config Configuration options - */ -Deluge.OptionsManager = Ext.extend(Ext.util.Observable, { - constructor: function (config) { - config = config || {}; - this.binds = {}; - this.changed = {}; - this.options = (config && config['options']) || {}; - this.focused = null; - - this.addEvents({ - /** - * @event add - * Fires when an option is added - */ - add: true, - - /** - * @event changed - * Fires when an option is changed - * @param {String} option The changed option - * @param {Mixed} value The options new value - * @param {Mixed} oldValue The options old value - */ - changed: true, - - /** - * @event reset - * Fires when the options are reset - */ - reset: true, - }); - this.on('changed', this.onChange, this); - - Deluge.OptionsManager.superclass.constructor.call(this); - }, - - /** - * Add a set of default options and values to the options manager - * @param {Object} options The default options. - */ - addOptions: function (options) { - this.options = Ext.applyIf(this.options, options); - }, - - /** - * Binds a form field to the specified option. - * @param {String} option - * @param {Ext.form.Field} field - */ - bind: function (option, field) { - this.binds[option] = this.binds[option] || []; - this.binds[option].push(field); - field._doption = option; - - field.on('focus', this.onFieldFocus, this); - field.on('blur', this.onFieldBlur, this); - field.on('change', this.onFieldChange, this); - field.on('check', this.onFieldChange, this); - field.on('spin', this.onFieldChange, this); - return field; - }, - - /** - * Changes all the changed values to be the default values - */ - commit: function () { - this.options = Ext.apply(this.options, this.changed); - this.reset(); - }, - - /** - * Converts the value so it matches the originals type - * @param {Mixed} oldValue The original value - * @param {Mixed} value The new value to convert - */ - convertValueType: function (oldValue, value) { - if (Ext.type(oldValue) != Ext.type(value)) { - switch (Ext.type(oldValue)) { - case 'string': - value = String(value); - break; - case 'number': - value = Number(value); - break; - case 'boolean': - if (Ext.type(value) == 'string') { - value = value.toLowerCase(); - value = - value == 'true' || value == '1' || value == 'on' - ? true - : false; - } else { - value = Boolean(value); - } - break; - } - } - return value; - }, - - /** - * Get the value for an option or options. - * @param {String} [option] A single option or an array of options to return. - * @returns {Object} the options value. - */ - get: function () { - if (arguments.length == 1) { - var option = arguments[0]; - return this.isDirty(option) - ? this.changed[option] - : this.options[option]; - } else { - var options = {}; - Ext.each( - arguments, - function (option) { - if (!this.has(option)) return; - options[option] = this.isDirty(option) - ? this.changed[option] - : this.options[option]; - }, - this - ); - return options; - } - }, - - /** - * Get the default value for an option or options. - * @param {String|Array} [option] A single option or an array of options to return. - * @returns {Object} the value of the option - */ - getDefault: function (option) { - return this.options[option]; - }, - - /** - * Returns the dirty (changed) values. - * @returns {Object} the changed options - */ - getDirty: function () { - return this.changed; - }, - - /** - * @param {String} [option] The option to check - * @returns {Boolean} true if the option has been changed from the default. - */ - isDirty: function (option) { - return !Ext.isEmpty(this.changed[option]); - }, - - /** - * Check to see if an option exists in the options manager - * @param {String} option - * @returns {Boolean} true if the option exists, else false. - */ - has: function (option) { - return this.options[option]; - }, - - /** - * Reset the options back to the default values. - */ - reset: function () { - this.changed = {}; - }, - - /** - * Sets the value of specified option(s) for the passed in id. - * @param {String} option - * @param {Object} value The value for the option - */ - set: function (option, value) { - if (option === undefined) { - return; - } else if (typeof option == 'object') { - var options = option; - this.options = Ext.apply(this.options, options); - for (var option in options) { - this.onChange(option, options[option]); - } - } else { - this.options[option] = value; - this.onChange(option, value); - } - }, - - /** - * Update the value for the specified option and id. - * @param {String/Object} option or options to update - * @param {Object} [value]; - */ - update: function (option, value) { - if (option === undefined) { - return; - } else if (value === undefined) { - for (var key in option) { - this.update(key, option[key]); - } - } else { - var defaultValue = this.getDefault(option); - value = this.convertValueType(defaultValue, value); - - var oldValue = this.get(option); - if (oldValue == value) return; - - if (defaultValue == value) { - if (this.isDirty(option)) delete this.changed[option]; - this.fireEvent('changed', option, value, oldValue); - return; - } - - this.changed[option] = value; - this.fireEvent('changed', option, value, oldValue); - } - }, - - /** - * Lets the option manager know when a field is blurred so if a value - * so value changing operations can continue on that field. - */ - onFieldBlur: function (field, event) { - if (this.focused == field) { - this.focused = null; - } - }, - - /** - * Stops a form fields value from being blocked by the change functions - * @param {Ext.form.Field} field - * @private - */ - onFieldChange: function (field, event) { - if (field.field) field = field.field; // fix for spinners - this.update(field._doption, field.getValue()); - }, - - /** - * Lets the option manager know when a field is focused so if a value changing - * operation is performed it will not change the value of the field. - */ - onFieldFocus: function (field, event) { - this.focused = field; - }, - - onChange: function (option, newValue, oldValue) { - // If we don't have a bind there's nothing to do. - if (Ext.isEmpty(this.binds[option])) return; - Ext.each( - this.binds[option], - function (bind) { - // The field is currently focused so we do not want to change it. - if (bind == this.focused) return; - // Set the form field to the new value. - bind.setValue(newValue); - }, - this - ); - }, -}); -/** - * Deluge.AboutWindow.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. - */ - -Ext.namespace('Deluge.about'); - -/** - * @class Deluge.about.AboutWindow - * @extends Ext.Window - */ -Deluge.about.AboutWindow = Ext.extend(Ext.Window, { - id: 'AboutWindow', - title: _('About Deluge'), - height: 330, - width: 270, - iconCls: 'x-deluge-main-panel', - resizable: false, - plain: true, - layout: { - type: 'vbox', - align: 'center', - }, - buttonAlign: 'center', - - initComponent: function () { - Deluge.about.AboutWindow.superclass.initComponent.call(this); - this.addEvents({ - build_ready: true, - }); - - var self = this; - var libtorrent = function () { - deluge.client.core.get_libtorrent_version({ - success: function (lt_version) { - comment += '<br/>' + _('libtorrent:') + ' ' + lt_version; - Ext.getCmp('about_comment').setText(comment, false); - self.fireEvent('build_ready'); - }, - }); - }; - - var client_version = deluge.version; - - var comment = - _( - 'A peer-to-peer file sharing program\nutilizing the BitTorrent protocol.' - ).replace('\n', '<br/>') + - '<br/><br/>' + - _('Client:') + - ' ' + - client_version + - '<br/>'; - deluge.client.web.connected({ - success: function (connected) { - if (connected) { - deluge.client.daemon.get_version({ - success: function (server_version) { - comment += - _('Server:') + ' ' + server_version + '<br/>'; - libtorrent(); - }, - }); - } else { - this.fireEvent('build_ready'); - } - }, - failure: function () { - this.fireEvent('build_ready'); - }, - scope: this, - }); - - this.add([ - { - xtype: 'box', - style: 'padding-top: 5px', - height: 80, - width: 240, - cls: 'x-deluge-logo', - hideLabel: true, - }, - { - xtype: 'label', - style: 'padding-top: 10px; font-weight: bold; font-size: 16px;', - text: _('Deluge') + ' ' + client_version, - }, - { - xtype: 'label', - id: 'about_comment', - style: 'padding-top: 10px; text-align:center; font-size: 12px;', - html: comment, - }, - { - xtype: 'label', - style: 'padding-top: 10px; font-size: 10px;', - text: _('Copyright 2007-2018 Deluge Team'), - }, - { - xtype: 'label', - style: 'padding-top: 5px; font-size: 12px;', - html: '<a href="https://deluge-torrent.org" target="_blank">deluge-torrent.org</a>', - }, - ]); - this.addButton(_('Close'), this.onCloseClick, this); - }, - - show: function () { - this.on('build_ready', function () { - Deluge.about.AboutWindow.superclass.show.call(this); - }); - }, - - onCloseClick: function () { - this.close(); - }, -}); - -Ext.namespace('Deluge'); - -Deluge.About = function () { - new Deluge.about.AboutWindow().show(); -}; -/** - * Deluge.AddConnectionWindow.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. - */ -Ext.ns('Deluge'); - -/** - * @class Deluge.AddConnectionWindow - * @extends Ext.Window - */ -Deluge.AddConnectionWindow = Ext.extend(Ext.Window, { - title: _('Add Connection'), - iconCls: 'x-deluge-add-window-icon', - - layout: 'fit', - width: 300, - height: 195, - constrainHeader: true, - bodyStyle: 'padding: 10px 5px;', - closeAction: 'hide', - - initComponent: function () { - Deluge.AddConnectionWindow.superclass.initComponent.call(this); - - this.addEvents('hostadded'); - - this.addButton(_('Close'), this.hide, this); - this.addButton(_('Add'), this.onAddClick, this); - - this.on('hide', this.onHide, this); - - this.form = this.add({ - xtype: 'form', - defaultType: 'textfield', - baseCls: 'x-plain', - labelWidth: 60, - items: [ - { - fieldLabel: _('Host:'), - labelSeparator: '', - name: 'host', - anchor: '75%', - value: '', - }, - { - xtype: 'spinnerfield', - fieldLabel: _('Port:'), - labelSeparator: '', - name: 'port', - strategy: { - xtype: 'number', - decimalPrecision: 0, - minValue: -1, - maxValue: 65535, - }, - value: '58846', - anchor: '40%', - }, - { - fieldLabel: _('Username:'), - labelSeparator: '', - name: 'username', - anchor: '75%', - value: '', - }, - { - fieldLabel: _('Password:'), - labelSeparator: '', - anchor: '75%', - name: 'password', - inputType: 'password', - value: '', - }, - ], - }); - }, - - onAddClick: function () { - var values = this.form.getForm().getValues(); - deluge.client.web.add_host( - values.host, - Number(values.port), - values.username, - values.password, - { - success: function (result) { - if (!result[0]) { - Ext.MessageBox.show({ - title: _('Error'), - msg: String.format( - _('Unable to add host: {0}'), - result[1] - ), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - } else { - this.fireEvent('hostadded'); - } - this.hide(); - }, - scope: this, - } - ); - }, - - onHide: function () { - this.form.getForm().reset(); - }, -}); -/** - * Deluge.AddTrackerWindow.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. - */ -Ext.ns('Deluge'); - -// Custom VType validator for tracker urls -var trackerUrlTest = - /(((^https?)|(^udp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i; -Ext.apply(Ext.form.VTypes, { - trackerUrl: function (val, field) { - return trackerUrlTest.test(val); - }, - trackerUrlText: 'Not a valid tracker url', -}); - -/** - * @class Deluge.AddTrackerWindow - * @extends Ext.Window - */ -Deluge.AddTrackerWindow = Ext.extend(Ext.Window, { - title: _('Add Tracker'), - layout: 'fit', - width: 375, - height: 150, - plain: true, - closable: true, - resizable: false, - constrainHeader: true, - bodyStyle: 'padding: 5px', - buttonAlign: 'right', - closeAction: 'hide', - iconCls: 'x-deluge-edit-trackers', - - initComponent: function () { - Deluge.AddTrackerWindow.superclass.initComponent.call(this); - - this.addButton(_('Cancel'), this.onCancelClick, this); - this.addButton(_('Add'), this.onAddClick, this); - this.addEvents('add'); - - this.form = this.add({ - xtype: 'form', - defaultType: 'textarea', - baseCls: 'x-plain', - labelWidth: 55, - items: [ - { - fieldLabel: _('Trackers:'), - labelSeparator: '', - name: 'trackers', - anchor: '100%', - }, - ], - }); - }, - - onAddClick: function () { - var trackers = this.form.getForm().findField('trackers').getValue(); - trackers = trackers.split('\n'); - - var cleaned = []; - Ext.each( - trackers, - function (tracker) { - if (Ext.form.VTypes.trackerUrl(tracker)) { - cleaned.push(tracker); - } - }, - this - ); - this.fireEvent('add', cleaned); - this.hide(); - this.form.getForm().findField('trackers').setValue(''); - }, - - onCancelClick: function () { - this.form.getForm().findField('trackers').setValue(''); - this.hide(); - }, -}); -/** - * Deluge.Client.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. - */ -Ext.namespace('Ext.ux.util'); - -/** - * A class that connects to a json-rpc resource and adds the available - * methods as functions to the class instance. - * @class Ext.ux.util.RpcClient - * @namespace Ext.ux.util - */ -Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, { - _components: [], - - _methods: [], - - _requests: {}, - - _url: null, - - _optionKeys: ['scope', 'success', 'failure'], - - /** - * @event connected - * Fires when the client has retrieved the list of methods from the server. - * @param {Ext.ux.util.RpcClient} this - */ - constructor: function (config) { - Ext.ux.util.RpcClient.superclass.constructor.call(this, config); - this._url = config.url || null; - this._id = 0; - - this.addEvents( - // raw events - 'connected', - 'error' - ); - this.reloadMethods(); - }, - - reloadMethods: function () { - this._execute('system.listMethods', { - success: this._setMethods, - scope: this, - }); - }, - - _execute: function (method, options) { - options = options || {}; - options.params = options.params || []; - options.id = this._id; - - var request = Ext.encode({ - method: method, - params: options.params, - id: options.id, - }); - this._id++; - - return Ext.Ajax.request({ - url: this._url, - method: 'POST', - success: this._onSuccess, - failure: this._onFailure, - scope: this, - jsonData: request, - options: options, - }); - }, - - _onFailure: function (response, requestOptions) { - var options = requestOptions.options; - errorObj = { - id: options.id, - result: null, - error: { - msg: 'HTTP: ' + response.status + ' ' + response.statusText, - code: 255, - }, - }; - - this.fireEvent('error', errorObj, response, requestOptions); - - if (Ext.type(options.failure) != 'function') return; - if (options.scope) { - options.failure.call( - options.scope, - errorObj, - response, - requestOptions - ); - } else { - options.failure(errorObj, response, requestOptions); - } - }, - - _onSuccess: function (response, requestOptions) { - var responseObj = Ext.decode(response.responseText); - var options = requestOptions.options; - if (responseObj.error) { - this.fireEvent('error', responseObj, response, requestOptions); - - if (Ext.type(options.failure) != 'function') return; - if (options.scope) { - options.failure.call( - options.scope, - responseObj, - response, - requestOptions - ); - } else { - options.failure(responseObj, response, requestOptions); - } - } else { - if (Ext.type(options.success) != 'function') return; - if (options.scope) { - options.success.call( - options.scope, - responseObj.result, - responseObj, - response, - requestOptions - ); - } else { - options.success( - responseObj.result, - responseObj, - response, - requestOptions - ); - } - } - }, - - _parseArgs: function (args) { - var params = []; - Ext.each(args, function (arg) { - params.push(arg); - }); - - var options = params[params.length - 1]; - if (Ext.type(options) == 'object') { - var keys = Ext.keys(options), - isOption = false; - - Ext.each(this._optionKeys, function (key) { - if (keys.indexOf(key) > -1) isOption = true; - }); - - if (isOption) { - params.remove(options); - } else { - options = {}; - } - } else { - options = {}; - } - options.params = params; - return options; - }, - - _setMethods: function (methods) { - var components = {}, - self = this; - - Ext.each(methods, function (method) { - var parts = method.split('.'); - var component = components[parts[0]] || {}; - - var fn = function () { - var options = self._parseArgs(arguments); - return self._execute(method, options); - }; - component[parts[1]] = fn; - components[parts[0]] = component; - }); - - for (var name in components) { - self[name] = components[name]; - } - Ext.each( - this._components, - function (component) { - if (!component in components) { - delete this[component]; - } - }, - this - ); - this._components = Ext.keys(components); - this.fireEvent('connected', this); - }, -}); -/** - * Deluge.ConnectionManager.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. - */ - -Deluge.ConnectionManager = Ext.extend(Ext.Window, { - layout: 'fit', - width: 300, - height: 220, - bodyStyle: 'padding: 10px 5px;', - buttonAlign: 'right', - closeAction: 'hide', - closable: true, - plain: true, - constrainHeader: true, - title: _('Connection Manager'), - iconCls: 'x-deluge-connect-window-icon', - - initComponent: function () { - Deluge.ConnectionManager.superclass.initComponent.call(this); - this.on('hide', this.onHide, this); - this.on('show', this.onShow, this); - - deluge.events.on('login', this.onLogin, this); - deluge.events.on('logout', this.onLogout, this); - - this.addButton(_('Close'), this.onClose, this); - this.addButton(_('Connect'), this.onConnect, this); - - this.list = new Ext.list.ListView({ - store: new Ext.data.ArrayStore({ - fields: [ - { name: 'status', mapping: 4 }, - { name: 'host', mapping: 1 }, - { name: 'port', mapping: 2 }, - { name: 'user', mapping: 3 }, - { name: 'version', mapping: 5 }, - ], - id: 0, - }), - columns: [ - { - header: _('Status'), - width: 0.24, - sortable: true, - tpl: new Ext.XTemplate( - '<tpl if="status == \'Online\'">', - _('Online'), - '</tpl>', - '<tpl if="status == \'Offline\'">', - _('Offline'), - '</tpl>', - '<tpl if="status == \'Connected\'">', - _('Connected'), - '</tpl>' - ), - dataIndex: 'status', - }, - { - id: 'host', - header: _('Host'), - width: 0.51, - sortable: true, - tpl: '{user}@{host}:{port}', - dataIndex: 'host', - }, - { - header: _('Version'), - width: 0.25, - sortable: true, - tpl: '<tpl if="version">{version}</tpl>', - dataIndex: 'version', - }, - ], - singleSelect: true, - listeners: { - selectionchange: { fn: this.onSelectionChanged, scope: this }, - }, - }); - - this.panel = this.add({ - autoScroll: true, - items: [this.list], - bbar: new Ext.Toolbar({ - buttons: [ - { - id: 'cm-add', - cls: 'x-btn-text-icon', - text: _('Add'), - iconCls: 'icon-add', - handler: this.onAddClick, - scope: this, - }, - { - id: 'cm-edit', - cls: 'x-btn-text-icon', - text: _('Edit'), - iconCls: 'icon-edit', - handler: this.onEditClick, - scope: this, - }, - { - id: 'cm-remove', - cls: 'x-btn-text-icon', - text: _('Remove'), - iconCls: 'icon-remove', - handler: this.onRemoveClick, - disabled: true, - scope: this, - }, - '->', - { - id: 'cm-stop', - cls: 'x-btn-text-icon', - text: _('Stop Daemon'), - iconCls: 'icon-error', - handler: this.onStopClick, - disabled: true, - scope: this, - }, - ], - }), - }); - this.update = this.update.createDelegate(this); - }, - - /** - * Check to see if the the web interface is currently connected - * to a Deluge Daemon and show the Connection Manager if not. - */ - checkConnected: function () { - deluge.client.web.connected({ - success: function (connected) { - if (connected) { - deluge.events.fire('connect'); - } else { - this.show(); - } - }, - scope: this, - }); - }, - - disconnect: function (show) { - deluge.events.fire('disconnect'); - if (show) { - if (this.isVisible()) return; - this.show(); - } - }, - - loadHosts: function () { - deluge.client.web.get_hosts({ - success: this.onGetHosts, - scope: this, - }); - }, - - update: function () { - this.list.getStore().each(function (r) { - deluge.client.web.get_host_status(r.id, { - success: this.onGetHostStatus, - scope: this, - }); - }, this); - }, - - /** - * Updates the buttons in the Connection Manager UI according to the - * passed in records host state. - * @param {Ext.data.Record} record The hosts record to update the UI for - */ - updateButtons: function (record) { - var button = this.buttons[1], - status = record.get('status'); - - // Update the Connect/Disconnect button - button.enable(); - if (status.toLowerCase() == 'connected') { - button.setText(_('Disconnect')); - } else { - button.setText(_('Connect')); - if (status.toLowerCase() != 'online') button.disable(); - } - - // Update the Stop/Start Daemon button - if ( - status.toLowerCase() == 'connected' || - status.toLowerCase() == 'online' - ) { - this.stopHostButton.enable(); - this.stopHostButton.setText(_('Stop Daemon')); - } else { - if ( - record.get('host') == '127.0.0.1' || - record.get('host') == 'localhost' - ) { - this.stopHostButton.enable(); - this.stopHostButton.setText(_('Start Daemon')); - } else { - this.stopHostButton.disable(); - } - } - }, - - // private - onAddClick: function (button, e) { - if (!this.addWindow) { - this.addWindow = new Deluge.AddConnectionWindow(); - this.addWindow.on('hostadded', this.onHostChange, this); - } - this.addWindow.show(); - }, - - // private - onEditClick: function (button, e) { - var connection = this.list.getSelectedRecords()[0]; - if (!connection) return; - - if (!this.editWindow) { - this.editWindow = new Deluge.EditConnectionWindow(); - this.editWindow.on('hostedited', this.onHostChange, this); - } - this.editWindow.show(connection); - }, - - // private - onHostChange: function () { - this.loadHosts(); - }, - - // private - onClose: function (e) { - this.hide(); - }, - - // private - onConnect: function (e) { - var selected = this.list.getSelectedRecords()[0]; - if (!selected) return; - - var me = this; - var disconnect = function () { - deluge.client.web.disconnect({ - success: function (result) { - this.update(this); - deluge.events.fire('disconnect'); - }, - scope: me, - }); - }; - - if (selected.get('status').toLowerCase() == 'connected') { - disconnect(); - } else { - if ( - this.list - .getStore() - .find('status', 'Connected', 0, false, false) > -1 - ) { - disconnect(); - } - - var id = selected.id; - deluge.client.web.connect(id, { - success: function (methods) { - deluge.client.reloadMethods(); - deluge.client.on( - 'connected', - function (e) { - deluge.events.fire('connect'); - }, - this, - { single: true } - ); - }, - }); - this.hide(); - } - }, - - // private - onGetHosts: function (hosts) { - this.list.getStore().loadData(hosts); - Ext.each( - hosts, - function (host) { - deluge.client.web.get_host_status(host[0], { - success: this.onGetHostStatus, - scope: this, - }); - }, - this - ); - }, - - // private - onGetHostStatus: function (host) { - var record = this.list.getStore().getById(host[0]); - record.set('status', host[1]); - record.set('version', host[2]); - record.commit(); - var selected = this.list.getSelectedRecords()[0]; - if (!selected) return; - if (selected == record) this.updateButtons(record); - }, - - // private - onHide: function () { - if (this.running) window.clearInterval(this.running); - }, - - // private - onLogin: function () { - if (deluge.config.first_login) { - Ext.MessageBox.confirm( - _('Change Default Password'), - _( - 'We recommend changing the default password.<br><br>Would you like to change it now?' - ), - function (res) { - this.checkConnected(); - if (res == 'yes') { - deluge.preferences.show(); - deluge.preferences.selectPage('Interface'); - } - deluge.client.web.set_config({ first_login: false }); - }, - this - ); - } else { - this.checkConnected(); - } - }, - - // private - onLogout: function () { - this.disconnect(); - if (!this.hidden && this.rendered) { - this.hide(); - } - }, - - // private - onRemoveClick: function (button) { - var connection = this.list.getSelectedRecords()[0]; - if (!connection) return; - - deluge.client.web.remove_host(connection.id, { - success: function (result) { - if (!result) { - Ext.MessageBox.show({ - title: _('Error'), - msg: result[1], - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - } else { - this.list.getStore().remove(connection); - } - }, - scope: this, - }); - }, - - // private - onSelectionChanged: function (list, selections) { - if (selections[0]) { - this.editHostButton.enable(); - this.removeHostButton.enable(); - this.stopHostButton.enable(); - this.stopHostButton.setText(_('Stop Daemon')); - this.updateButtons(this.list.getRecord(selections[0])); - } else { - this.editHostButton.disable(); - this.removeHostButton.disable(); - this.stopHostButton.disable(); - } - }, - - // FIXME: Find out why this is being fired twice - // private - onShow: function () { - if (!this.addHostButton) { - var bbar = this.panel.getBottomToolbar(); - this.addHostButton = bbar.items.get('cm-add'); - this.editHostButton = bbar.items.get('cm-edit'); - this.removeHostButton = bbar.items.get('cm-remove'); - this.stopHostButton = bbar.items.get('cm-stop'); - } - this.loadHosts(); - if (this.running) return; - this.running = window.setInterval(this.update, 2000, this); - }, - - // private - onStopClick: function (button, e) { - var connection = this.list.getSelectedRecords()[0]; - if (!connection) return; - - if (connection.get('status') == 'Offline') { - // This means we need to start the daemon - deluge.client.web.start_daemon(connection.get('port')); - } else { - // This means we need to stop the daemon - deluge.client.web.stop_daemon(connection.id, { - success: function (result) { - if (!result[0]) { - Ext.MessageBox.show({ - title: _('Error'), - msg: result[1], - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - } - }, - }); - } - }, -}); -/* - * Deluge.CopyMagnet.js - * - * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, write to: - * The Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301, USA. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the OpenSSL - * library. - * You must obey the GNU General Public License in all respects for all of - * the code used other than OpenSSL. If you modify file(s) with this - * exception, you may extend this exception to your version of the file(s), - * but you are not obligated to do so. If you do not wish to do so, delete - * this exception statement from your version. If you delete this exception - * statement from all source files in the program, then also delete it here. - */ -Deluge.CopyMagnet = Ext.extend(Ext.Window, { - title: _('Copy Magnet URI'), - width: 375, - closeAction: 'hide', - iconCls: 'icon-magnet-copy', - - initComponent: function () { - Deluge.CopyMagnet.superclass.initComponent.call(this); - form = this.add({ - xtype: 'form', - defaultType: 'textfield', - hideLabels: true, - }); - this.magnetURI = form.add({ - name: 'URI', - anchor: '100%', - }); - this.addButton(_('Close'), this.onClose, this); - this.addButton(_('Copy'), this.onCopy, this); - }, - show: function (a) { - Deluge.CopyMagnet.superclass.show.call(this); - var torrent = deluge.torrents.getSelected(); - deluge.client.core.get_magnet_uri(torrent.id, { - success: this.onRequestComplete, - scope: this, - }); - }, - onRequestComplete: function (uri) { - this.magnetURI.setValue(uri); - }, - onCopy: function () { - this.magnetURI.focus(); - this.magnetURI.el.dom.select(); - document.execCommand('copy'); - }, - onClose: function () { - this.hide(); - }, -}); - -deluge.copyMagnetWindow = new Deluge.CopyMagnet(); -/** - * Deluge.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. - */ - -// Setup the state manager -Ext.state.Manager.setProvider( - new Ext.state.CookieProvider({ - /** - * By default, cookies will expire after 7 days. Provide - * an expiry date 10 years in the future to approximate - * a cookie that does not expire. - */ - expires: new Date( - new Date().getTime() + 1000 * 60 * 60 * 24 * 365 * 10 - ), - }) -); - -// Add some additional functions to ext and setup some of the -// configurable parameters -Ext.apply(Ext, { - isObjectEmpty: function (obj) { - for (var i in obj) { - return false; - } - return true; - }, - - areObjectsEqual: function (obj1, obj2) { - var equal = true; - if (!obj1 || !obj2) return false; - for (var i in obj1) { - if (obj1[i] != obj2[i]) { - equal = false; - } - } - return equal; - }, - - keys: function (obj) { - var keys = []; - for (var i in obj) - if (obj.hasOwnProperty(i)) { - keys.push(i); - } - return keys; - }, - - values: function (obj) { - var values = []; - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - values.push(obj[i]); - } - } - return values; - }, - - splat: function (obj) { - var type = Ext.type(obj); - return type ? (type != 'array' ? [obj] : obj) : []; - }, -}); -Ext.getKeys = Ext.keys; -Ext.BLANK_IMAGE_URL = deluge.config.base + 'images/s.gif'; -Ext.USE_NATIVE_JSON = true; - -// Create the Deluge namespace -Ext.apply(Deluge, { - // private - pluginStore: {}, - - // private - progressTpl: - '<div class="x-progress-wrap x-progress-renderered">' + - '<div class="x-progress-inner">' + - '<div style="width: {2}px" class="x-progress-bar">' + - '<div style="z-index: 99; width: {3}px" class="x-progress-text">' + - '<div style="width: {1}px;">{0}</div>' + - '</div>' + - '</div>' + - '<div class="x-progress-text x-progress-text-back">' + - '<div style="width: {1}px;">{0}</div>' + - '</div>' + - '</div>' + - '</div>', - - /** - * A method to create a progress bar that can be used by renderers - * to display a bar within a grid or tree. - * @param {Number} progress The bars progress - * @param {Number} width The width of the bar - * @param {String} text The text to display on the bar - * @param {Number} modified Amount to subtract from the width allowing for fixes - */ - progressBar: function (progress, width, text, modifier) { - modifier = Ext.value(modifier, 10); - var progressWidth = ((width / 100.0) * progress).toFixed(0); - var barWidth = progressWidth - 1; - var textWidth = - progressWidth - modifier > 0 ? progressWidth - modifier : 0; - return String.format( - Deluge.progressTpl, - text, - width, - barWidth, - textWidth - ); - }, - - /** - * Constructs a new instance of the specified plugin. - * @param {String} name The plugin name to create - */ - createPlugin: function (name) { - return new Deluge.pluginStore[name](); - }, - - /** - * Check to see if a plugin has been registered. - * @param {String} name The plugin name to check - */ - hasPlugin: function (name) { - return Deluge.pluginStore[name] ? true : false; - }, - - /** - * Register a plugin with the Deluge interface. - * @param {String} name The plugin name to register - * @param {Plugin} plugin The plugin to register - */ - registerPlugin: function (name, plugin) { - Deluge.pluginStore[name] = plugin; - }, -}); - -// Setup a space for plugins to insert themselves -deluge.plugins = {}; - -// Hinting for gettext_gen.py -// _('Skip') -// _('Low') -// _('Normal') -// _('High') -// _('Mixed') -FILE_PRIORITY = { - 0: 'Skip', - 1: 'Low', - 2: 'Low', - 3: 'Low', - 4: 'Normal', - 5: 'High', - 6: 'High', - 7: 'High', - 9: 'Mixed', - Skip: 0, - Low: 1, - Normal: 4, - High: 7, - Mixed: 9, -}; - -FILE_PRIORITY_CSS = { - 0: 'x-no-download', - 1: 'x-low-download', - 2: 'x-low-download', - 3: 'x-low-download', - 4: 'x-normal-download', - 5: 'x-high-download', - 6: 'x-high-download', - 7: 'x-high-download', - 9: 'x-mixed-download', -}; -/** - * Deluge.EditConnectionWindow.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. - */ -Ext.ns('Deluge'); - -/** - * @class Deluge.EditConnectionWindow - * @extends Ext.Window - */ -Deluge.EditConnectionWindow = Ext.extend(Ext.Window, { - title: _('Edit Connection'), - iconCls: 'x-deluge-add-window-icon', - - layout: 'fit', - width: 300, - height: 195, - constrainHeader: true, - bodyStyle: 'padding: 10px 5px;', - closeAction: 'hide', - - initComponent: function () { - Deluge.EditConnectionWindow.superclass.initComponent.call(this); - - this.addEvents('hostedited'); - - this.addButton(_('Close'), this.hide, this); - this.addButton(_('Edit'), this.onEditClick, this); - - this.on('hide', this.onHide, this); - - this.form = this.add({ - xtype: 'form', - defaultType: 'textfield', - baseCls: 'x-plain', - labelWidth: 60, - items: [ - { - fieldLabel: _('Host:'), - labelSeparator: '', - name: 'host', - anchor: '75%', - value: '', - }, - { - xtype: 'spinnerfield', - fieldLabel: _('Port:'), - labelSeparator: '', - name: 'port', - strategy: { - xtype: 'number', - decimalPrecision: 0, - minValue: 0, - maxValue: 65535, - }, - anchor: '40%', - value: 58846, - }, - { - fieldLabel: _('Username:'), - labelSeparator: '', - name: 'username', - anchor: '75%', - value: '', - }, - { - fieldLabel: _('Password:'), - labelSeparator: '', - anchor: '75%', - name: 'password', - inputType: 'password', - value: '', - }, - ], - }); - }, - - show: function (connection) { - Deluge.EditConnectionWindow.superclass.show.call(this); - - this.form.getForm().findField('host').setValue(connection.get('host')); - this.form.getForm().findField('port').setValue(connection.get('port')); - this.form - .getForm() - .findField('username') - .setValue(connection.get('user')); - this.host_id = connection.id; - }, - - onEditClick: function () { - var values = this.form.getForm().getValues(); - deluge.client.web.edit_host( - this.host_id, - values.host, - Number(values.port), - values.username, - values.password, - { - success: function (result) { - if (!result) { - console.log(result); - Ext.MessageBox.show({ - title: _('Error'), - msg: String.format(_('Unable to edit host')), - buttons: Ext.MessageBox.OK, - modal: false, - icon: Ext.MessageBox.ERROR, - iconCls: 'x-deluge-icon-error', - }); - } else { - this.fireEvent('hostedited'); - } - this.hide(); - }, - scope: this, - } - ); - }, - - onHide: function () { - this.form.getForm().reset(); - }, -}); -/** - * Deluge.EditTrackerWindow.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. - */ -Ext.ns('Deluge'); - -/** - * @class Deluge.EditTrackerWindow - * @extends Ext.Window - */ -Deluge.EditTrackerWindow = Ext.extend(Ext.Window, { - title: _('Edit Tracker'), - layout: 'fit', - width: 375, - height: 110, - plain: true, - closable: true, - resizable: false, - constrainHeader: true, - bodyStyle: 'padding: 5px', - buttonAlign: 'right', - closeAction: 'hide', - iconCls: 'x-deluge-edit-trackers', - - initComponent: function () { - Deluge.EditTrackerWindow.superclass.initComponent.call(this); - - this.addButton(_('Cancel'), this.onCancelClick, this); - this.addButton(_('Save'), this.onSaveClick, this); - this.on('hide', this.onHide, this); - - this.form = this.add({ - xtype: 'form', - defaultType: 'textfield', - baseCls: 'x-plain', - labelWidth: 55, - items: [ - { - fieldLabel: _('Tracker:'), - labelSeparator: '', - name: 'tracker', - anchor: '100%', - }, - ], - }); - }, - - show: function (record) { - Deluge.EditTrackerWindow.superclass.show.call(this); - - this.record = record; - this.form.getForm().findField('tracker').setValue(record.data['url']); - }, - - onCancelClick: function () { - this.hide(); - }, - - onHide: function () { - this.form.getForm().findField('tracker').setValue(''); - }, - - onSaveClick: function () { - var url = this.form.getForm().findField('tracker').getValue(); - this.record.set('url', url); - this.record.commit(); - this.hide(); - }, -}); -/** - * Deluge.EditTrackers.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. - */ -Ext.ns('Deluge'); - -/** - * @class Deluge.EditTrackersWindow - * @extends Ext.Window - */ -Deluge.EditTrackersWindow = Ext.extend(Ext.Window, { - title: _('Edit Trackers'), - layout: 'fit', - width: 350, - height: 220, - plain: true, - closable: true, - resizable: true, - constrainHeader: true, - - bodyStyle: 'padding: 5px', - buttonAlign: 'right', - closeAction: 'hide', - iconCls: 'x-deluge-edit-trackers', - - initComponent: function () { - Deluge.EditTrackersWindow.superclass.initComponent.call(this); - - this.addButton(_('Cancel'), this.onCancelClick, this); - this.addButton(_('OK'), this.onOkClick, this); - this.addEvents('save'); - - this.on('show', this.onShow, this); - this.on('save', this.onSave, this); - - this.addWindow = new Deluge.AddTrackerWindow(); - this.addWindow.on('add', this.onAddTrackers, this); - this.editWindow = new Deluge.EditTrackerWindow(); - - this.list = new Ext.list.ListView({ - store: new Ext.data.JsonStore({ - root: 'trackers', - fields: ['tier', 'url'], - }), - columns: [ - { - header: _('Tier'), - width: 0.1, - dataIndex: 'tier', - }, - { - header: _('Tracker'), - width: 0.9, - dataIndex: 'url', - tpl: new Ext.XTemplate('{url:htmlEncode}'), - }, - ], - columnSort: { - sortClasses: ['', ''], - }, - stripeRows: true, - singleSelect: true, - listeners: { - dblclick: { fn: this.onListNodeDblClicked, scope: this }, - selectionchange: { fn: this.onSelect, scope: this }, - }, - }); - - this.panel = this.add({ - items: [this.list], - autoScroll: true, - bbar: new Ext.Toolbar({ - items: [ - { - text: _('Up'), - iconCls: 'icon-up', - handler: this.onUpClick, - scope: this, - }, - { - text: _('Down'), - iconCls: 'icon-down', - handler: this.onDownClick, - scope: this, - }, - '->', - { - text: _('Add'), - iconCls: 'icon-add', - handler: this.onAddClick, - scope: this, - }, - { - text: _('Edit'), - iconCls: 'icon-edit-trackers', - handler: this.onEditClick, - scope: this, - }, - { - text: _('Remove'), - iconCls: 'icon-remove', - handler: this.onRemoveClick, - scope: this, - }, - ], - }), - }); - }, - - onAddClick: function () { - this.addWindow.show(); - }, - - onAddTrackers: function (trackers) { - var store = this.list.getStore(); - Ext.each( - trackers, - function (tracker) { - var duplicate = false, - heightestTier = -1; - store.each(function (record) { - if (record.get('tier') > heightestTier) { - heightestTier = record.get('tier'); - } - if (tracker == record.get('tracker')) { - duplicate = true; - return false; - } - }, this); - if (duplicate) return; - store.add( - new store.recordType({ - tier: heightestTier + 1, - url: tracker, - }) - ); - }, - this - ); - }, - - onCancelClick: function () { - this.hide(); - }, - - onEditClick: function () { - var selected = this.list.getSelectedRecords()[0]; - if (!selected) return; - this.editWindow.show(selected); - }, - - onHide: function () { - this.list.getStore().removeAll(); - }, - - onListNodeDblClicked: function (list, index, node, e) { - this.editWindow.show(this.list.getRecord(node)); - }, - - onOkClick: function () { - var trackers = []; - this.list.getStore().each(function (record) { - trackers.push({ - tier: record.get('tier'), - url: record.get('url'), - }); - }, this); - - deluge.client.core.set_torrent_trackers(this.torrentId, trackers, { - failure: this.onSaveFail, - scope: this, - }); - - this.hide(); - }, - - onRemoveClick: function () { - // Remove from the grid - var selected = this.list.getSelectedRecords()[0]; - if (!selected) return; - this.list.getStore().remove(selected); - }, - - onRequestComplete: function (status) { - this.list.getStore().loadData(status); - this.list.getStore().sort('tier', 'ASC'); - }, - - onSaveFail: function () {}, - - onSelect: function (list) { - if (list.getSelectionCount()) { - this.panel.getBottomToolbar().items.get(4).enable(); - } - }, - - onShow: function () { - this.panel.getBottomToolbar().items.get(4).disable(); - var r = deluge.torrents.getSelected(); - this.torrentId = r.id; - deluge.client.core.get_torrent_status(r.id, ['trackers'], { - success: this.onRequestComplete, - scope: this, - }); - }, - - onDownClick: function () { - var r = this.list.getSelectedRecords()[0]; - if (!r) return; - - r.set('tier', r.get('tier') + 1); - r.store.sort('tier', 'ASC'); - r.store.commitChanges(); - - this.list.select(r.store.indexOf(r)); - }, - - onUpClick: function () { - var r = this.list.getSelectedRecords()[0]; - if (!r) return; - - if (r.get('tier') == 0) return; - r.set('tier', r.get('tier') - 1); - r.store.sort('tier', 'ASC'); - r.store.commitChanges(); - - this.list.select(r.store.indexOf(r)); - }, -}); -/** - * Deluge.EventsManager.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. - */ - -/** - * @class Deluge.EventsManager - * @extends Ext.util.Observable - * <p>Deluge.EventsManager is instantated as <tt>deluge.events</tt> and can be used by components of the UI to fire global events</p> - * Class for holding global events that occur within the UI. - */ -Deluge.EventsManager = Ext.extend(Ext.util.Observable, { - constructor: function () { - this.toRegister = []; - this.on('login', this.onLogin, this); - Deluge.EventsManager.superclass.constructor.call(this); - }, - - /** - * Append an event handler to this object. - */ - addListener: function (eventName, fn, scope, o) { - this.addEvents(eventName); - if (/[A-Z]/.test(eventName.substring(0, 1))) { - if (!deluge.client) { - this.toRegister.push(eventName); - } else { - deluge.client.web.register_event_listener(eventName); - } - } - Deluge.EventsManager.superclass.addListener.call( - this, - eventName, - fn, - scope, - o - ); - }, - - getEvents: function () { - deluge.client.web.get_events({ - success: this.onGetEventsSuccess, - failure: this.onGetEventsFailure, - scope: this, - }); - }, - - /** - * Starts the EventsManagerManager checking for events. - */ - start: function () { - Ext.each(this.toRegister, function (eventName) { - deluge.client.web.register_event_listener(eventName); - }); - this.running = true; - this.errorCount = 0; - this.getEvents(); - }, - - /** - * Stops the EventsManagerManager checking for events. - */ - stop: function () { - this.running = false; - }, - - // private - onLogin: function () { - this.start(); - }, - - onGetEventsSuccess: function (events) { - if (!this.running) return; - if (events) { - Ext.each( - events, - function (event) { - var name = event[0], - args = event[1]; - args.splice(0, 0, name); - this.fireEvent.apply(this, args); - }, - this - ); - } - this.getEvents(); - }, - - // private - onGetEventsFailure: function (result, error) { - // the request timed out or we had a communication failure - if (!this.running) return; - if (!error.isTimeout && this.errorCount++ >= 3) { - this.stop(); - return; - } - this.getEvents(); - }, -}); - -/** - * Appends an event handler to this object (shorthand for {@link #addListener}) - * @method - */ -Deluge.EventsManager.prototype.on = Deluge.EventsManager.prototype.addListener; - -/** - * Fires the specified event with the passed parameters (minus the - * event name). - * @method - */ -Deluge.EventsManager.prototype.fire = Deluge.EventsManager.prototype.fireEvent; -deluge.events = new Deluge.EventsManager(); -/** - * Deluge.FileBrowser.js - * - * Copyright (c) Damien Churchill 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. - */ - -Ext.namespace('Deluge'); -Deluge.FileBrowser = Ext.extend(Ext.Window, { - title: _('File Browser'), - - width: 500, - height: 400, - - initComponent: function () { - Deluge.FileBrowser.superclass.initComponent.call(this); - - this.add({ - xtype: 'toolbar', - items: [ - { - text: _('Back'), - iconCls: 'icon-back', - }, - { - text: _('Forward'), - iconCls: 'icon-forward', - }, - { - text: _('Up'), - iconCls: 'icon-up', - }, - { - text: _('Home'), - iconCls: 'icon-home', - }, - ], - }); - }, -}); -/** - * Deluge.FilterPanel.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. - */ -Ext.ns('Deluge'); - -/** - * @class Deluge.FilterPanel - * @extends Ext.list.ListView - */ -Deluge.FilterPanel = Ext.extend(Ext.Panel, { - autoScroll: true, - - border: false, - - show_zero: null, - - initComponent: function () { - Deluge.FilterPanel.superclass.initComponent.call(this); - this.filterType = this.initialConfig.filter; - var title = ''; - if (this.filterType == 'state') { - title = _('States'); - } else if (this.filterType == 'tracker_host') { - title = _('Trackers'); - } else if (this.filterType == 'owner') { - title = _('Owner'); - } else if (this.filterType == 'label') { - title = _('Labels'); - } else { - (title = this.filterType.replace('_', ' ')), - (parts = title.split(' ')), - (title = ''); - Ext.each(parts, function (p) { - fl = p.substring(0, 1).toUpperCase(); - title += fl + p.substring(1) + ' '; - }); - } - this.setTitle(_(title)); - - if (Deluge.FilterPanel.templates[this.filterType]) { - var tpl = Deluge.FilterPanel.templates[this.filterType]; - } else { - var tpl = - '<div class="x-deluge-filter x-deluge-{filter:lowercase}">{filter} ({count})</div>'; - } - - this.list = this.add({ - xtype: 'listview', - singleSelect: true, - hideHeaders: true, - reserveScrollOffset: true, - store: new Ext.data.ArrayStore({ - idIndex: 0, - fields: ['filter', 'count'], - }), - columns: [ - { - id: 'filter', - sortable: false, - tpl: tpl, - dataIndex: 'filter', - }, - ], - }); - this.relayEvents(this.list, ['selectionchange']); - }, - - /** - * Return the currently selected filter state - * @returns {String} the current filter state - */ - getState: function () { - if (!this.list.getSelectionCount()) return; - - var state = this.list.getSelectedRecords()[0]; - if (!state) return; - if (state.id == 'All') return; - return state.id; - }, - - /** - * Return the current states in the filter - */ - getStates: function () { - return this.states; - }, - - /** - * Return the Store for the ListView of the FilterPanel - * @returns {Ext.data.Store} the ListView store - */ - getStore: function () { - return this.list.getStore(); - }, - - /** - * Update the states in the FilterPanel - */ - updateStates: function (states) { - this.states = {}; - Ext.each( - states, - function (state) { - this.states[state[0]] = state[1]; - }, - this - ); - - var show_zero = - this.show_zero == null - ? deluge.config.sidebar_show_zero - : this.show_zero; - if (!show_zero) { - var newStates = []; - Ext.each(states, function (state) { - if (state[1] > 0 || state[0] == 'All') { - newStates.push(state); - } - }); - states = newStates; - } - - var store = this.getStore(); - var filters = {}; - Ext.each( - states, - function (s, i) { - var record = store.getById(s[0]); - if (!record) { - record = new store.recordType({ - filter: s[0], - count: s[1], - }); - record.id = s[0]; - store.insert(i, record); - } - record.beginEdit(); - record.set('filter', _(s[0])); - record.set('count', s[1]); - record.endEdit(); - filters[s[0]] = true; - }, - this - ); - - store.each(function (record) { - if (filters[record.id]) return; - store.remove(record); - var selected = this.list.getSelectedRecords()[0]; - if (!selected) return; - if (selected.id == record.id) { - this.list.select(0); - } - }, this); - - store.commitChanges(); - - if (!this.list.getSelectionCount()) { - this.list.select(0); - } - }, -}); - -Deluge.FilterPanel.templates = { - tracker_host: - '<div class="x-deluge-filter" style="background-image: url(' + - deluge.config.base + - 'tracker/{filter});">{filter:htmlEncode} ({count})</div>', -}; -/** - * Deluge.Formatters.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. - */ - -/** - * A collection of functions for string formatting values. - * @class Deluge.Formatters - * @author Damien Churchill <damoxc@gmail.com> - * @version 1.3 - * @singleton - */ -Deluge.Formatters = (function () { - var charToEntity = { - '&': '&', - '>': '>', - '<': '<', - '"': '"', - "'": ''', - }; - - var charToEntityRegex = new RegExp( - '(' + Object.keys(charToEntity).join('|') + ')', - 'g' - ); - var htmlEncodeReplaceFn = function (match, capture) { - return charToEntity[capture]; - }; - - /** - * Formats a date string in the date representation of the current locale, - * based on the systems timezone. - * - * @param {Number} timestamp time in seconds since the Epoch. - * @return {String} a string in the date representation of the current locale - * or "" if seconds < 0. - */ - return (Formatters = { - date: function (timestamp) { - function zeroPad(num, count) { - var numZeropad = num + ''; - while (numZeropad.length < count) { - numZeropad = '0' + numZeropad; - } - return numZeropad; - } - timestamp = timestamp * 1000; - var date = new Date(timestamp); - return String.format( - '{0}/{1}/{2} {3}:{4}:{5}', - zeroPad(date.getDate(), 2), - zeroPad(date.getMonth() + 1, 2), - date.getFullYear(), - zeroPad(date.getHours(), 2), - zeroPad(date.getMinutes(), 2), - zeroPad(date.getSeconds(), 2) - ); - }, - - /** - * Formats the bytes value into a string with KiB, MiB or GiB units. - * - * @param {Number} bytes the filesize in bytes - * @param {Boolean} showZero pass in true to displays 0 values - * @return {String} formatted string with KiB, MiB or GiB units. - */ - size: function (bytes, showZero) { - if (!bytes && !showZero) return ''; - bytes = bytes / 1024.0; - - if (bytes < 1024) { - return bytes.toFixed(1) + ' KiB'; - } else { - bytes = bytes / 1024; - } - - if (bytes < 1024) { - return bytes.toFixed(1) + ' MiB'; - } else { - bytes = bytes / 1024; - } - - return bytes.toFixed(1) + ' GiB'; - }, - - /** - * Formats the bytes value into a string with K, M or G units. - * - * @param {Number} bytes the filesize in bytes - * @param {Boolean} showZero pass in true to displays 0 values - * @return {String} formatted string with K, M or G units. - */ - sizeShort: function (bytes, showZero) { - if (!bytes && !showZero) return ''; - bytes = bytes / 1024.0; - - if (bytes < 1024) { - return bytes.toFixed(1) + ' K'; - } else { - bytes = bytes / 1024; - } - - if (bytes < 1024) { - return bytes.toFixed(1) + ' M'; - } else { - bytes = bytes / 1024; - } - - return bytes.toFixed(1) + ' G'; - }, - - /** - * Formats a string to display a transfer speed utilizing {@link #size} - * - * @param {Number} bytes the number of bytes per second - * @param {Boolean} showZero pass in true to displays 0 values - * @return {String} formatted string with KiB, MiB or GiB units. - */ - speed: function (bytes, showZero) { - return !bytes && !showZero ? '' : fsize(bytes, showZero) + '/s'; - }, - - /** - * Formats a string to show time in a human readable form. - * - * @param {Number} time the number of seconds - * @return {String} a formatted time string. will return '' if seconds == 0 - */ - timeRemaining: function (time) { - if (time <= 0) { - return '∞'; - } - time = time.toFixed(0); - if (time < 60) { - return time + 's'; - } else { - time = time / 60; - } - - if (time < 60) { - var minutes = Math.floor(time); - var seconds = Math.round(60 * (time - minutes)); - if (seconds > 0) { - return minutes + 'm ' + seconds + 's'; - } else { - return minutes + 'm'; - } - } else { - time = time / 60; - } - - if (time < 24) { - var hours = Math.floor(time); - var minutes = Math.round(60 * (time - hours)); - if (minutes > 0) { - return hours + 'h ' + minutes + 'm'; - } else { - return hours + 'h'; - } - } else { - time = time / 24; - } - - var days = Math.floor(time); - var hours = Math.round(24 * (time - days)); - if (hours > 0) { - return days + 'd ' + hours + 'h'; - } else { - return days + 'd'; - } - }, - - /** - * Simply returns the value untouched, for when no formatting is required. - * - * @param {Mixed} value the value to be displayed - * @return the untouched value. - */ - plain: function (value) { - return value; - }, - - cssClassEscape: function (value) { - return value.toLowerCase().replace('.', '_'); - }, - - htmlEncode: function (value) { - return !value - ? value - : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn); - }, - }); -})(); -var fsize = Deluge.Formatters.size; -var fsize_short = Deluge.Formatters.sizeShort; -var fspeed = Deluge.Formatters.speed; -var ftime = Deluge.Formatters.timeRemaining; -var fdate = Deluge.Formatters.date; -var fplain = Deluge.Formatters.plain; -Ext.util.Format.cssClassEscape = Deluge.Formatters.cssClassEscape; -Ext.util.Format.htmlEncode = Deluge.Formatters.htmlEncode; -/** - * Deluge.Keys.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. - */ - -/** - * @description The torrent status keys that are commonly used around the UI. - * @class Deluge.Keys - * @singleton - */ -Deluge.Keys = { - /** - * Keys that are used within the torrent grid. - * <pre>['queue', 'name', 'total_wanted', 'state', 'progress', 'num_seeds', - * 'total_seeds', 'num_peers', 'total_peers', 'download_payload_rate', - * 'upload_payload_rate', 'eta', 'ratio', 'distributed_copies', - * 'is_auto_managed', 'time_added', 'tracker_host', 'download_location', 'last_seen_complete', - * 'total_done', 'total_uploaded', 'max_download_speed', 'max_upload_speed', - * 'seeds_peers_ratio', 'total_remaining', 'completed_time', 'time_since_transfer']</pre> - */ - Grid: [ - 'queue', - 'name', - 'total_wanted', - 'state', - 'progress', - 'num_seeds', - 'total_seeds', - 'num_peers', - 'total_peers', - 'download_payload_rate', - 'upload_payload_rate', - 'eta', - 'ratio', - 'distributed_copies', - 'is_auto_managed', - 'time_added', - 'tracker_host', - 'download_location', - 'last_seen_complete', - 'total_done', - 'total_uploaded', - 'max_download_speed', - 'max_upload_speed', - 'seeds_peers_ratio', - 'total_remaining', - 'completed_time', - 'time_since_transfer', - ], - - /** - * Keys used in the status tab of the statistics panel. - * These get updated to include the keys in {@link #Grid}. - * <pre>['total_done', 'total_payload_download', 'total_uploaded', - * 'total_payload_upload', 'next_announce', 'tracker_status', 'num_pieces', - * 'piece_length', 'is_auto_managed', 'active_time', 'seeding_time', 'time_since_transfer', - * 'seed_rank', 'last_seen_complete', 'completed_time', 'owner', 'public', 'shared']</pre> - */ - Status: [ - 'total_done', - 'total_payload_download', - 'total_uploaded', - 'total_payload_upload', - 'next_announce', - 'tracker_status', - 'num_pieces', - 'piece_length', - 'is_auto_managed', - 'active_time', - 'seeding_time', - 'time_since_transfer', - 'seed_rank', - 'last_seen_complete', - 'completed_time', - 'owner', - 'public', - 'shared', - ], - - /** - * Keys used in the files tab of the statistics panel. - * <pre>['files', 'file_progress', 'file_priorities']</pre> - */ - Files: ['files', 'file_progress', 'file_priorities'], - - /** - * Keys used in the peers tab of the statistics panel. - * <pre>['peers']</pre> - */ - Peers: ['peers'], - - /** - * Keys used in the details tab of the statistics panel. - */ - Details: [ - 'name', - 'download_location', - 'total_size', - 'num_files', - 'message', - 'tracker_host', - 'comment', - 'creator', - ], - - /** - * Keys used in the options tab of the statistics panel. - * <pre>['max_download_speed', 'max_upload_speed', 'max_connections', 'max_upload_slots', - * 'is_auto_managed', 'stop_at_ratio', 'stop_ratio', 'remove_at_ratio', 'private', - * 'prioritize_first_last']</pre> - */ - Options: [ - 'max_download_speed', - 'max_upload_speed', - 'max_connections', - 'max_upload_slots', - 'is_auto_managed', - 'stop_at_ratio', - 'stop_ratio', - 'remove_at_ratio', - 'private', - 'prioritize_first_last', - 'move_completed', - 'move_completed_path', - 'super_seeding', - ], -}; - -// Merge the grid and status keys together as the status keys contain all the -// grid ones. -Ext.each(Deluge.Keys.Grid, function (key) { - Deluge.Keys.Status.push(key); -}); -/** - * Deluge.LoginWindow.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. - */ - -Deluge.LoginWindow = Ext.extend(Ext.Window, { - firstShow: true, - bodyStyle: 'padding: 10px 5px;', - buttonAlign: 'center', - closable: false, - closeAction: 'hide', - iconCls: 'x-deluge-login-window-icon', - layout: 'fit', - modal: true, - plain: true, - resizable: false, - title: _('Login'), - width: 300, - height: 120, - - initComponent: function () { - Deluge.LoginWindow.superclass.initComponent.call(this); - this.on('show', this.onShow, this); - - this.addButton({ - text: _('Login'), - handler: this.onLogin, - scope: this, - }); - - this.form = this.add({ - xtype: 'form', - baseCls: 'x-plain', - labelWidth: 120, - labelAlign: 'right', - defaults: { width: 110 }, - defaultType: 'textfield', - }); - - this.passwordField = this.form.add({ - xtype: 'textfield', - fieldLabel: _('Password:'), - labelSeparator: '', - grow: true, - growMin: '110', - growMax: '145', - id: '_password', - name: 'password', - inputType: 'password', - }); - this.passwordField.on('specialkey', this.onSpecialKey, this); - }, - - logout: function () { - deluge.events.fire('logout'); - deluge.client.auth.delete_session({ - success: function (result) { - this.show(true); - }, - scope: this, - }); - }, - - show: function (skipCheck) { - if (this.firstShow) { - deluge.client.on('error', this.onClientError, this); - this.firstShow = false; - } - - if (skipCheck) { - return Deluge.LoginWindow.superclass.show.call(this); - } - - deluge.client.auth.check_session({ - success: function (result) { - if (result) { - deluge.events.fire('login'); - } else { - this.show(true); - } - }, - failure: function (result) { - this.show(true); - }, - scope: this, - }); - }, - - onSpecialKey: function (field, e) { - if (e.getKey() == 13) this.onLogin(); - }, - - onLogin: function () { - var passwordField = this.passwordField; - deluge.client.auth.login(passwordField.getValue(), { - success: function (result) { - if (result) { - deluge.events.fire('login'); - this.hide(); - passwordField.setRawValue(''); - } else { - Ext.MessageBox.show({ - title: _('Login Failed'), - msg: _('You entered an incorrect password'), - buttons: Ext.MessageBox.OK, - modal: false, - fn: function () { - passwordField.focus(true, 10); - }, - icon: Ext.MessageBox.WARNING, - iconCls: 'x-deluge-icon-warning', - }); - } - }, - scope: this, - }); - }, - - onClientError: function (errorObj, response, requestOptions) { - if (errorObj.error.code == 1) { - deluge.events.fire('logout'); - this.show(true); - } - }, - - onShow: function () { - this.passwordField.focus(true, 300); - }, -}); -/** - * Deluge.Menus.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. - */ - -deluge.menus = { - onTorrentActionSetOpt: function (item, e) { - var ids = deluge.torrents.getSelectedIds(); - var action = item.initialConfig.torrentAction; - var opts = {}; - opts[action[0]] = action[1]; - deluge.client.core.set_torrent_options(ids, opts); - }, - - onTorrentActionMethod: function (item, e) { - var ids = deluge.torrents.getSelectedIds(); - var action = item.initialConfig.torrentAction; - deluge.client.core[action](ids, { - success: function () { - deluge.ui.update(); - }, - }); - }, - - onTorrentActionShow: function (item, e) { - var ids = deluge.torrents.getSelectedIds(); - var action = item.initialConfig.torrentAction; - switch (action) { - case 'copy_magnet': - deluge.copyMagnetWindow.show(); - break; - case 'edit_trackers': - deluge.editTrackers.show(); - break; - case 'remove': - deluge.removeWindow.show(ids); - break; - case 'move': - deluge.moveStorage.show(ids); - break; - } - }, -}; - -deluge.menus.torrent = new Ext.menu.Menu({ - id: 'torrentMenu', - items: [ - { - torrentAction: 'pause_torrent', - text: _('Pause'), - iconCls: 'icon-pause', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - { - torrentAction: 'resume_torrent', - text: _('Resume'), - iconCls: 'icon-resume', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - '-', - { - text: _('Options'), - iconCls: 'icon-options', - hideOnClick: false, - menu: new Ext.menu.Menu({ - items: [ - { - text: _('D/L Speed Limit'), - iconCls: 'x-deluge-downloading', - hideOnClick: false, - menu: new Ext.menu.Menu({ - items: [ - { - torrentAction: ['max_download_speed', 5], - text: _('5 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_download_speed', 10], - text: _('10 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_download_speed', 30], - text: _('30 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_download_speed', 80], - text: _('80 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_download_speed', 300], - text: _('300 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_download_speed', -1], - text: _('Unlimited'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - ], - }), - }, - { - text: _('U/L Speed Limit'), - iconCls: 'x-deluge-seeding', - hideOnClick: false, - menu: new Ext.menu.Menu({ - items: [ - { - torrentAction: ['max_upload_speed', 5], - text: _('5 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_speed', 10], - text: _('10 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_speed', 30], - text: _('30 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_speed', 80], - text: _('80 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_speed', 300], - text: _('300 KiB/s'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_speed', -1], - text: _('Unlimited'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - ], - }), - }, - { - text: _('Connection Limit'), - iconCls: 'x-deluge-connections', - hideOnClick: false, - menu: new Ext.menu.Menu({ - items: [ - { - torrentAction: ['max_connections', 50], - text: '50', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_connections', 100], - text: '100', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_connections', 200], - text: '200', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_connections', 300], - text: '300', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_connections', 500], - text: '500', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_connections', -1], - text: _('Unlimited'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - ], - }), - }, - { - text: _('Upload Slot Limit'), - iconCls: 'icon-upload-slots', - hideOnClick: false, - menu: new Ext.menu.Menu({ - items: [ - { - torrentAction: ['max_upload_slots', 0], - text: '0', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_slots', 1], - text: '1', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_slots', 2], - text: '2', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_slots', 3], - text: '3', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_slots', 5], - text: '5', - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['max_upload_slots', -1], - text: _('Unlimited'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - ], - }), - }, - { - id: 'auto_managed', - text: _('Auto Managed'), - hideOnClick: false, - menu: new Ext.menu.Menu({ - items: [ - { - torrentAction: ['auto_managed', true], - text: _('On'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - { - torrentAction: ['auto_managed', false], - text: _('Off'), - handler: deluge.menus.onTorrentActionSetOpt, - scope: deluge.menus, - }, - ], - }), - }, - ], - }), - }, - '-', - { - text: _('Queue'), - iconCls: 'icon-queue', - hideOnClick: false, - menu: new Ext.menu.Menu({ - items: [ - { - torrentAction: 'queue_top', - text: _('Top'), - iconCls: 'icon-top', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - { - torrentAction: 'queue_up', - text: _('Up'), - iconCls: 'icon-up', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - { - torrentAction: 'queue_down', - text: _('Down'), - iconCls: 'icon-down', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - { - torrentAction: 'queue_bottom', - text: _('Bottom'), - iconCls: 'icon-bottom', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - ], - }), - }, - '-', - { - torrentAction: 'copy_magnet', - text: _('Copy Magnet URI'), - iconCls: 'icon-magnet-copy', - handler: deluge.menus.onTorrentActionShow, - scope: deluge.menus, - }, - { - torrentAction: 'force_reannounce', - text: _('Update Tracker'), - iconCls: 'icon-update-tracker', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - { - torrentAction: 'edit_trackers', - text: _('Edit Trackers'), - iconCls: 'icon-edit-trackers', - handler: deluge.menus.onTorrentActionShow, - scope: deluge.menus, - }, - '-', - { - torrentAction: 'remove', - text: _('Remove Torrent'), - iconCls: 'icon-remove', - handler: deluge.menus.onTorrentActionShow, - scope: deluge.menus, - }, - '-', - { - torrentAction: 'force_recheck', - text: _('Force Recheck'), - iconCls: 'icon-recheck', - handler: deluge.menus.onTorrentActionMethod, - scope: deluge.menus, - }, - { - torrentAction: 'move', - text: _('Move Download Folder'), - iconCls: 'icon-move', - handler: deluge.menus.onTorrentActionShow, - scope: deluge.menus, - }, - ], -}); - -deluge.menus.filePriorities = new Ext.menu.Menu({ - id: 'filePrioritiesMenu', - items: [ - { - id: 'expandAll', - text: _('Expand All'), - iconCls: 'icon-expand-all', - }, - '-', - { - id: 'skip', - text: _('Skip'), - iconCls: 'icon-do-not-download', - filePriority: FILE_PRIORITY['Skip'], - }, - { - id: 'low', - text: _('Low'), - iconCls: 'icon-low', - filePriority: FILE_PRIORITY['Low'], - }, - { - id: 'normal', - text: _('Normal'), - iconCls: 'icon-normal', - filePriority: FILE_PRIORITY['Normal'], - }, - { - id: 'high', - text: _('High'), - iconCls: 'icon-high', - filePriority: FILE_PRIORITY['High'], - }, - ], -}); -/** - * Deluge.MoveStorage.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. - */ - -Ext.namespace('Deluge'); -Deluge.MoveStorage = Ext.extend(Ext.Window, { - constructor: function (config) { - config = Ext.apply( - { - title: _('Move Download Folder'), - width: 375, - height: 110, - layout: 'fit', - buttonAlign: 'right', - closeAction: 'hide', - closable: true, - iconCls: 'x-deluge-move-storage', - plain: true, - constrainHeader: true, - resizable: false, - }, - config - ); - Deluge.MoveStorage.superclass.constructor.call(this, config); - }, - - initComponent: function () { - Deluge.MoveStorage.superclass.initComponent.call(this); - - this.addButton(_('Cancel'), this.onCancel, this); - this.addButton(_('Move'), this.onMove, this); - - this.form = this.add({ - xtype: 'form', - border: false, - defaultType: 'textfield', - width: 300, - bodyStyle: 'padding: 5px', - }); - - this.moveLocation = this.form.add({ - fieldLabel: _('Download Folder'), - name: 'location', - width: 240, - }); - //this.form.add({ - // xtype: 'button', - // text: _('Browse'), - // handler: function() { - // if (!this.fileBrowser) { - // this.fileBrowser = new Deluge.FileBrowser(); - // } - // this.fileBrowser.show(); - // }, - // scope: this - //}); - }, - - hide: function () { - Deluge.MoveStorage.superclass.hide.call(this); - this.torrentIds = null; - }, - - show: function (torrentIds) { - Deluge.MoveStorage.superclass.show.call(this); - this.torrentIds = torrentIds; - }, - - onCancel: function () { - this.hide(); - }, - - onMove: function () { - var dest = this.moveLocation.getValue(); - deluge.client.core.move_storage(this.torrentIds, dest); - this.hide(); - }, -}); -deluge.moveStorage = new Deluge.MoveStorage(); -/** - * Deluge.MultiOptionsManager.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. - */ - -/** - * @description A class that can be used to manage options throughout the ui. - * @namespace Deluge - * @class Deluge.MultiOptionsManager - * @extends Deluge.OptionsManager - */ -Deluge.MultiOptionsManager = Ext.extend(Deluge.OptionsManager, { - constructor: function (config) { - this.currentId = null; - this.stored = {}; - Deluge.MultiOptionsManager.superclass.constructor.call(this, config); - }, - - /** - * Changes bound fields to use the specified id. - * @param {String} id - */ - changeId: function (id, dontUpdateBinds) { - var oldId = this.currentId; - this.currentId = id; - if (!dontUpdateBinds) { - for (var option in this.options) { - if (!this.binds[option]) continue; - Ext.each( - this.binds[option], - function (bind) { - bind.setValue(this.get(option)); - }, - this - ); - } - } - return oldId; - }, - - /** - * Changes all the changed values to be the default values - * @param {String} id - */ - commit: function () { - this.stored[this.currentId] = Ext.apply( - this.stored[this.currentId], - this.changed[this.currentId] - ); - this.reset(); - }, - - /** - * Get the value for an option - * @param {String/Array} option A single option or an array of options to return. - * @returns {Object} the options value. - */ - get: function () { - if (arguments.length == 1) { - var option = arguments[0]; - return this.isDirty(option) - ? this.changed[this.currentId][option] - : this.getDefault(option); - } else if (arguments.length == 0) { - var options = {}; - for (var option in this.options) { - options[option] = this.isDirty(option) - ? this.changed[this.currentId][option] - : this.getDefault(option); - } - return options; - } else { - var options = {}; - Ext.each( - arguments, - function (option) { - options[option] = this.isDirty(option) - ? this.changed[this.currentId][option] - : this.getDefault(option); - }, - this - ); - return options; - } - }, - - /** - * Get the default value for an option. - * @param {String} option A single option. - * @returns {Object} the value of the option - */ - getDefault: function (option) { - return this.has(option) - ? this.stored[this.currentId][option] - : this.options[option]; - }, - - /** - * Returns the dirty (changed) values. - * @returns {Object} the changed options - */ - getDirty: function () { - return this.changed[this.currentId] ? this.changed[this.currentId] : {}; - }, - - /** - * Check to see if the option has been changed. - * @param {String} option - * @returns {Boolean} true if the option has been changed, else false. - */ - isDirty: function (option) { - return ( - this.changed[this.currentId] && - !Ext.isEmpty(this.changed[this.currentId][option]) - ); - }, - - /** - * Check to see if an id has had an option set to something other than the - * default value. - * @param {String} option - * @returns {Boolean} true if the id has an option, else false. - */ - has: function (option) { - return ( - this.stored[this.currentId] && - !Ext.isEmpty(this.stored[this.currentId][option]) - ); - }, - - /** - * Reset the options back to the default values for the specified id. - */ - reset: function () { - if (this.changed[this.currentId]) delete this.changed[this.currentId]; - if (this.stored[this.currentId]) delete this.stored[this.currentId]; - }, - - /** - * Reset the options back to their defaults for all ids. - */ - resetAll: function () { - this.changed = {}; - this.stored = {}; - this.changeId(null); - }, - - /** - * Sets the value of specified option for the passed in id. - * @param {String} id - * @param {String} option - * @param {Object} value The value for the option - */ - setDefault: function (option, value) { - if (option === undefined) { - return; - } else if (value === undefined) { - for (var key in option) { - this.setDefault(key, option[key]); - } - } else { - var oldValue = this.getDefault(option); - value = this.convertValueType(oldValue, value); - - // If the value is the same as the old value there is - // no point in setting it again. - if (oldValue == value) return; - - // Store the new default - if (!this.stored[this.currentId]) this.stored[this.currentId] = {}; - this.stored[this.currentId][option] = value; - - if (!this.isDirty(option)) { - this.fireEvent('changed', option, value, oldValue); - } - } - }, - - /** - * Update the value for the specified option and id. - * @param {String} id - * @param {String/Object} option or options to update - * @param {Object} [value]; - */ - update: function (option, value) { - if (option === undefined) { - return; - } else if (value === undefined) { - for (var key in option) { - this.update(key, option[key]); - } - } else { - if (!this.changed[this.currentId]) - this.changed[this.currentId] = {}; - - var defaultValue = this.getDefault(option); - value = this.convertValueType(defaultValue, value); - - var oldValue = this.get(option); - if (oldValue == value) return; - - if (defaultValue == value) { - if (this.isDirty(option)) - delete this.changed[this.currentId][option]; - this.fireEvent('changed', option, value, oldValue); - return; - } else { - this.changed[this.currentId][option] = value; - this.fireEvent('changed', option, value, oldValue); - } - } - }, -}); -/** - * Deluge.OtherLimitWindow.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. - */ -Ext.ns('Deluge'); - -/** - * @class Deluge.OtherLimitWindow - * @extends Ext.Window - */ -Deluge.OtherLimitWindow = Ext.extend(Ext.Window, { - layout: 'fit', - width: 210, - height: 100, - constrainHeader: true, - closeAction: 'hide', - - initComponent: function () { - Deluge.OtherLimitWindow.superclass.initComponent.call(this); - this.form = this.add({ - xtype: 'form', - baseCls: 'x-plain', - bodyStyle: 'padding: 5px', - layout: 'hbox', - layoutConfig: { - pack: 'start', - }, - items: [ - { - xtype: 'spinnerfield', - name: 'limit', - }, - ], - }); - if (this.initialConfig.unit) { - this.form.add({ - border: false, - baseCls: 'x-plain', - bodyStyle: 'padding: 5px', - html: this.initialConfig.unit, - }); - } else { - this.setSize(180, 100); - } - - this.addButton(_('Cancel'), this.onCancelClick, this); - this.addButton(_('OK'), this.onOkClick, this); - this.afterMethod('show', this.doFocusField, this); - }, - - setValue: function (value) { - this.form.getForm().setValues({ limit: value }); - }, - - onCancelClick: function () { - this.form.getForm().reset(); - this.hide(); - }, - - onOkClick: function () { - var config = {}; - config[this.group] = this.form.getForm().getValues().limit; - deluge.client.core.set_config(config, { - success: function () { - deluge.ui.update(); - }, - }); - this.hide(); - }, - - doFocusField: function () { - this.form.getForm().findField('limit').focus(true, 10); - }, -}); -/** - * Deluge.Plugin.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. - */ -Ext.ns('Deluge'); - -/** - * @class Deluge.Plugin - * @extends Ext.util.Observable - */ -Deluge.Plugin = Ext.extend(Ext.util.Observable, { - /** - * The plugins name - * @property name - * @type {String} - */ - name: null, - - constructor: function (config) { - this.isDelugePlugin = true; - this.addEvents({ - /** - * @event enabled - * @param {Plugin} plugin the plugin instance - */ - enabled: true, - - /** - * @event disabled - * @param {Plugin} plugin the plugin instance - */ - disabled: true, - }); - Deluge.Plugin.superclass.constructor.call(this, config); - }, - - /** - * Disables the plugin, firing the "{@link #disabled}" event and - * then executing the plugins clean up method onDisabled. - */ - disable: function () { - this.fireEvent('disabled', this); - if (this.onDisable) this.onDisable(); - }, - - /** - * Enables the plugin, firing the "{@link #enabled}" event and - * then executes the plugins setup method, onEnabled. - */ - enable: function () { - deluge.client.reloadMethods(); - this.fireEvent('enable', this); - if (this.onEnable) this.onEnable(); - }, - - registerTorrentStatus: function (key, header, options) { - options = options || {}; - var cc = options.colCfg || {}, - sc = options.storeCfg || {}; - sc = Ext.apply(sc, { name: key }); - deluge.torrents.meta.fields.push(sc); - deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta); - - cc = Ext.apply(cc, { - header: header, - dataIndex: key, - }); - var cols = deluge.torrents.columns.slice(0); - cols.push(cc); - deluge.torrents.colModel.setConfig(cols); - deluge.torrents.columns = cols; - - Deluge.Keys.Grid.push(key); - deluge.torrents.getView().refresh(true); - }, - - deregisterTorrentStatus: function (key) { - var fields = []; - Ext.each(deluge.torrents.meta.fields, function (field) { - if (field.name != key) fields.push(field); - }); - deluge.torrents.meta.fields = fields; - deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta); - - var cols = []; - Ext.each(deluge.torrents.columns, function (col) { - if (col.dataIndex != key) cols.push(col); - }); - deluge.torrents.colModel.setConfig(cols); - deluge.torrents.columns = cols; - - var keys = []; - Ext.each(Deluge.Keys.Grid, function (k) { - if (k == key) keys.push(k); - }); - Deluge.Keys.Grid = keys; - deluge.torrents.getView().refresh(true); - }, -}); - -Ext.ns('Deluge.plugins'); -/** - * Deluge.RemoveWindow.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. - */ - -/** - * @class Deluge.RemoveWindow - * @extends Ext.Window - */ -Deluge.RemoveWindow = Ext.extend(Ext.Window, { - title: _('Remove Torrent'), - layout: 'fit', - width: 350, - height: 100, - constrainHeader: true, - buttonAlign: 'right', - closeAction: 'hide', - closable: true, - iconCls: 'x-deluge-remove-window-icon', - plain: true, - - bodyStyle: 'padding: 5px; padding-left: 10px;', - html: 'Are you sure you wish to remove the torrent (s)?', - - initComponent: function () { - Deluge.RemoveWindow.superclass.initComponent.call(this); - this.addButton(_('Cancel'), this.onCancel, this); - this.addButton(_('Remove With Data'), this.onRemoveData, this); - this.addButton(_('Remove Torrent'), this.onRemove, this); - }, - - remove: function (removeData) { - deluge.client.core.remove_torrents(this.torrentIds, removeData, { - success: function (result) { - if (result == true) { - console.log( - 'Error(s) occured when trying to delete torrent(s).' - ); - } - this.onRemoved(this.torrentIds); - }, - scope: this, - torrentIds: this.torrentIds, - }); - }, - - show: function (ids) { - Deluge.RemoveWindow.superclass.show.call(this); - this.torrentIds = ids; - }, - - onCancel: function () { - this.hide(); - this.torrentIds = null; - }, - - onRemove: function () { - this.remove(false); - }, - - onRemoveData: function () { - this.remove(true); - }, - - onRemoved: function (torrentIds) { - deluge.events.fire('torrentsRemoved', torrentIds); - this.hide(); - deluge.ui.update(); - }, -}); - -deluge.removeWindow = new Deluge.RemoveWindow(); -/** - * Deluge.Sidebar.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. - */ - -// These are just so gen_gettext.py will pick up the strings -// _('State') -// _('Tracker Host') - -/** - * @class Deluge.Sidebar - * @author Damien Churchill <damoxc@gmail.com> - * @version 1.3 - */ -Deluge.Sidebar = Ext.extend(Ext.Panel, { - // private - panels: {}, - - // private - selected: null, - - constructor: function (config) { - config = Ext.apply( - { - id: 'sidebar', - region: 'west', - cls: 'deluge-sidebar', - title: _('Filters'), - layout: 'accordion', - split: true, - width: 200, - minSize: 100, - collapsible: true, - }, - config - ); - Deluge.Sidebar.superclass.constructor.call(this, config); - }, - - // private - initComponent: function () { - Deluge.Sidebar.superclass.initComponent.call(this); - deluge.events.on('disconnect', this.onDisconnect, this); - }, - - createFilter: function (filter, states) { - var panel = new Deluge.FilterPanel({ - filter: filter, - }); - panel.on('selectionchange', function (view, nodes) { - deluge.ui.update(); - }); - this.add(panel); - - this.doLayout(); - this.panels[filter] = panel; - - panel.header.on('click', function (header) { - if (!deluge.config.sidebar_multiple_filters) { - deluge.ui.update(); - } - if (!panel.list.getSelectionCount()) { - panel.list.select(0); - } - }); - this.fireEvent('filtercreate', this, panel); - - panel.updateStates(states); - this.fireEvent('afterfiltercreate', this, panel); - }, - - getFilter: function (filter) { - return this.panels[filter]; - }, - - getFilterStates: function () { - var states = {}; - - if (deluge.config.sidebar_multiple_filters) { - // Grab the filters from each of the filter panels - this.items.each(function (panel) { - var state = panel.getState(); - if (state == null) return; - states[panel.filterType] = state; - }, this); - } else { - var panel = this.getLayout().activeItem; - if (panel) { - var state = panel.getState(); - if (!state == null) return; - states[panel.filterType] = state; - } - } - - return states; - }, - - hasFilter: function (filter) { - return this.panels[filter] ? true : false; - }, - - // private - onDisconnect: function () { - for (var filter in this.panels) { - this.remove(this.panels[filter]); - } - this.panels = {}; - this.selected = null; - }, - - onFilterSelect: function (selModel, rowIndex, record) { - deluge.ui.update(); - }, - - update: function (filters) { - for (var filter in filters) { - var states = filters[filter]; - if (Ext.getKeys(this.panels).indexOf(filter) > -1) { - this.panels[filter].updateStates(states); - } else { - this.createFilter(filter, states); - } - } - - // Perform a cleanup of fitlers that are not enabled any more. - Ext.each( - Ext.keys(this.panels), - function (filter) { - if (Ext.keys(filters).indexOf(filter) == -1) { - // We need to remove the panel - this.remove(this.panels[filter]); - this.doLayout(); - delete this.panels[filter]; - } - }, - this - ); - }, -}); -/** - * Deluge.Statusbar.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. - */ -Ext.namespace('Deluge'); - -Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, { - constructor: function (config) { - config = Ext.apply( - { - id: 'deluge-statusbar', - defaultIconCls: 'x-deluge-statusbar x-not-connected', - defaultText: _('Not Connected'), - }, - config - ); - Deluge.Statusbar.superclass.constructor.call(this, config); - }, - - initComponent: function () { - Deluge.Statusbar.superclass.initComponent.call(this); - - deluge.events.on('connect', this.onConnect, this); - deluge.events.on('disconnect', this.onDisconnect, this); - }, - - createButtons: function () { - this.buttons = this.add( - { - id: 'statusbar-connections', - text: ' ', - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-connections', - tooltip: _('Connections'), - menu: new Deluge.StatusbarMenu({ - items: [ - { - text: '50', - value: '50', - group: 'max_connections_global', - checked: false, - }, - { - text: '100', - value: '100', - group: 'max_connections_global', - checked: false, - }, - { - text: '200', - value: '200', - group: 'max_connections_global', - checked: false, - }, - { - text: '300', - value: '300', - group: 'max_connections_global', - checked: false, - }, - { - text: '500', - value: '500', - group: 'max_connections_global', - checked: false, - }, - { - text: _('Unlimited'), - value: '-1', - group: 'max_connections_global', - checked: false, - }, - '-', - { - text: _('Other'), - value: 'other', - group: 'max_connections_global', - checked: false, - }, - ], - otherWin: { - title: _('Set Maximum Connections'), - }, - }), - }, - '-', - { - id: 'statusbar-downspeed', - text: ' ', - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-downloading', - tooltip: _('Download Speed'), - menu: new Deluge.StatusbarMenu({ - items: [ - { - value: '5', - text: _('5 KiB/s'), - group: 'max_download_speed', - checked: false, - }, - { - value: '10', - text: _('10 KiB/s'), - group: 'max_download_speed', - checked: false, - }, - { - value: '30', - text: _('30 KiB/s'), - group: 'max_download_speed', - checked: false, - }, - { - value: '80', - text: _('80 KiB/s'), - group: 'max_download_speed', - checked: false, - }, - { - value: '300', - text: _('300 KiB/s'), - group: 'max_download_speed', - checked: false, - }, - { - value: '-1', - text: _('Unlimited'), - group: 'max_download_speed', - checked: false, - }, - '-', - { - value: 'other', - text: _('Other'), - group: 'max_download_speed', - checked: false, - }, - ], - otherWin: { - title: _('Set Maximum Download Speed'), - unit: _('KiB/s'), - }, - }), - }, - '-', - { - id: 'statusbar-upspeed', - text: ' ', - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-seeding', - tooltip: _('Upload Speed'), - menu: new Deluge.StatusbarMenu({ - items: [ - { - value: '5', - text: _('5 KiB/s'), - group: 'max_upload_speed', - checked: false, - }, - { - value: '10', - text: _('10 KiB/s'), - group: 'max_upload_speed', - checked: false, - }, - { - value: '30', - text: _('30 KiB/s'), - group: 'max_upload_speed', - checked: false, - }, - { - value: '80', - text: _('80 KiB/s'), - group: 'max_upload_speed', - checked: false, - }, - { - value: '300', - text: _('300 KiB/s'), - group: 'max_upload_speed', - checked: false, - }, - { - value: '-1', - text: _('Unlimited'), - group: 'max_upload_speed', - checked: false, - }, - '-', - { - value: 'other', - text: _('Other'), - group: 'max_upload_speed', - checked: false, - }, - ], - otherWin: { - title: _('Set Maximum Upload Speed'), - unit: _('KiB/s'), - }, - }), - }, - '-', - { - id: 'statusbar-traffic', - text: ' ', - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-traffic', - tooltip: _('Protocol Traffic Download/Upload'), - handler: function () { - deluge.preferences.show(); - deluge.preferences.selectPage('Network'); - }, - }, - '-', - { - id: 'statusbar-externalip', - text: ' ', - cls: 'x-btn-text', - tooltip: _('External IP Address'), - }, - '-', - { - id: 'statusbar-dht', - text: ' ', - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-dht', - tooltip: _('DHT Nodes'), - }, - '-', - { - id: 'statusbar-freespace', - text: ' ', - cls: 'x-btn-text-icon', - iconCls: 'x-deluge-freespace', - tooltip: _('Freespace in download folder'), - handler: function () { - deluge.preferences.show(); - deluge.preferences.selectPage('Downloads'); - }, - } - ); - this.created = true; - }, - - onConnect: function () { - this.setStatus({ - iconCls: 'x-connected', - text: '', - }); - if (!this.created) { - this.createButtons(); - } else { - Ext.each(this.buttons, function (item) { - item.show(); - item.enable(); - }); - } - this.doLayout(); - }, - - onDisconnect: function () { - this.clearStatus({ useDefaults: true }); - Ext.each(this.buttons, function (item) { - item.hide(); - item.disable(); - }); - this.doLayout(); - }, - - update: function (stats) { - if (!stats) return; - - function addSpeed(val) { - return val + ' KiB/s'; - } - - var updateStat = function (name, config) { - var item = this.items.get('statusbar-' + name); - if (config.limit.value > 0) { - var value = config.value.formatter - ? config.value.formatter(config.value.value, true) - : config.value.value; - var limit = config.limit.formatter - ? config.limit.formatter(config.limit.value, true) - : config.limit.value; - var str = String.format(config.format, value, limit); - } else { - var str = config.value.formatter - ? config.value.formatter(config.value.value, true) - : config.value.value; - } - item.setText(str); - - if (!item.menu) return; - item.menu.setValue(config.limit.value); - }.createDelegate(this); - - updateStat('connections', { - value: { value: stats.num_connections }, - limit: { value: stats.max_num_connections }, - format: '{0} ({1})', - }); - - updateStat('downspeed', { - value: { - value: stats.download_rate, - formatter: Deluge.Formatters.speed, - }, - limit: { - value: stats.max_download, - formatter: addSpeed, - }, - format: '{0} ({1})', - }); - - updateStat('upspeed', { - value: { - value: stats.upload_rate, - formatter: Deluge.Formatters.speed, - }, - limit: { - value: stats.max_upload, - formatter: addSpeed, - }, - format: '{0} ({1})', - }); - - updateStat('traffic', { - value: { - value: stats.download_protocol_rate, - formatter: Deluge.Formatters.speed, - }, - limit: { - value: stats.upload_protocol_rate, - formatter: Deluge.Formatters.speed, - }, - format: '{0}/{1}', - }); - - this.items.get('statusbar-dht').setText(stats.dht_nodes); - this.items - .get('statusbar-freespace') - .setText( - stats.free_space >= 0 ? fsize(stats.free_space) : _('Error') - ); - this.items - .get('statusbar-externalip') - .setText( - String.format( - _('<b>IP</b> {0}'), - stats.external_ip ? stats.external_ip : _('n/a') - ) - ); - }, -}); -/** - * Deluge.Toolbar.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. - */ - -/** - * An extension of the <tt>Ext.Toolbar</tt> class that provides an extensible toolbar for Deluge. - * @class Deluge.Toolbar - * @extends Ext.Toolbar - */ -Deluge.Toolbar = Ext.extend(Ext.Toolbar, { - constructor: function (config) { - config = Ext.apply( - { - items: [ - { - id: 'tbar-deluge-text', - text: _('Deluge'), - iconCls: 'x-deluge-main-panel', - handler: this.onAboutClick, - }, - new Ext.Toolbar.Separator(), - { - id: 'create', - disabled: true, - hidden: true, - text: _('Create'), - iconCls: 'icon-create', - handler: this.onTorrentAction, - }, - { - id: 'add', - disabled: true, - text: _('Add'), - iconCls: 'icon-add', - handler: this.onTorrentAdd, - }, - { - id: 'remove', - disabled: true, - text: _('Remove'), - iconCls: 'icon-remove', - handler: this.onTorrentAction, - }, - new Ext.Toolbar.Separator(), - { - id: 'pause', - disabled: true, - text: _('Pause'), - iconCls: 'icon-pause', - handler: this.onTorrentAction, - }, - { - id: 'resume', - disabled: true, - text: _('Resume'), - iconCls: 'icon-resume', - handler: this.onTorrentAction, - }, - new Ext.Toolbar.Separator(), - { - id: 'up', - cls: 'x-btn-text-icon', - disabled: true, - text: _('Up'), - iconCls: 'icon-up', - handler: this.onTorrentAction, - }, - { - id: 'down', - disabled: true, - text: _('Down'), - iconCls: 'icon-down', - handler: this.onTorrentAction, - }, - new Ext.Toolbar.Separator(), - { - id: 'preferences', - text: _('Preferences'), - iconCls: 'x-deluge-preferences', - handler: this.onPreferencesClick, - scope: this, - }, - { - id: 'connectionman', - text: _('Connection Manager'), - iconCls: 'x-deluge-connection-manager', - handler: this.onConnectionManagerClick, - scope: this, - }, - '->', - { - id: 'help', - iconCls: 'icon-help', - text: _('Help'), - handler: this.onHelpClick, - scope: this, - }, - { - id: 'logout', - iconCls: 'icon-logout', - disabled: true, - text: _('Logout'), - handler: this.onLogout, - scope: this, - }, - ], - }, - config - ); - Deluge.Toolbar.superclass.constructor.call(this, config); - }, - - connectedButtons: ['add', 'remove', 'pause', 'resume', 'up', 'down'], - - initComponent: function () { - Deluge.Toolbar.superclass.initComponent.call(this); - deluge.events.on('connect', this.onConnect, this); - deluge.events.on('login', this.onLogin, this); - }, - - onConnect: function () { - Ext.each( - this.connectedButtons, - function (buttonId) { - this.items.get(buttonId).enable(); - }, - this - ); - }, - - onDisconnect: function () { - Ext.each( - this.connectedButtons, - function (buttonId) { - this.items.get(buttonId).disable(); - }, - this - ); - }, - - onLogin: function () { - this.items.get('logout').enable(); - }, - - onLogout: function () { - this.items.get('logout').disable(); - deluge.login.logout(); - }, - - onConnectionManagerClick: function () { - deluge.connectionManager.show(); - }, - - onHelpClick: function () { - window.open('http://dev.deluge-torrent.org/wiki/UserGuide'); - }, - - onAboutClick: function () { - var about = new Deluge.about.AboutWindow(); - about.show(); - }, - - onPreferencesClick: function () { - deluge.preferences.show(); - }, - - onTorrentAction: function (item) { - var selection = deluge.torrents.getSelections(); - var ids = []; - Ext.each(selection, function (record) { - ids.push(record.id); - }); - - switch (item.id) { - case 'remove': - deluge.removeWindow.show(ids); - break; - case 'pause': - case 'resume': - deluge.client.core[item.id + '_torrent'](ids, { - success: function () { - deluge.ui.update(); - }, - }); - break; - case 'up': - case 'down': - deluge.client.core['queue_' + item.id](ids, { - success: function () { - deluge.ui.update(); - }, - }); - break; - } - }, - - onTorrentAdd: function () { - deluge.add.show(); - }, -}); -/** - * 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; 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(); -})(); -/** - * Deluge.UI.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. - */ - -/** Dummy translation arrays so Torrent states are available for gettext.js and Translators. - * - * All entries in deluge.common.TORRENT_STATE should be added here. - * - * No need to import these, just simply use the `_()` function around a status variable. - */ -var TORRENT_STATE_TRANSLATION = [ - _('All'), - _('Active'), - _('Allocating'), - _('Checking'), - _('Downloading'), - _('Seeding'), - _('Paused'), - _('Checking'), - _('Queued'), - _('Error'), -]; - -/** - * @static - * @class Deluge.UI - * The controller for the whole interface, that ties all the components - * together and handles the 2 second poll. - */ -deluge.ui = { - errorCount: 0, - - filters: null, - - /** - * @description Create all the interface components, the json-rpc client - * and set up various events that the UI will utilise. - */ - initialize: function () { - deluge.add = new Deluge.add.AddWindow(); - deluge.details = new Deluge.details.DetailsPanel(); - deluge.connectionManager = new Deluge.ConnectionManager(); - deluge.editTrackers = new Deluge.EditTrackersWindow(); - deluge.login = new Deluge.LoginWindow(); - deluge.preferences = new Deluge.preferences.PreferencesWindow(); - deluge.sidebar = new Deluge.Sidebar(); - deluge.statusbar = new Deluge.Statusbar(); - deluge.toolbar = new Deluge.Toolbar(); - - this.detailsPanel = new Ext.Panel({ - id: 'detailsPanel', - cls: 'detailsPanel', - region: 'south', - split: true, - height: 215, - minSize: 100, - collapsible: true, - layout: 'fit', - items: [deluge.details], - }); - - this.MainPanel = new Ext.Panel({ - id: 'mainPanel', - iconCls: 'x-deluge-main-panel', - layout: 'border', - border: false, - tbar: deluge.toolbar, - items: [deluge.sidebar, this.detailsPanel, deluge.torrents], - bbar: deluge.statusbar, - }); - - this.Viewport = new Ext.Viewport({ - layout: 'fit', - items: [this.MainPanel], - }); - - deluge.events.on('connect', this.onConnect, this); - deluge.events.on('disconnect', this.onDisconnect, this); - deluge.events.on('PluginDisabledEvent', this.onPluginDisabled, this); - deluge.events.on('PluginEnabledEvent', this.onPluginEnabled, this); - deluge.client = new Ext.ux.util.RpcClient({ - url: deluge.config.base + 'json', - }); - - // enable all the already active plugins - for (var plugin in Deluge.pluginStore) { - plugin = Deluge.createPlugin(plugin); - plugin.enable(); - deluge.plugins[plugin.name] = plugin; - } - - // Initialize quicktips so all the tooltip configs start working. - Ext.QuickTips.init(); - - deluge.client.on( - 'connected', - function (e) { - deluge.login.show(); - }, - this, - { single: true } - ); - - this.update = this.update.createDelegate(this); - this.checkConnection = this.checkConnection.createDelegate(this); - - this.originalTitle = document.title; - }, - - checkConnection: function () { - deluge.client.web.connected({ - success: this.onConnectionSuccess, - failure: this.onConnectionError, - scope: this, - }); - }, - - update: function () { - var filters = deluge.sidebar.getFilterStates(); - this.oldFilters = this.filters; - this.filters = filters; - - deluge.client.web.update_ui(Deluge.Keys.Grid, filters, { - success: this.onUpdate, - failure: this.onUpdateError, - scope: this, - }); - deluge.details.update(); - }, - - onConnectionError: function (error) {}, - - onConnectionSuccess: function (result) { - deluge.statusbar.setStatus({ - iconCls: 'x-deluge-statusbar icon-ok', - text: _('Connection restored'), - }); - clearInterval(this.checking); - if (!result) { - deluge.connectionManager.show(); - } - }, - - onUpdateError: function (error) { - if (this.errorCount == 2) { - Ext.MessageBox.show({ - title: _('Lost Connection'), - msg: _('The connection to the webserver has been lost!'), - buttons: Ext.MessageBox.OK, - icon: Ext.MessageBox.ERROR, - }); - deluge.events.fire('disconnect'); - deluge.statusbar.setStatus({ - text: _('Lost connection to webserver'), - }); - this.checking = setInterval(this.checkConnection, 2000); - } - this.errorCount++; - }, - - /** - * @static - * @private - * Updates the various components in the interface. - */ - onUpdate: function (data) { - if (!data['connected']) { - deluge.connectionManager.disconnect(true); - return; - } - - if (deluge.config.show_session_speed) { - document.title = - 'D: ' + - fsize_short(data['stats'].download_rate, true) + - ' U: ' + - fsize_short(data['stats'].upload_rate, true) + - ' - ' + - this.originalTitle; - } - if (Ext.areObjectsEqual(this.filters, this.oldFilters)) { - deluge.torrents.update(data['torrents']); - } else { - deluge.torrents.update(data['torrents'], true); - } - deluge.statusbar.update(data['stats']); - deluge.sidebar.update(data['filters']); - this.errorCount = 0; - }, - - /** - * @static - * @private - * Start the Deluge UI polling the server and update the interface. - */ - onConnect: function () { - if (!this.running) { - this.running = setInterval(this.update, 2000); - this.update(); - } - deluge.client.web.get_plugins({ - success: this.onGotPlugins, - scope: this, - }); - }, - - /** - * @static - * @private - */ - onDisconnect: function () { - this.stop(); - }, - - onGotPlugins: function (plugins) { - Ext.each( - plugins.enabled_plugins, - function (plugin) { - if (deluge.plugins[plugin]) return; - deluge.client.web.get_plugin_resources(plugin, { - success: this.onGotPluginResources, - scope: this, - }); - }, - this - ); - }, - - onPluginEnabled: function (pluginName) { - if (deluge.plugins[pluginName]) { - deluge.plugins[pluginName].enable(); - } else { - deluge.client.web.get_plugin_resources(pluginName, { - success: this.onGotPluginResources, - scope: this, - }); - } - }, - - onGotPluginResources: function (resources) { - var scripts = Deluge.debug - ? resources.debug_scripts - : resources.scripts; - Ext.each( - scripts, - function (script) { - Ext.ux.JSLoader({ - url: deluge.config.base + script, - onLoad: this.onPluginLoaded, - pluginName: resources.name, - }); - }, - this - ); - }, - - onPluginDisabled: function (pluginName) { - if (deluge.plugins[pluginName]) deluge.plugins[pluginName].disable(); - }, - - onPluginLoaded: function (options) { - // This could happen if the plugin has multiple scripts - if (!Deluge.hasPlugin(options.pluginName)) return; - - // Enable the plugin - plugin = Deluge.createPlugin(options.pluginName); - plugin.enable(); - deluge.plugins[plugin.name] = plugin; - }, - - /** - * @static - * Stop the Deluge UI polling the server and clear the interface. - */ - stop: function () { - if (this.running) { - clearInterval(this.running); - this.running = false; - deluge.torrents.getStore().removeAll(); - } - }, -}; - -Ext.onReady(function (e) { - deluge.ui.initialize(); -}); diff --git a/deluge/ui/web/js/deluge-all.js b/deluge/ui/web/js/deluge-all.js deleted file mode 100644 index f9fd796..0000000 --- a/deluge/ui/web/js/deluge-all.js +++ /dev/null @@ -1,291 +0,0 @@ -Ext.ns("Deluge.add");Deluge.add.Window=Ext.extend(Ext.Window,{initComponent:function(){Deluge.add.Window.superclass.initComponent.call(this);this.addEvents("beforeadd","add","addfailed")},createTorrentId:function(){return(new Date).getTime().toString()}});Ext.namespace("Deluge.add"); -Ext.override(Ext.ux.form.FileUploadField,{onRender:function(a,b){Ext.ux.form.FileUploadField.superclass.onRender.call(this,a,b);this.wrap=this.el.wrap({cls:"x-form-field-wrap x-form-file-wrap"});this.el.addClass("x-form-file-text");this.el.dom.removeAttribute("name");this.createFileInput();var c=Ext.applyIf(this.buttonCfg||{},{text:this.buttonText});this.button=new Ext.Button(Ext.apply(c,{renderTo:this.wrap,cls:"x-form-file-btn"+(c.iconCls?" x-btn-text-icon":"")}));this.buttonOnly&&(this.el.hide(), -this.wrap.setWidth(this.button.getEl().getWidth()));this.bindListeners();this.resizeEl=this.positionEl=this.wrap}}); -Deluge.add.AddWindow=Ext.extend(Deluge.add.Window,{title:_("Add Torrents"),layout:"border",width:470,height:450,bodyStyle:"padding: 10px 5px;",buttonAlign:"right",closeAction:"hide",closable:!0,plain:!0,iconCls:"x-deluge-add-window-icon",initComponent:function(){Deluge.add.AddWindow.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancelClick,this);this.addButton(_("Add"),this.onAddClick,this);this.list=new Ext.list.ListView({store:new Ext.data.SimpleStore({fields:[{name:"info_hash", -mapping:1},{name:"text",mapping:2}],id:0}),columns:[{id:"torrent",width:150,sortable:!0,dataIndex:"text",tpl:new Ext.XTemplate('<div class="x-deluge-add-torrent-name">{text:htmlEncode}</div>')}],stripeRows:!0,singleSelect:!0,listeners:{selectionchange:{fn:this.onSelect,scope:this}},hideHeaders:!0,autoExpandColumn:"torrent",height:"100%",autoScroll:!0});this.add({region:"center",items:[this.list],border:!1,bbar:new Ext.Toolbar({items:[{id:"fileUploadForm",xtype:"form",layout:"fit",baseCls:"x-plain", -fileUpload:!0,items:[{buttonOnly:!0,xtype:"fileuploadfield",id:"torrentFile",name:"file",multiple:!0,buttonCfg:{iconCls:"x-deluge-add-file",text:_("File")},listeners:{scope:this,fileselected:this.onFileSelected}}]},{text:_("Url"),iconCls:"icon-add-url",handler:this.onUrl,scope:this},{text:_("Infohash"),iconCls:"icon-magnet-add",hidden:!0,disabled:!0},"->",{text:_("Remove"),iconCls:"icon-remove",handler:this.onRemove,scope:this}]})});this.fileUploadForm=Ext.getCmp("fileUploadForm").getForm();this.optionsPanel= -this.add(new Deluge.add.OptionsPanel);this.on("hide",this.onHide,this);this.on("show",this.onShow,this)},clear:function(){this.list.getStore().removeAll();this.optionsPanel.clear();this.fileUploadForm.reset()},onAddClick:function(){var a=[];this.list&&(this.list.getStore().each(function(b){b=b.get("info_hash");a.push({path:this.optionsPanel.getFilename(b),options:this.optionsPanel.getOptions(b)})},this),deluge.client.web.add_torrents(a,{success:function(a){}}),this.clear(),this.hide())},onCancelClick:function(){this.clear(); -this.hide()},onFile:function(){this.file||(this.file=new Deluge.add.FileWindow);this.file.show()},onHide:function(){this.optionsPanel.setActiveTab(0);this.optionsPanel.files.setDisabled(!0);this.optionsPanel.form.setDisabled(!0)},onRemove:function(){if(this.list.getSelectionCount()){var a=this.list.getSelectedRecords()[0];a&&(this.list.getStore().remove(a),this.optionsPanel.clear(),this.torrents&&this.torrents[a.id]&&delete this.torrents[a.id])}},onSelect:function(a,b){if(b.length){var c=this.list.getRecord(b[0]); -this.optionsPanel.setTorrent(c.get("info_hash"))}else this.optionsPanel.files.setDisabled(!0),this.optionsPanel.form.setDisabled(!0)},onShow:function(){this.url||(this.url=new Deluge.add.UrlWindow,this.url.on("beforeadd",this.onTorrentBeforeAdd,this),this.url.on("add",this.onTorrentAdd,this),this.url.on("addfailed",this.onTorrentAddFailed,this));this.optionsPanel.form.getDefaults()},onFileSelected:function(){if(this.fileUploadForm.isValid()){var a=[],b=this.fileUploadForm.findField("torrentFile").value, -c=this.createTorrentId();Array.prototype.forEach.call(b,function(b,f){var g=c+f.toString();a.push(g);this.onTorrentBeforeAdd(g,b.name)}.bind(this));this.fileUploadForm.submit({url:deluge.config.base+"upload",waitMsg:_("Uploading your torrent..."),success:this.onUploadSuccess,failure:this.onUploadFailure,scope:this,torrentIds:a})}},onUploadSuccess:function(a,b){b.result.success?(b.result.files.forEach(function(a,d){deluge.client.web.get_torrent_info(a,{success:this.onGotInfo,scope:this,filename:a, -torrentId:b.options.torrentIds[d]})}.bind(this)),this.fileUploadForm.reset()):this.clear()},onUploadFailure:function(a,b){this.hide();Ext.MessageBox.show({title:_("Error"),msg:_("Failed to upload torrent"),buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"});this.fireEvent("addfailed",this.torrentId)},onGotInfo:function(a,b,c,d){a.filename=d.options.filename;torrentId=d.options.torrentId;this.onTorrentAdd(torrentId,a)},onTorrentBeforeAdd:function(a,b){this.list.getStore().loadData([[a, -null,b]],!0)},onTorrentAdd:function(a,b){var c=this.list.getStore().getById(a);b?(c.set("info_hash",b.info_hash),c.set("text",b.name),this.list.getStore().commitChanges(),this.optionsPanel.addTorrent(b),this.list.select(c)):(Ext.MessageBox.show({title:_("Error"),msg:_("Not a valid torrent"),buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"}),this.list.getStore().remove(c))},onTorrentAddFailed:function(a){var b=this.list.getStore();(a=b.getById(a))&&b.remove(a)}, -onUrl:function(a,b){this.url.show()}});Ext.ns("Deluge.add"); -Deluge.add.FilesTab=Ext.extend(Ext.ux.tree.TreeGrid,{layout:"fit",title:_("Files"),autoScroll:!1,animate:!1,border:!1,disabled:!0,rootVisible:!1,columns:[{header:_("Filename"),width:295,dataIndex:"filename",tpl:new Ext.XTemplate("{filename:htmlEncode}")},{header:_("Size"),width:60,dataIndex:"size",tpl:new Ext.XTemplate("{size:this.fsize}",{fsize:function(a){return fsize(a)}})},{header:_("Download"),width:65,dataIndex:"download",tpl:new Ext.XTemplate("{download:this.format}",{format:function(a){return'<div rel="chkbox" class="x-grid3-check-col'+ -(a?"-on":"")+'"> </div>'}})}],initComponent:function(){Deluge.add.FilesTab.superclass.initComponent.call(this);this.on("click",this.onNodeClick,this)},clearFiles:function(){var a=this.getRootNode();a.hasChildNodes()&&a.cascade(function(a){a.parentNode&&a.getOwnerTree()&&a.remove()})},setDownload:function(a,b,c){a.attributes.download=b;a.ui.updateColumns();if(a.isLeaf()){if(!c)return this.fireEvent("fileschecked",[a],b,!b)}else{var d=[a];a.cascade(function(a){a.attributes.download=b;a.ui.updateColumns(); -d.push(a)},this);if(!c)return this.fireEvent("fileschecked",d,b,!b)}},onNodeClick:function(a,b){"chkbox"==(new Ext.Element(b.target)).getAttribute("rel")&&this.setDownload(a,!a.attributes.download)}});Ext.namespace("Ext.deluge.add");Ext.ns("Deluge.add"); -Deluge.add.OptionsPanel=Ext.extend(Ext.TabPanel,{torrents:{},region:"south",border:!1,activeTab:0,height:265,initComponent:function(){Deluge.add.OptionsPanel.superclass.initComponent.call(this);this.files=this.add(new Deluge.add.FilesTab);this.form=this.add(new Deluge.add.OptionsTab);this.files.on("fileschecked",this.onFilesChecked,this)},addTorrent:function(a){this.torrents[a.info_hash]=a;var b={};this.walkFileTree(a.files_tree,function(a,c,g,e){"file"==c&&(b[g.index]=g.download)},this);var c=[]; -Ext.each(Ext.keys(b),function(a){c[a]=b[a]});a=this.form.optionsManager.changeId(a.info_hash,!0);this.form.optionsManager.setDefault("file_priorities",c);this.form.optionsManager.changeId(a,!0)},clear:function(){this.files.clearFiles();this.form.optionsManager.resetAll()},getFilename:function(a){return this.torrents[a].filename},getOptions:function(a){a=this.form.optionsManager.changeId(a,!0);var b=this.form.optionsManager.get();this.form.optionsManager.changeId(a,!0);Ext.each(b.file_priorities,function(a, -d){b.file_priorities[d]=a?1:0});return b},setTorrent:function(a){if(a){this.torrentId=a;this.form.optionsManager.changeId(a);this.files.clearFiles();var b=this.files.getRootNode(),c=this.form.optionsManager.get("file_priorities");this.form.setDisabled(!1);this.torrents[a].files_tree?(this.walkFileTree(this.torrents[a].files_tree,function(a,b,g,e){a=new Ext.tree.TreeNode({download:g.index?c[g.index]:!0,filename:a,fileindex:g.index,leaf:"dir"!=b,size:g.length});e.appendChild(a);if("dir"==b)return a}, -this,b),b.firstChild.expand(),this.files.setDisabled(!1),this.files.show()):(this.form.show(),this.files.setDisabled(!0))}},walkFileTree:function(a,b,c,d){for(var f in a.contents){var g=a.contents[f],e=g.type,l=c?b.apply(c,[f,e,g,d]):b(f,e,g,d);"dir"==e&&this.walkFileTree(g,b,c,l)}},onFilesChecked:function(a,b,c){Ext.each(a,function(a){if(!(0>a.attributes.fileindex)){var c=this.form.optionsManager.get("file_priorities");c[a.attributes.fileindex]=b;this.form.optionsManager.update("file_priorities", -c)}},this)}});Ext.ns("Deluge.add"); -Deluge.add.OptionsTab=Ext.extend(Ext.form.FormPanel,{title:_("Options"),height:170,border:!1,bodyStyle:"padding: 5px",disabled:!0,labelWidth:1,initComponent:function(){Deluge.add.OptionsTab.superclass.initComponent.call(this);this.optionsManager=new Deluge.MultiOptionsManager;var a=this.add({xtype:"fieldset",title:_("Download Folder"),border:!1,autoHeight:!0,defaultType:"textfield",labelWidth:1,fieldLabel:"",style:"padding: 5px 0; margin-bottom: 0;"});this.optionsManager.bind("download_location",a.add({fieldLabel:"", -name:"download_location",anchor:"95%",labelSeparator:""}));a=this.add({xtype:"fieldset",title:_("Move Completed Folder"),border:!1,autoHeight:!0,defaultType:"togglefield",labelWidth:1,fieldLabel:"",style:"padding: 5px 0; margin-bottom: 0;"});a=a.add({fieldLabel:"",name:"move_completed_path",anchor:"98%"});this.optionsManager.bind("move_completed",a.toggle);this.optionsManager.bind("move_completed_path",a.input);var b=this.add({border:!1,layout:"column",defaultType:"fieldset"}),a=b.add({title:_("Bandwidth"), -border:!1,autoHeight:!0,bodyStyle:"padding: 2px 5px",labelWidth:105,width:200,defaultType:"spinnerfield",style:"padding-right: 10px;"});this.optionsManager.bind("max_download_speed",a.add({fieldLabel:_("Max Down Speed"),name:"max_download_speed",width:60}));this.optionsManager.bind("max_upload_speed",a.add({fieldLabel:_("Max Up Speed"),name:"max_upload_speed",width:60}));this.optionsManager.bind("max_connections",a.add({fieldLabel:_("Max Connections"),name:"max_connections",width:60}));this.optionsManager.bind("max_upload_slots", -a.add({fieldLabel:_("Max Upload Slots"),name:"max_upload_slots",width:60}));a=b.add({border:!1,autoHeight:!0,defaultType:"checkbox"});this.optionsManager.bind("add_paused",a.add({name:"add_paused",boxLabel:_("Add In Paused State"),fieldLabel:"",labelSeparator:""}));this.optionsManager.bind("prioritize_first_last_pieces",a.add({name:"prioritize_first_last_pieces",boxLabel:_("Prioritize First/Last Pieces"),fieldLabel:"",labelSeparator:""}));this.optionsManager.bind("sequential_download",a.add({name:"sequential_download", -boxLabel:_("Sequential Download"),fieldLabel:"",labelSeparator:""}));this.optionsManager.bind("seed_mode",a.add({name:"seed_mode",boxLabel:_("Skip File Hash Check"),fieldLabel:"",labelSeparator:""}));this.optionsManager.bind("super_seeding",a.add({name:"super_seeding",boxLabel:_("Super Seed"),fieldLabel:"",labelSeparator:""}));this.optionsManager.bind("pre_allocate_storage",a.add({name:"pre_allocate_storage",boxLabel:_("Preallocate Disk Space"),fieldLabel:"",labelSeparator:""}))},getDefaults:function(){deluge.client.core.get_config_values("add_paused pre_allocate_storage download_location max_connections_per_torrent max_download_speed_per_torrent move_completed move_completed_path max_upload_slots_per_torrent max_upload_speed_per_torrent prioritize_first_last_pieces sequential_download".split(" "), -{success:function(a){this.optionsManager.options={file_priorities:[],add_paused:a.add_paused,sequential_download:a.sequential_download,pre_allocate_storage:a.pre_allocate_storage,download_location:a.download_location,move_completed:a.move_completed,move_completed_path:a.move_completed_path,max_connections:a.max_connections_per_torrent,max_download_speed:a.max_download_speed_per_torrent,max_upload_slots:a.max_upload_slots_per_torrent,max_upload_speed:a.max_upload_speed_per_torrent,prioritize_first_last_pieces:a.prioritize_first_last_pieces, -seed_mode:!1,super_seeding:!1};this.optionsManager.resetAll()},scope:this})}});Ext.namespace("Deluge.add"); -Deluge.add.UrlWindow=Ext.extend(Deluge.add.Window,{title:_("Add from Url"),modal:!0,plain:!0,layout:"fit",width:350,height:155,buttonAlign:"center",closeAction:"hide",bodyStyle:"padding: 10px 5px;",iconCls:"x-deluge-add-url-window-icon",initComponent:function(){Deluge.add.UrlWindow.superclass.initComponent.call(this);this.addButton(_("Add"),this.onAddClick,this);var a=this.add({xtype:"form",defaultType:"textfield",baseCls:"x-plain",labelWidth:55});this.urlField=a.add({fieldLabel:_("Url"),id:"url", -name:"url",width:"97%"});this.urlField.on("specialkey",this.onAdd,this);this.cookieField=a.add({fieldLabel:_("Cookies"),id:"cookies",name:"cookies",width:"97%"});this.cookieField.on("specialkey",this.onAdd,this)},onAddClick:function(a,b){if(!(("url"==a.id||"cookies"==a.id)&&b.getKey()!=b.ENTER)){a=this.urlField;var c=a.getValue(),d=this.cookieField.getValue(),f=this.createTorrentId();0==c.indexOf("magnet:?")&&-1<c.indexOf("xt=urn:btih")?deluge.client.web.get_magnet_info(c,{success:this.onGotInfo, -scope:this,filename:c,torrentId:f}):deluge.client.web.download_torrent_from_url(c,d,{success:this.onDownload,failure:this.onDownloadFailed,scope:this,torrentId:f});this.hide();this.urlField.setValue("");this.fireEvent("beforeadd",f,c)}},onDownload:function(a,b,c,d){deluge.client.web.get_torrent_info(a,{success:this.onGotInfo,failure:this.onDownloadFailed,scope:this,filename:a,torrentId:d.options.torrentId})},onDownloadFailed:function(a,b,c){Ext.MessageBox.show({title:_("Error"),msg:_("Failed to download torrent"), -buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"});this.fireEvent("addfailed",c.options.torrentId)},onGotInfo:function(a,b,c,d){a.filename=d.options.filename;this.fireEvent("add",d.options.torrentId,a)}});Ext.namespace("Deluge.data");Deluge.data.SortTypes={asIPAddress:function(a){a=a.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\:(\d+)/);return 256*(256*(256*+a[1]+ +a[2])+ +a[3])+ +a[4]},asQueuePosition:function(a){return-1<a?a:Number.MAX_VALUE},asName:function(a){return String(a).toLowerCase()}}; -Ext.namespace("Deluge.data");Deluge.data.Peer=Ext.data.Record.create([{name:"country",type:"string"},{name:"ip",type:"string",sortType:Deluge.data.SortTypes.asIPAddress},{name:"client",type:"string"},{name:"progress",type:"float"},{name:"down_speed",type:"int"},{name:"up_speed",type:"int"},{name:"seed",type:"int"}]);Ext.namespace("Deluge.data"); -Deluge.data.Torrent=Ext.data.Record.create([{name:"queue",type:"int"},{name:"name",type:"string",sortType:Deluge.data.SortTypes.asName},{name:"total_wanted",type:"int"},{name:"state",type:"string"},{name:"progress",type:"int"},{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"},{name:"ratio",type:"float"},{name:"distributed_copies", -type:"float"},{name:"time_added",type:"int"},{name:"tracker_host",type:"string"},{name:"save_path",type:"string"},{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"}]);Ext.namespace("Deluge.details"); -Deluge.details.DetailsPanel=Ext.extend(Ext.TabPanel,{id:"torrentDetails",activeTab:0,initComponent:function(){Deluge.details.DetailsPanel.superclass.initComponent.call(this);this.add(new Deluge.details.StatusTab);this.add(new Deluge.details.DetailsTab);this.add(new Deluge.details.FilesTab);this.add(new Deluge.details.PeersTab);this.add(new Deluge.details.OptionsTab)},clear:function(){this.items.each(function(a){a.clear&&(a.clear.defer(100,a),a.disable())})},update:function(a){var b=deluge.torrents.getSelected(); -b?(this.items.each(function(a){a.disabled&&a.enable()}),a=a||this.getActiveTab(),a.update&&a.update(b.id)):this.clear()},onRender:function(a,b){Deluge.details.DetailsPanel.superclass.onRender.call(this,a,b);deluge.events.on("disconnect",this.clear,this);deluge.torrents.on("rowclick",this.onTorrentsClick,this);this.on("tabchange",this.onTabChange,this);deluge.torrents.getSelectionModel().on("selectionchange",function(a){a.hasSelection()||this.clear()},this)},onTabChange:function(a,b){this.update(b)}, -onTorrentsClick:function(a,b,c){this.update()}}); -Deluge.details.DetailsTab=Ext.extend(Ext.Panel,{title:_("Details"),fields:{},autoScroll:!0,queuedItems:{},oldData:{},initComponent:function(){Deluge.details.DetailsTab.superclass.initComponent.call(this);this.addItem("torrent_name",_("Name:"));this.addItem("hash",_("Hash:"));this.addItem("path",_("Download Folder:"));this.addItem("size",_("Total Size:"));this.addItem("files",_("Total Files:"));this.addItem("comment",_("Comment:"));this.addItem("status",_("Status:"));this.addItem("tracker",_("Tracker:")); -this.addItem("creator",_("Created By:"))},onRender:function(a,b){Deluge.details.DetailsTab.superclass.onRender.call(this,a,b);this.body.setStyle("padding","10px");this.dl=Ext.DomHelper.append(this.body,{tag:"dl"},!0);for(var c in this.queuedItems)this.doAddItem(c,this.queuedItems[c])},addItem:function(a,b){this.rendered?this.doAddItem(a,b):this.queuedItems[a]=b},doAddItem:function(a,b){Ext.DomHelper.append(this.dl,{tag:"dt",cls:a,html:b});this.fields[a]=Ext.DomHelper.append(this.dl,{tag:"dd",cls:a, -html:""},!0)},clear:function(){if(this.fields){for(var a in this.fields)this.fields[a].dom.innerHTML="";this.oldData={}}},update:function(a){deluge.client.web.get_torrent_status(a,Deluge.Keys.Details,{success:this.onRequestComplete,scope:this,torrentId:a})},onRequestComplete:function(a,b,c,d){a={torrent_name:a.name,hash:d.options.torrentId,path:a.download_location,size:fsize(a.total_size),files:a.num_files,status:a.message,tracker:a.tracker_host,comment:a.comment,creator:a.creator};for(var f in this.fields)Ext.isDefined(a[f])&& -a[f]!=this.oldData[f]&&(this.fields[f].dom.innerHTML=Ext.util.Format.htmlEncode(a[f]));this.oldData=a}}); -Deluge.details.FilesTab=Ext.extend(Ext.ux.tree.TreeGrid,{title:_("Files"),rootVisible:!1,columns:[{header:_("Filename"),width:330,dataIndex:"filename",tpl:new Ext.XTemplate("{filename:htmlEncode}")},{header:_("Size"),width:150,dataIndex:"size",tpl:new Ext.XTemplate("{size:this.fsize}",{fsize:function(a){return fsize(a)}})},{xtype:"tgrendercolumn",header:_("Progress"),width:150,dataIndex:"progress",renderer:function(a){a*=100;return Deluge.progressBar(a,this.col.width,a.toFixed(2)+"%",0)}},{header:_("Priority"), -width:150,dataIndex:"priority",tpl:new Ext.XTemplate('<tpl if="!isNaN(priority)"><div class="{priority:this.getClass}">{priority:this.getName}</div></tpl>',{getClass:function(a){return FILE_PRIORITY_CSS[a]},getName:function(a){return _(FILE_PRIORITY[a])}})}],selModel:new Ext.tree.MultiSelectionModel,initComponent:function(){Deluge.details.FilesTab.superclass.initComponent.call(this);this.setRootNode(new Ext.tree.TreeNode({text:_("Files")}))},clear:function(){var a=this.getRootNode();a.hasChildNodes()&& -a.cascade(function(a){var c=a.parentNode;c&&c.ownerTree&&c.removeChild(a)})},createFileTree:function(a){function b(a,c){for(var g in a.contents){var e=a.contents[g];"dir"==e.type?b(e,c.appendChild(new Ext.tree.TreeNode({text:g,filename:g,size:e.size,progress:e.progress,priority:e.priority}))):c.appendChild(new Ext.tree.TreeNode({text:g,filename:g,fileIndex:e.index,size:e.size,progress:e.progress,priority:e.priority,leaf:!0,iconCls:"x-deluge-file",uiProvider:Ext.ux.tree.TreeGridNodeUI}))}}var c=this.getRootNode(); -b(a,c);c.firstChild.expand()},update:function(a){this.torrentId!=a&&(this.clear(),this.torrentId=a);deluge.client.web.get_torrent_files(a,{success:this.onRequestComplete,scope:this,torrentId:a})},updateFileTree:function(a){function b(a,d){for(var f in a.contents){var g=a.contents[f],e=d.findChild("filename",f);e.attributes.size=g.size;e.attributes.progress=g.progress;e.attributes.priority=g.priority;e.ui.updateColumns();"dir"==g.type&&b(g,e)}}b(a,this.getRootNode())},onRender:function(a,b){Deluge.details.FilesTab.superclass.onRender.call(this, -a,b);deluge.menus.filePriorities.on("itemclick",this.onItemClick,this);this.on("contextmenu",this.onContextMenu,this);this.sorter=new Ext.tree.TreeSorter(this,{folderSort:!0})},onContextMenu:function(a,b){b.stopEvent();var c=this.getSelectionModel();2>c.getSelectedNodes().length&&(c.clearSelections(),a.select());deluge.menus.filePriorities.showAt(b.getPoint())},onItemClick:function(a,b){switch(a.id){case "expandAll":this.expandAll();break;default:var c={};this.getRootNode().cascade(function(a){Ext.isEmpty(a.attributes.fileIndex)|| -(c[a.attributes.fileIndex]=a.attributes.priority)});var d=this.getSelectionModel().getSelectedNodes();Ext.each(d,function(b){b.isLeaf()?Ext.isEmpty(b.attributes.fileIndex)||(c[b.attributes.fileIndex]=a.filePriority):b.cascade(function(b){Ext.isEmpty(b.attributes.fileIndex)||(c[b.attributes.fileIndex]=a.filePriority)})});var f=Array(Ext.keys(c).length),g;for(g in c)f[g]=c[g];deluge.client.core.set_torrent_options([this.torrentId],{file_priorities:f},{success:function(){Ext.each(d,function(b){b.setColumnValue(3, -a.filePriority)})},scope:this})}},onRequestComplete:function(a,b){this.getRootNode().hasChildNodes()?this.updateFileTree(a):this.createFileTree(a)}}); -Deluge.details.OptionsTab=Ext.extend(Ext.form.FormPanel,{constructor:function(a){a=Ext.apply({autoScroll:!0,bodyStyle:"padding: 5px;",border:!1,cls:"x-deluge-options",defaults:{autoHeight:!0,labelWidth:1,defaultType:"checkbox"},deferredRender:!1,layout:"column",title:_("Options")},a);Deluge.details.OptionsTab.superclass.constructor.call(this,a)},initComponent:function(){Deluge.details.OptionsTab.superclass.initComponent.call(this);this.fieldsets={};this.fields={};this.optionsManager=new Deluge.MultiOptionsManager({options:{max_download_speed:-1, -max_upload_speed:-1,max_connections:-1,max_upload_slots:-1,auto_managed:!1,stop_at_ratio:!1,stop_ratio:2,remove_at_ratio:!1,move_completed:!1,move_completed_path:"","private":!1,prioritize_first_last:!1,super_seeding:!1}});this.fieldsets.bandwidth=this.add({xtype:"fieldset",defaultType:"spinnerfield",bodyStyle:"padding: 5px",layout:"table",layoutConfig:{columns:3},labelWidth:150,style:"margin-left: 10px; margin-right: 5px; padding: 5px",title:_("Bandwidth"),width:250});this.fieldsets.bandwidth.add({xtype:"label", -text:_("Max Download Speed:"),forId:"max_download_speed",cls:"x-deluge-options-label"});this.fields.max_download_speed=this.fieldsets.bandwidth.add({id:"max_download_speed",name:"max_download_speed",width:70,strategy:{xtype:"number",decimalPrecision:1,minValue:-1,maxValue:99999}});this.fieldsets.bandwidth.add({xtype:"label",text:_("KiB/s"),style:"margin-left: 10px"});this.fieldsets.bandwidth.add({xtype:"label",text:_("Max Upload Speed:"),forId:"max_upload_speed",cls:"x-deluge-options-label"});this.fields.max_upload_speed= -this.fieldsets.bandwidth.add({id:"max_upload_speed",name:"max_upload_speed",width:70,value:-1,strategy:{xtype:"number",decimalPrecision:1,minValue:-1,maxValue:99999}});this.fieldsets.bandwidth.add({xtype:"label",text:_("KiB/s"),style:"margin-left: 10px"});this.fieldsets.bandwidth.add({xtype:"label",text:_("Max Connections:"),forId:"max_connections",cls:"x-deluge-options-label"});this.fields.max_connections=this.fieldsets.bandwidth.add({id:"max_connections",name:"max_connections",width:70,value:-1, -strategy:{xtype:"number",decimalPrecision:0,minValue:-1,maxValue:99999},colspan:2});this.fieldsets.bandwidth.add({xtype:"label",text:_("Max Upload Slots:"),forId:"max_upload_slots",cls:"x-deluge-options-label"});this.fields.max_upload_slots=this.fieldsets.bandwidth.add({id:"max_upload_slots",name:"max_upload_slots",width:70,value:-1,strategy:{xtype:"number",decimalPrecision:0,minValue:-1,maxValue:99999},colspan:2});this.fieldsets.queue=this.add({xtype:"fieldset",title:_("Queue"),style:"margin-left: 5px; margin-right: 5px; padding: 5px", -width:210,layout:"table",layoutConfig:{columns:2},labelWidth:0,defaults:{fieldLabel:"",labelSeparator:""}});this.fields.auto_managed=this.fieldsets.queue.add({xtype:"checkbox",fieldLabel:"",labelSeparator:"",name:"is_auto_managed",boxLabel:_("Auto Managed"),width:200,colspan:2});this.fields.stop_at_ratio=this.fieldsets.queue.add({fieldLabel:"",labelSeparator:"",id:"stop_at_ratio",width:120,boxLabel:_("Stop seed at ratio:"),handler:this.onStopRatioChecked,scope:this});this.fields.stop_ratio=this.fieldsets.queue.add({xtype:"spinnerfield", -id:"stop_ratio",name:"stop_ratio",disabled:!0,width:50,value:2,strategy:{xtype:"number",minValue:-1,maxValue:99999,incrementValue:0.1,alternateIncrementValue:1,decimalPrecision:1}});this.fields.remove_at_ratio=this.fieldsets.queue.add({fieldLabel:"",labelSeparator:"",id:"remove_at_ratio",ctCls:"x-deluge-indent-checkbox",bodyStyle:"padding-left: 10px",boxLabel:_("Remove at ratio"),disabled:!0,colspan:2});this.fields.move_completed=this.fieldsets.queue.add({fieldLabel:"",labelSeparator:"",id:"move_completed", -boxLabel:_("Move Completed:"),colspan:2,handler:this.onMoveCompletedChecked,scope:this});this.fields.move_completed_path=this.fieldsets.queue.add({xtype:"textfield",fieldLabel:"",id:"move_completed_path",colspan:3,bodyStyle:"margin-left: 20px",width:180,disabled:!0});this.rightColumn=this.add({border:!1,autoHeight:!0,style:"margin-left: 5px",width:210});this.fieldsets.general=this.rightColumn.add({xtype:"fieldset",autoHeight:!0,defaultType:"checkbox",title:_("General"),layout:"form"});this.fields["private"]= -this.fieldsets.general.add({fieldLabel:"",labelSeparator:"",boxLabel:_("Private"),id:"private",disabled:!0});this.fields.prioritize_first_last=this.fieldsets.general.add({fieldLabel:"",labelSeparator:"",boxLabel:_("Prioritize First/Last"),id:"prioritize_first_last"});this.fields.super_seeding=this.fieldsets.general.add({fieldLabel:"",labelSeparator:"",boxLabel:_("Super Seeding"),id:"super_seeding"});for(var a in this.fields)this.optionsManager.bind(a,this.fields[a]);this.buttonPanel=this.rightColumn.add({layout:"hbox", -xtype:"panel",border:!1});this.buttonPanel.add({id:"edit_trackers",xtype:"button",text:_("Edit Trackers"),cls:"x-btn-text-icon",iconCls:"x-deluge-edit-trackers",border:!1,width:100,handler:this.onEditTrackers,scope:this});this.buttonPanel.add({id:"apply",xtype:"button",text:_("Apply"),style:"margin-left: 10px;",border:!1,width:100,handler:this.onApply,scope:this})},onRender:function(a,b){Deluge.details.OptionsTab.superclass.onRender.call(this,a,b);this.layout=new Ext.layout.ColumnLayout;this.layout.setContainer(this); -this.doLayout()},clear:function(){null!=this.torrentId&&(this.torrentId=null,this.optionsManager.changeId(null))},reset:function(){this.torrentId&&this.optionsManager.reset()},update:function(a){this.torrentId&&!a&&this.clear();a&&(this.torrentId!=a&&(this.torrentId=a,this.optionsManager.changeId(a)),deluge.client.web.get_torrent_status(a,Deluge.Keys.Options,{success:this.onRequestComplete,scope:this}))},onApply:function(){var a=this.optionsManager.getDirty();deluge.client.core.set_torrent_options([this.torrentId], -a,{success:function(){this.optionsManager.commit()},scope:this})},onEditTrackers:function(){deluge.editTrackers.show()},onMoveCompletedChecked:function(a,b){this.fields.move_completed_path.setDisabled(!b);b&&this.fields.move_completed_path.focus()},onStopRatioChecked:function(a,b){this.fields.remove_at_ratio.setDisabled(!b);this.fields.stop_ratio.setDisabled(!b)},onRequestComplete:function(a,b){this.fields["private"].setValue(a["private"]);this.fields["private"].setDisabled(!0);delete a["private"]; -a.auto_managed=a.is_auto_managed;a.prioritize_first_last_pieces=a.prioritize_first_last;this.optionsManager.setDefault(a);var c=this.optionsManager.get("stop_at_ratio");this.fields.remove_at_ratio.setDisabled(!c);this.fields.stop_ratio.setDisabled(!c);this.fields.move_completed_path.setDisabled(!this.optionsManager.get("move_completed"))}}); -(function(){function a(a){return!a.replace(" ","").replace(" ","")?"":String.format('<img alt="{1}" title="{1}" src="{0}flag/{1}" />',deluge.config.base,a)}function b(a,b,c){b=1024==c.data.seed?"x-deluge-seed":"x-deluge-peer";c=a.split(":");2<c.length&&(a=c.pop(),a="["+c.join(":")+"]:"+a);return String.format('<div class="{0}">{1}</div>',b,a)}function c(a){a=(100*a).toFixed(0);return Deluge.progressBar(a,this.width-8,a+"%")}Deluge.details.PeersTab=Ext.extend(Ext.grid.GridPanel,{peers:{},constructor:function(d){d= -Ext.apply({title:_("Peers"),cls:"x-deluge-peers",store:new Ext.data.Store({reader:new Ext.data.JsonReader({idProperty:"ip",root:"peers"},Deluge.data.Peer)}),columns:[{header:" ",width:30,sortable:!0,renderer:a,dataIndex:"country"},{header:_("Address"),width:125,sortable:!0,renderer:b,dataIndex:"ip"},{header:_("Client"),width:125,sortable:!0,renderer:"htmlEncode",dataIndex:"client"},{header:_("Progress"),width:150,sortable:!0,renderer:c,dataIndex:"progress"},{header:_("Down Speed"),width:100, -sortable:!0,renderer:fspeed,dataIndex:"down_speed"},{header:_("Up Speed"),width:100,sortable:!0,renderer:fspeed,dataIndex:"up_speed"}],stripeRows:!0,deferredRender:!1,autoScroll:!0},d);Deluge.details.PeersTab.superclass.constructor.call(this,d)},clear:function(){this.getStore().removeAll();this.peers={}},update:function(a){deluge.client.web.get_torrent_status(a,Deluge.Keys.Peers,{success:this.onRequestComplete,scope:this})},onRequestComplete:function(a,b){if(a){var c=this.getStore(),e=[],l={};Ext.each(a.peers, -function(a){if(this.peers[a.ip]){var b=c.getById(a.ip);b.beginEdit();for(var d in a)b.get(d)!=a[d]&&b.set(d,a[d]);b.endEdit()}else this.peers[a.ip]=1,e.push(new Deluge.data.Peer(a,a.ip));l[a.ip]=1},this);c.add(e);c.each(function(a){l[a.id]||(c.remove(a),delete this.peers[a.id])},this);c.commitChanges();var h=c.getSortState();h&&c.sort(h.field,h.direction)}}})})();Ext.ns("Deluge.details"); -Deluge.details.StatusTab=Ext.extend(Ext.Panel,{title:_("Status"),autoScroll:!0,onRender:function(a,b){Deluge.details.StatusTab.superclass.onRender.call(this,a,b);this.progressBar=this.add({xtype:"progress",cls:"x-deluge-status-progressbar"});this.status=this.add({cls:"x-deluge-status",id:"deluge-details-status",border:!1,width:1E3,listeners:{render:{fn:function(a){a.load({url:deluge.config.base+"render/tab_status.html",text:_("Loading")+"..."});a.getUpdater().on("update",this.onPanelUpdate,this)}, -scope:this}}})},clear:function(){this.progressBar.updateProgress(0," ");for(var a in this.fields)this.fields[a].innerHTML=""},update:function(a){this.fields||this.getFields();deluge.client.web.get_torrent_status(a,Deluge.Keys.Status,{success:this.onRequestComplete,scope:this})},onPanelUpdate:function(a,b){this.fields={};Ext.each(Ext.query("dd",this.status.body.dom),function(a){this.fields[a.className]=a},this)},onRequestComplete:function(a){seeds=-1<a.total_seeds?a.num_seeds+" ("+a.total_seeds+")": -a.num_seeds;peers=-1<a.total_peers?a.num_peers+" ("+a.total_peers+")":a.num_peers;last_seen_complete=0<a.last_seen_complete?fdate(a.last_seen_complete):"Never";completed_time=0<a.completed_time?fdate(a.completed_time):"";var b={downloaded:fsize(a.total_done,!0),uploaded:fsize(a.total_uploaded,!0),share:-1==a.ratio?"∞":a.ratio.toFixed(3),announce:ftime(a.next_announce),tracker_status:a.tracker_status,downspeed:a.download_payload_rate?fspeed(a.download_payload_rate):"0.0 KiB/s",upspeed:a.upload_payload_rate? -fspeed(a.upload_payload_rate):"0.0 KiB/s",eta:0>a.eta?"∞":ftime(a.eta),pieces:a.num_pieces+" ("+fsize(a.piece_length)+")",seeds:seeds,peers:peers,avail:a.distributed_copies.toFixed(3),active_time:ftime(a.active_time),seeding_time:ftime(a.seeding_time),seed_rank:a.seed_rank,time_added:fdate(a.time_added),last_seen_complete:last_seen_complete,completed_time:completed_time,time_since_transfer:ftime(a.time_since_transfer)};b.auto_managed=_(a.is_auto_managed?"True":"False");var c={Error:_("Error"), -Warning:_("Warning"),"Announce OK":_("Announce OK"),"Announce Sent":_("Announce Sent")},d;for(d in c)if(-1!=b.tracker_status.indexOf(d)){b.tracker_status=b.tracker_status.replace(d,c[d]);break}b.downloaded+=" ("+(a.total_payload_download?fsize(a.total_payload_download):"0.0 KiB")+")";b.uploaded+=" ("+(a.total_payload_upload?fsize(a.total_payload_upload):"0.0 KiB")+")";for(var f in this.fields)this.fields[f].innerHTML=b[f];b=a.state+" "+a.progress.toFixed(2)+"%";this.progressBar.updateProgress(a.progress/ -100,b)}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Bandwidth=Ext.extend(Ext.form.FormPanel,{constructor:function(a){a=Ext.apply({border:!1,title:_("Bandwidth"),header:!1,layout:"form",labelWidth:10},a);Deluge.preferences.Bandwidth.superclass.constructor.call(this,a)},initComponent:function(){Deluge.preferences.Bandwidth.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("Global Bandwidth Usage"),labelWidth:200,defaultType:"spinnerfield",defaults:{minValue:-1, -maxValue:99999},style:"margin-bottom: 0px; padding-bottom: 0px;",autoHeight:!0});a.bind("max_connections_global",b.add({name:"max_connections_global",fieldLabel:_("Maximum Connections:"),labelSeparator:"",width:80,value:-1,decimalPrecision:0}));a.bind("max_upload_slots_global",b.add({name:"max_upload_slots_global",fieldLabel:_("Maximum Upload Slots"),labelSeparator:"",width:80,value:-1,decimalPrecision:0}));a.bind("max_download_speed",b.add({name:"max_download_speed",fieldLabel:_("Maximum Download Speed (KiB/s):"), -labelSeparator:"",width:80,value:-1,decimalPrecision:1}));a.bind("max_upload_speed",b.add({name:"max_upload_speed",fieldLabel:_("Maximum Upload Speed (KiB/s):"),labelSeparator:"",width:80,value:-1,decimalPrecision:1}));a.bind("max_half_open_connections",b.add({name:"max_half_open_connections",fieldLabel:_("Maximum Half-Open Connections:"),labelSeparator:"",width:80,value:-1,decimalPrecision:0}));a.bind("max_connections_per_second",b.add({name:"max_connections_per_second",fieldLabel:_("Maximum Connection Attempts per Second:"), -labelSeparator:"",width:80,value:-1,decimalPrecision:0}));b=this.add({xtype:"fieldset",border:!1,title:"",defaultType:"checkbox",style:"padding-top: 0px; padding-bottom: 5px; margin-top: 0px; margin-bottom: 0px;",autoHeight:!0});a.bind("ignore_limits_on_local_network",b.add({name:"ignore_limits_on_local_network",height:22,fieldLabel:"",labelSeparator:"",boxLabel:_("Ignore limits on local network")}));a.bind("rate_limit_ip_overhead",b.add({name:"rate_limit_ip_overhead",height:22,fieldLabel:"",labelSeparator:"", -boxLabel:_("Rate limit IP overhead")}));b=this.add({xtype:"fieldset",border:!1,title:_("Per Torrent Bandwidth Usage"),style:"margin-bottom: 0px; padding-bottom: 0px;",defaultType:"spinnerfield",labelWidth:200,defaults:{minValue:-1,maxValue:99999},autoHeight:!0});a.bind("max_connections_per_torrent",b.add({name:"max_connections_per_torrent",fieldLabel:_("Maximum Connections:"),labelSeparator:"",width:80,value:-1,decimalPrecision:0}));a.bind("max_upload_slots_per_torrent",b.add({name:"max_upload_slots_per_torrent", -fieldLabel:_("Maximum Upload Slots:"),labelSeparator:"",width:80,value:-1,decimalPrecision:0}));a.bind("max_download_speed_per_torrent",b.add({name:"max_download_speed_per_torrent",fieldLabel:_("Maximum Download Speed (KiB/s):"),labelSeparator:"",width:80,value:-1,decimalPrecision:0}));a.bind("max_upload_speed_per_torrent",b.add({name:"max_upload_speed_per_torrent",fieldLabel:_("Maximum Upload Speed (KiB/s):"),labelSeparator:"",width:80,value:-1,decimalPrecision:0}))}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Cache=Ext.extend(Ext.form.FormPanel,{border:!1,title:_("Cache"),header:!1,layout:"form",initComponent:function(){Deluge.preferences.Cache.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("Settings"),autoHeight:!0,labelWidth:180,defaultType:"spinnerfield",defaults:{decimalPrecision:0,minValue:-1,maxValue:999999}});a.bind("cache_size",b.add({fieldLabel:_("Cache Size (16 KiB Blocks):"),labelSeparator:"", -name:"cache_size",width:60,value:512}));a.bind("cache_expiry",b.add({fieldLabel:_("Cache Expiry (seconds):"),labelSeparator:"",name:"cache_expiry",width:60,value:60}))}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Daemon=Ext.extend(Ext.form.FormPanel,{border:!1,title:_("Daemon"),header:!1,layout:"form",initComponent:function(){Deluge.preferences.Daemon.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("Port"),autoHeight:!0,defaultType:"spinnerfield"});a.bind("daemon_port",b.add({fieldLabel:_("Daemon port:"),labelSeparator:"",name:"daemon_port",value:58846,decimalPrecision:0,minValue:-1,maxValue:99999}));b=this.add({xtype:"fieldset", -border:!1,title:_("Connections"),autoHeight:!0,labelWidth:1,defaultType:"checkbox"});a.bind("allow_remote",b.add({fieldLabel:"",height:22,labelSeparator:"",boxLabel:_("Allow Remote Connections"),name:"allow_remote"}));b=this.add({xtype:"fieldset",border:!1,title:_("Other"),autoHeight:!0,labelWidth:1,defaultType:"checkbox"});a.bind("new_release_check",b.add({fieldLabel:"",labelSeparator:"",height:40,boxLabel:_("Periodically check the website for new releases"),id:"new_release_check"}))}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Downloads=Ext.extend(Ext.FormPanel,{constructor:function(a){a=Ext.apply({border:!1,title:_("Downloads"),header:!1,layout:"form",autoHeight:!0,width:320},a);Deluge.preferences.Downloads.superclass.constructor.call(this,a)},initComponent:function(){Deluge.preferences.Downloads.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("Folders"),labelWidth:150,defaultType:"togglefield",autoHeight:!0,labelAlign:"top", -width:300,style:"margin-bottom: 5px; padding-bottom: 5px;"});a.bind("download_location",b.add({xtype:"textfield",name:"download_location",fieldLabel:_("Download to:"),labelSeparator:"",width:280}));var c=b.add({name:"move_completed_path",fieldLabel:_("Move completed to:"),labelSeparator:"",width:280});a.bind("move_completed",c.toggle);a.bind("move_completed_path",c.input);c=b.add({name:"torrentfiles_location",fieldLabel:_("Copy of .torrent files to:"),labelSeparator:"",width:280});a.bind("copy_torrent_file", -c.toggle);a.bind("torrentfiles_location",c.input);b=this.add({xtype:"fieldset",border:!1,title:_("Options"),autoHeight:!0,labelWidth:1,defaultType:"checkbox",style:"margin-bottom: 0; padding-bottom: 0;",width:280});a.bind("prioritize_first_last_pieces",b.add({name:"prioritize_first_last_pieces",labelSeparator:"",height:22,boxLabel:_("Prioritize first and last pieces of torrent")}));a.bind("sequential_download",b.add({name:"sequential_download",labelSeparator:"",height:22,boxLabel:_("Sequential download")})); -a.bind("add_paused",b.add({name:"add_paused",labelSeparator:"",height:22,boxLabel:_("Add torrents in Paused state")}));a.bind("pre_allocate_storage",b.add({name:"pre_allocate_storage",labelSeparator:"",height:22,boxLabel:_("Pre-allocate disk space")}))}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Encryption=Ext.extend(Ext.form.FormPanel,{border:!1,title:_("Encryption"),header:!1,initComponent:function(){Deluge.preferences.Encryption.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("Settings"),header:!1,autoHeight:!0,defaultType:"combo",width:300});a.bind("enc_in_policy",b.add({fieldLabel:_("Incoming:"),labelSeparator:"",mode:"local",width:150,store:new Ext.data.ArrayStore({fields:["id","text"], -data:[[0,_("Forced")],[1,_("Enabled")],[2,_("Disabled")]]}),editable:!1,triggerAction:"all",valueField:"id",displayField:"text"}));a.bind("enc_out_policy",b.add({fieldLabel:_("Outgoing:"),labelSeparator:"",mode:"local",width:150,store:new Ext.data.SimpleStore({fields:["id","text"],data:[[0,_("Forced")],[1,_("Enabled")],[2,_("Disabled")]]}),editable:!1,triggerAction:"all",valueField:"id",displayField:"text"}));a.bind("enc_level",b.add({fieldLabel:_("Level:"),labelSeparator:"",mode:"local",width:150, -store:new Ext.data.SimpleStore({fields:["id","text"],data:[[0,_("Handshake")],[1,_("Full Stream")],[2,_("Either")]]}),editable:!1,triggerAction:"all",valueField:"id",displayField:"text"}))}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.InstallPluginWindow=Ext.extend(Ext.Window,{title:_("Install Plugin"),layout:"fit",height:115,width:350,constrainHeader:!0,bodyStyle:"padding: 10px 5px;",buttonAlign:"center",closeAction:"hide",iconCls:"x-deluge-install-plugin",modal:!0,plain:!0,initComponent:function(){Deluge.preferences.InstallPluginWindow.superclass.initComponent.call(this);this.addButton(_("Install"),this.onInstall,this);this.form=this.add({xtype:"form",baseCls:"x-plain",labelWidth:70,autoHeight:!0,fileUpload:!0, -items:[{xtype:"fileuploadfield",width:240,emptyText:_("Select an egg"),fieldLabel:_("Plugin Egg"),name:"file",buttonCfg:{text:_("Browse...")}}]})},onInstall:function(a,b){this.form.getForm().submit({url:deluge.config.base+"upload",waitMsg:_("Uploading your plugin..."),success:this.onUploadSuccess,scope:this})},onUploadPlugin:function(a,b,c,d){this.fireEvent("pluginadded")},onUploadSuccess:function(a,b){this.hide();if(b.result.success){var c=this.form.getForm().getFieldValues().file,c=c.split("\\").slice(-1)[0], -d=b.result.files[0];this.form.getForm().setValues({file:""});deluge.client.web.upload_plugin(c,d,{success:this.onUploadPlugin,scope:this,filename:c})}}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Interface=Ext.extend(Ext.form.FormPanel,{border:!1,title:_("Interface"),header:!1,layout:"form",initComponent:function(){Deluge.preferences.Interface.superclass.initComponent.call(this);var a=this.optionsManager=new Deluge.OptionsManager;this.on("show",this.onPageShow,this);var b=this.add({xtype:"fieldset",border:!1,title:_("Interface"),style:"margin-bottom: 0px; padding-bottom: 5px; padding-top: 5px",autoHeight:!0,labelWidth:1,defaultType:"checkbox",defaults:{height:17,fieldLabel:"", -labelSeparator:""}});a.bind("show_session_speed",b.add({name:"show_session_speed",boxLabel:_("Show session speed in titlebar")}));a.bind("sidebar_show_zero",b.add({name:"sidebar_show_zero",boxLabel:_("Show filters with zero torrents")}));a.bind("sidebar_multiple_filters",b.add({name:"sidebar_multiple_filters",boxLabel:_("Allow the use of multiple filters at once")}));b=this.add({xtype:"fieldset",border:!1,title:_("Language"),style:"margin-bottom: 0px; padding-bottom: 5px; padding-top: 5px",autoHeight:!0, -labelWidth:1,defaultType:"checkbox"});this.language=a.bind("language",b.add({xtype:"combo",labelSeparator:"",name:"language",mode:"local",width:200,store:new Ext.data.ArrayStore({fields:["id","text"]}),editable:!1,triggerAction:"all",valueField:"id",displayField:"text"}));b=this.add({xtype:"fieldset",border:!1,title:_("WebUI Password"),style:"margin-bottom: 0px; padding-bottom: 5px; padding-top: 5px",autoHeight:!0,labelWidth:100,defaultType:"textfield",defaults:{width:100,inputType:"password",labelStyle:"padding-left: 5px", -height:20,labelSeparator:""}});this.oldPassword=b.add({name:"old_password",fieldLabel:_("Old:")});this.newPassword=b.add({name:"new_password",fieldLabel:_("New:")});this.confirmPassword=b.add({name:"confirm_password",fieldLabel:_("Confirm:")});b=this.add({xtype:"fieldset",border:!1,title:_("Server"),style:"padding-top: 5px; margin-bottom: 0px; padding-bottom: 5px",autoHeight:!0,labelWidth:100,defaultType:"spinnerfield",defaults:{labelSeparator:"",labelStyle:"padding-left: 5px",height:20,width:80}}); -a.bind("session_timeout",b.add({name:"session_timeout",fieldLabel:_("Session Timeout:"),decimalPrecision:0,minValue:-1,maxValue:99999}));a.bind("port",b.add({name:"port",fieldLabel:_("Port:"),decimalPrecision:0,minValue:1,maxValue:65535}));this.httpsField=a.bind("https",b.add({xtype:"checkbox",name:"https",hideLabel:!0,width:300,style:"margin-left: 5px",boxLabel:_("Enable SSL (paths relative to Deluge config folder)")}));this.httpsField.on("check",this.onSSLCheck,this);this.pkeyField=a.bind("pkey", -b.add({xtype:"textfield",disabled:!0,name:"pkey",width:180,fieldLabel:_("Private Key:")}));this.certField=a.bind("cert",b.add({xtype:"textfield",disabled:!0,name:"cert",width:180,fieldLabel:_("Certificate:")}))},onApply:function(){var a=this.optionsManager.getDirty();if(!Ext.isObjectEmpty(a)){deluge.client.web.set_config(a,{success:this.onSetConfig,scope:this});for(var b in deluge.config)deluge.config[b]=this.optionsManager.get(b);"language"in a&&Ext.Msg.show({title:_("WebUI Language Changed"),msg:_("Do you want to refresh the page now to use the new language?"), -buttons:{yes:_("Refresh"),no:_("Close")},multiline:!1,fn:function(a){"yes"===a&&location.reload()},icon:Ext.MessageBox.QUESTION})}if(this.oldPassword.getValue()||this.newPassword.getValue())this.onPasswordChange()},onOk:function(){this.onApply()},onGotConfig:function(a){this.optionsManager.set(a)},onGotLanguages:function(a,b,c,d){a.unshift(["",_("System Default")]);this.language.store.loadData(a);this.language.setValue(this.optionsManager.get("language"))},onPasswordChange:function(){var a=this.newPassword.getValue(); -if(a!=this.confirmPassword.getValue())Ext.MessageBox.show({title:_("Invalid Password"),msg:_("Your passwords don't match!"),buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"});else{var b=this.oldPassword.getValue();deluge.client.auth.change_password(b,a,{success:function(a){a?(Ext.MessageBox.show({title:_("Change Successful"),msg:_("Your password was successfully changed!"),buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.INFO,iconCls:"x-deluge-icon-info"}), -this.oldPassword.setValue(""),this.newPassword.setValue(""),this.confirmPassword.setValue("")):(Ext.MessageBox.show({title:_("Password"),msg:_("Your old password was incorrect!"),buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"}),this.oldPassword.setValue(""))},scope:this})}},onSetConfig:function(){this.optionsManager.commit()},onPageShow:function(){deluge.client.web.get_config({success:this.onGotConfig,scope:this});deluge.client.webutils.get_languages({success:this.onGotLanguages, -scope:this})},onSSLCheck:function(a,b){this.pkeyField.setDisabled(!b);this.certField.setDisabled(!b)}});Ext.namespace("Deluge.preferences");Ext.apply(Ext.form.VTypes,{IPAddress:function(a){return/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(a)},IPAddressText:"Must be a numeric IP address",IPAddressMask:/[\d\.]/i}); -Deluge.preferences.Network=Ext.extend(Ext.form.FormPanel,{border:!1,layout:"form",title:_("Network"),header:!1,initComponent:function(){Deluge.preferences.Network.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("Incoming Address"),style:"margin-bottom: 5px; padding-bottom: 0px;",autoHeight:!0,labelWidth:1,defaultType:"textfield"});a.bind("listen_interface",b.add({name:"listen_interface",fieldLabel:"",labelSeparator:"", -width:200,vtype:"IPAddress"}));var b=this.add({xtype:"fieldset",border:!1,title:_("Incoming Port"),style:"margin-bottom: 5px; padding-bottom: 0px;",autoHeight:!0,labelWidth:1,defaultType:"checkbox"});a.bind("random_port",b.add({fieldLabel:"",labelSeparator:"",boxLabel:_("Use Random Port"),name:"random_port",height:22,listeners:{check:{fn:function(a,b){this.listenPort.setDisabled(b)},scope:this}}}));this.listenPort=b.add({xtype:"spinnerfield",name:"listen_port",fieldLabel:"",labelSeparator:"",width:75, -strategy:{xtype:"number",decimalPrecision:0,minValue:0,maxValue:65535}});a.bind("listen_ports",this.listenPort);b=this.add({xtype:"fieldset",border:!1,title:_("Outgoing Interface"),style:"margin-bottom: 5px; padding-bottom: 0px;",autoHeight:!0,labelWidth:1,defaultType:"textfield"});a.bind("outgoing_interface",b.add({name:"outgoing_interface",fieldLabel:"",labelSeparator:"",width:40}));b=this.add({xtype:"fieldset",border:!1,title:_("Outgoing Ports"),style:"margin-bottom: 5px; padding-bottom: 0px;", -autoHeight:!0,labelWidth:1,defaultType:"checkbox"});a.bind("random_outgoing_ports",b.add({fieldLabel:"",labelSeparator:"",boxLabel:_("Use Random Ports"),name:"random_outgoing_ports",height:22,listeners:{check:{fn:function(a,b){this.outgoingPorts.setDisabled(b)},scope:this}}}));this.outgoingPorts=b.add({xtype:"spinnergroup",name:"outgoing_ports",fieldLabel:"",labelSeparator:"",colCfg:{labelWidth:40,style:"margin-right: 10px;"},items:[{fieldLabel:_("From:"),labelSeparator:"",strategy:{xtype:"number", -decimalPrecision:0,minValue:0,maxValue:65535}},{fieldLabel:_("To:"),labelSeparator:"",strategy:{xtype:"number",decimalPrecision:0,minValue:0,maxValue:65535}}]});a.bind("outgoing_ports",this.outgoingPorts);b=this.add({xtype:"fieldset",border:!1,title:_("Network Extras"),autoHeight:!0,layout:"table",layoutConfig:{columns:3},defaultType:"checkbox"});a.bind("upnp",b.add({fieldLabel:"",labelSeparator:"",boxLabel:_("UPnP"),name:"upnp"}));a.bind("natpmp",b.add({fieldLabel:"",labelSeparator:"",boxLabel:_("NAT-PMP"), -ctCls:"x-deluge-indent-checkbox",name:"natpmp"}));a.bind("utpex",b.add({fieldLabel:"",labelSeparator:"",boxLabel:_("Peer Exchange"),ctCls:"x-deluge-indent-checkbox",name:"utpex"}));a.bind("lsd",b.add({fieldLabel:"",labelSeparator:"",boxLabel:_("LSD"),name:"lsd"}));a.bind("dht",b.add({fieldLabel:"",labelSeparator:"",boxLabel:_("DHT"),ctCls:"x-deluge-indent-checkbox",name:"dht"}));b=this.add({xtype:"fieldset",border:!1,title:_("Type Of Service"),style:"margin-bottom: 5px; padding-bottom: 0px;",bodyStyle:"margin: 0px; padding: 0px", -autoHeight:!0,defaultType:"textfield"});a.bind("peer_tos",b.add({name:"peer_tos",fieldLabel:_("Peer TOS Byte:"),labelSeparator:"",width:40}))}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Other=Ext.extend(Ext.form.FormPanel,{constructor:function(a){a=Ext.apply({border:!1,title:_("Other"),header:!1,layout:"form"},a);Deluge.preferences.Other.superclass.constructor.call(this,a)},initComponent:function(){Deluge.preferences.Other.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("Updates"),autoHeight:!0,labelWidth:1,defaultType:"checkbox"});a.bind("new_release_check",b.add({fieldLabel:"",labelSeparator:"", -height:22,name:"new_release_check",boxLabel:_("Be alerted about new releases")}));b=this.add({xtype:"fieldset",border:!1,title:_("System Information"),autoHeight:!0,labelWidth:1,defaultType:"checkbox"});b.add({xtype:"panel",border:!1,bodyCfg:{html:_("Help us improve Deluge by sending us your Python version, PyGTK version, OS and processor types. Absolutely no other information is sent.")}});a.bind("send_info",b.add({fieldLabel:"",labelSeparator:"",height:22,boxLabel:_("Yes, please send anonymous statistics"), -name:"send_info"}));b=this.add({xtype:"fieldset",border:!1,title:_("GeoIP Database"),autoHeight:!0,labelWidth:80,defaultType:"textfield"});a.bind("geoip_db_location",b.add({name:"geoip_db_location",fieldLabel:_("Path:"),labelSeparator:"",width:200}))}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Plugins=Ext.extend(Ext.Panel,{layout:"border",title:_("Plugins"),header:!1,border:!1,cls:"x-deluge-plugins",pluginTemplate:new Ext.Template('<dl class="singleline"><dt>'+_("Author:")+"</dt><dd>{author}</dd><dt>"+_("Version:")+"</dt><dd>{version}</dd><dt>"+_("Author Email:")+"</dt><dd>{email}</dd><dt>"+_("Homepage:")+"</dt><dd>{homepage}</dd><dt>"+_("Details:")+'</dt><dd style="white-space:normal">{details}</dd></dl>'),initComponent:function(){Deluge.preferences.Plugins.superclass.initComponent.call(this); -this.defaultValues={version:"",email:"",homepage:"",details:""};this.pluginTemplate.compile();this.list=this.add({xtype:"listview",store:new Ext.data.ArrayStore({fields:[{name:"enabled",mapping:0},{name:"plugin",mapping:1,sortType:"asUCString"}]}),columns:[{id:"enabled",header:_("Enabled"),width:0.2,sortable:!0,tpl:new Ext.XTemplate("{enabled:this.getCheckbox}",{getCheckbox:function(a){return'<div class="x-grid3-check-col'+(a?"-on":"")+'" rel="chkbox"> </div>'}}),dataIndex:"enabled"},{id:"plugin", -header:_("Plugin"),width:0.8,sortable:!0,dataIndex:"plugin"}],singleSelect:!0,autoExpandColumn:"plugin",listeners:{selectionchange:{fn:this.onPluginSelect,scope:this}}});this.panel=this.add({region:"center",autoScroll:!0,items:[this.list],bbar:new Ext.Toolbar({items:[{cls:"x-btn-text-icon",iconCls:"x-deluge-install-plugin",text:_("Install"),handler:this.onInstallPluginWindow,scope:this},"->",{cls:"x-btn-text-icon",text:_("Find More"),iconCls:"x-deluge-find-more",handler:this.onFindMorePlugins,scope:this}]})}); -this.pluginInfo=this.add({xtype:"panel",border:!1,height:100,region:"south",padding:"5",autoScroll:!0,bodyCfg:{style:"white-space: nowrap"}});this.pluginInfo.on("render",this.onPluginInfoRender,this);this.list.on("click",this.onNodeClick,this);deluge.preferences.on("show",this.onPreferencesShow,this);deluge.events.on("PluginDisabledEvent",this.onPluginDisabled,this);deluge.events.on("PluginEnabledEvent",this.onPluginEnabled,this)},disablePlugin:function(a){deluge.client.core.disable_plugin(a)},enablePlugin:function(a){deluge.client.core.enable_plugin(a)}, -setInfo:function(a){this.pluginInfo.rendered&&(this.pluginInfo.body.dom.innerHTML=this.pluginTemplate.apply(a||this.defaultValues))},updatePlugins:function(){var a=function(a){this.enabledPlugins=a;this.onGotPlugins()};deluge.client.core.get_available_plugins({success:function(b){this.availablePlugins=b.sort(function(a,b){return a.toLowerCase().localeCompare(b.toLowerCase())});deluge.client.core.get_enabled_plugins({success:a,scope:this})},scope:this})},updatePluginsGrid:function(){var a=[];Ext.each(this.availablePlugins, -function(b){-1<this.enabledPlugins.indexOf(b)?a.push([!0,b]):a.push([!1,b])},this);this.list.getStore().loadData(a)},onNodeClick:function(a,b,c,d){"chkbox"==(new Ext.Element(d.target)).getAttribute("rel")&&(a=a.getStore().getAt(b),"WebUi"!=a.get("plugin")&&(a.set("enabled",!a.get("enabled")),a.commit(),a.get("enabled")?this.enablePlugin(a.get("plugin")):this.disablePlugin(a.get("plugin"))))},onFindMorePlugins:function(){window.open("http://dev.deluge-torrent.org/wiki/Plugins")},onGotPlugins:function(){this.setInfo(); -this.updatePluginsGrid()},onGotPluginInfo:function(a){this.setInfo({author:a.Author,version:a.Version,email:a["Author-email"],homepage:a["Home-page"],details:a.Description});delete a},onInstallPluginWindow:function(){this.installWindow||(this.installWindow=new Deluge.preferences.InstallPluginWindow,this.installWindow.on("pluginadded",this.onPluginInstall,this));this.installWindow.show()},onPluginEnabled:function(a){a=this.list.getStore().find("plugin",a);-1!=a&&(a=this.list.getStore().getAt(a),a.set("enabled", -!0),a.commit())},onPluginDisabled:function(a){a=this.list.getStore().find("plugin",a);-1!=a&&(a=this.list.getStore().getAt(a),a.set("enabled",!1),a.commit())},onPluginInstall:function(){this.updatePlugins()},onPluginSelect:function(a,b){if(0!=b.length){var c=a.getRecords(b)[0];deluge.client.web.get_plugin_info(c.get("plugin"),{success:this.onGotPluginInfo,scope:this})}},onPreferencesShow:function(){this.updatePlugins()},onPluginInfoRender:function(a,b){this.setInfo()}});Ext.namespace("Deluge.preferences"); -PreferencesRecord=Ext.data.Record.create([{name:"name",type:"string"}]); -Deluge.preferences.PreferencesWindow=Ext.extend(Ext.Window,{currentPage:null,title:_("Preferences"),layout:"border",width:485,height:500,border:!1,constrainHeader:!0,buttonAlign:"right",closeAction:"hide",closable:!0,iconCls:"x-deluge-preferences",plain:!0,resizable:!1,pages:{},initComponent:function(){Deluge.preferences.PreferencesWindow.superclass.initComponent.call(this);this.list=new Ext.list.ListView({store:new Ext.data.Store,columns:[{id:"name",dataIndex:"name"}],singleSelect:!0,listeners:{selectionchange:{fn:this.onPageSelect, -scope:this}},hideHeaders:!0,autoExpandColumn:"name",deferredRender:!1,autoScroll:!0,collapsible:!0});this.add({region:"west",items:[this.list],width:120,margins:"0 5 0 0",cmargins:"0 5 0 0"});this.configPanel=this.add({type:"container",autoDestroy:!1,region:"center",layout:"card",layoutConfig:{deferredRender:!0},autoScroll:!0,width:300});this.addButton(_("Close"),this.onClose,this);this.addButton(_("Apply"),this.onApply,this);this.addButton(_("OK"),this.onOk,this);this.optionsManager=new Deluge.OptionsManager; -this.on("afterrender",this.onAfterRender,this);this.on("show",this.onShow,this);this.initPages()},initPages:function(){deluge.preferences=this;this.addPage(new Deluge.preferences.Downloads);this.addPage(new Deluge.preferences.Network);this.addPage(new Deluge.preferences.Encryption);this.addPage(new Deluge.preferences.Bandwidth);this.addPage(new Deluge.preferences.Interface);this.addPage(new Deluge.preferences.Other);this.addPage(new Deluge.preferences.Daemon);this.addPage(new Deluge.preferences.Queue); -this.addPage(new Deluge.preferences.Proxy);this.addPage(new Deluge.preferences.Cache);this.addPage(new Deluge.preferences.Plugins)},onApply:function(a){a=this.optionsManager.getDirty();Ext.isObjectEmpty(a)||("listen_ports"in a&&(a.listen_ports=[a.listen_ports,a.listen_ports]),deluge.client.core.set_config(a,{success:this.onSetConfig,scope:this}));for(var b in this.pages)if(this.pages[b].onApply)this.pages[b].onApply()},getOptionsManager:function(){return this.optionsManager},addPage:function(a){var b= -this.list.getStore(),c=a.title;b.add([new PreferencesRecord({name:c})]);a.bodyStyle="padding: 5px";a.preferences=this;this.pages[c]=this.configPanel.add(a);this.pages[c].index=-1;return this.pages[c]},removePage:function(a){var b=a.title,c=this.list.getStore();c.removeAt(c.find("name",b));this.configPanel.remove(a);delete this.pages[a.title]},selectPage:function(a){0>this.pages[a].index&&(this.pages[a].index=this.configPanel.items.indexOf(this.pages[a]));this.list.select(this.pages[a].index)},doSelectPage:function(a){0> -this.pages[a].index&&(this.pages[a].index=this.configPanel.items.indexOf(this.pages[a]));this.configPanel.getLayout().setActiveItem(this.pages[a].index);this.currentPage=a},onGotConfig:function(a){this.getOptionsManager().set(a)},onPageSelect:function(a,b){var c=a.getRecord(b[0]);this.doSelectPage(c.get("name"))},onSetConfig:function(){this.getOptionsManager().commit()},onAfterRender:function(){this.list.getSelectionCount()||this.list.select(0);this.configPanel.getLayout().setActiveItem(0)},onShow:function(){deluge.client.core&& -deluge.client.core.get_config({success:this.onGotConfig,scope:this})},onClose:function(){this.hide()},onOk:function(){var a=this.optionsManager.getDirty();Ext.isObjectEmpty(a)||deluge.client.core.set_config(a,{success:this.onSetConfig,scope:this});for(var b in this.pages)if(this.pages[b].onOk)this.pages[b].onOk();this.hide()}});Ext.ns("Deluge.preferences"); -Deluge.preferences.ProxyField=Ext.extend(Ext.form.FieldSet,{border:!1,autoHeight:!0,labelWidth:70,initComponent:function(){Deluge.preferences.ProxyField.superclass.initComponent.call(this);this.proxyType=this.add({xtype:"combo",fieldLabel:_("Type:"),labelSeparator:"",name:"proxytype",mode:"local",width:150,store:new Ext.data.ArrayStore({fields:["id","text"],data:[[0,_("None")],[1,_("Socks4")],[2,_("Socks5")],[3,_("Socks5 Auth")],[4,_("HTTP")],[5,_("HTTP Auth")],[6,_("I2P")]]}),editable:!1,triggerAction:"all", -valueField:"id",displayField:"text"});this.proxyType.on("change",this.onFieldChange,this);this.proxyType.on("select",this.onTypeSelect,this);this.hostname=this.add({xtype:"textfield",name:"hostname",fieldLabel:_("Host:"),labelSeparator:"",width:220});this.hostname.on("change",this.onFieldChange,this);this.port=this.add({xtype:"spinnerfield",name:"port",fieldLabel:_("Port:"),labelSeparator:"",width:80,decimalPrecision:0,minValue:0,maxValue:65535});this.port.on("change",this.onFieldChange,this);this.username= -this.add({xtype:"textfield",name:"username",fieldLabel:_("Username:"),labelSeparator:"",width:220});this.username.on("change",this.onFieldChange,this);this.password=this.add({xtype:"textfield",name:"password",fieldLabel:_("Password:"),labelSeparator:"",inputType:"password",width:220});this.password.on("change",this.onFieldChange,this);this.proxy_host_resolve=this.add({xtype:"checkbox",name:"proxy_host_resolve",fieldLabel:"",boxLabel:_("Proxy Hostnames"),width:220});this.proxy_host_resolve.on("change", -this.onFieldChange,this);this.proxy_peer_conn=this.add({xtype:"checkbox",name:"proxy_peer_conn",fieldLabel:"",boxLabel:_("Proxy Peers"),width:220});this.proxy_peer_conn.on("change",this.onFieldChange,this);this.proxy_tracker_conn=this.add({xtype:"checkbox",name:"proxy_tracker_conn",fieldLabel:"",boxLabel:_("Proxy Trackers"),width:220});this.proxy_tracker_conn.on("change",this.onFieldChange,this);var a=this.add({xtype:"fieldset",border:!1,title:_("Force Proxy"),autoHeight:!0,labelWidth:1,defaultType:"checkbox", -style:"padding-left: 0px; margin-top: 10px"});this.force_proxy=a.add({fieldLabel:"",labelSeparator:"",height:20,name:"force_proxy",boxLabel:_("Force Use of Proxy")});this.force_proxy.on("change",this.onFieldChange,this);this.anonymous_mode=a.add({fieldLabel:"",labelSeparator:"",height:20,name:"anonymous_mode",boxLabel:_("Hide Client Identity")});this.anonymous_mode.on("change",this.onFieldChange,this);this.setting=!1},getName:function(){return this.initialConfig.name},getValue:function(){return{type:this.proxyType.getValue(), -hostname:this.hostname.getValue(),port:Number(this.port.getValue()),username:this.username.getValue(),password:this.password.getValue(),proxy_hostnames:this.proxy_host_resolve.getValue(),proxy_peer_connections:this.proxy_peer_conn.getValue(),proxy_tracker_connections:this.proxy_tracker_conn.getValue(),force_proxy:this.force_proxy.getValue(),anonymous_mode:this.anonymous_mode.getValue()}},setValue:function(a){this.setting=!0;this.proxyType.setValue(a.type);var b=this.proxyType.getStore().find("id", -a.type),c=this.proxyType.getStore().getAt(b);this.hostname.setValue(a.hostname);this.port.setValue(a.port);this.username.setValue(a.username);this.password.setValue(a.password);this.proxy_host_resolve.setValue(a.proxy_hostnames);this.proxy_peer_conn.setValue(a.proxy_peer_connections);this.proxy_tracker_conn.setValue(a.proxy_tracker_connections);this.force_proxy.setValue(a.force_proxy);this.anonymous_mode.setValue(a.anonymous_mode);this.onTypeSelect(this.type,c,b);this.setting=!1},onFieldChange:function(a, -b,c){if(!this.setting){b=this.getValue();var d=Ext.apply({},b);d[a.getName()]=c;this.fireEvent("change",this,b,d)}},onTypeSelect:function(a,b,c){a=b.get("id");0<a?(this.hostname.show(),this.port.show(),this.proxy_peer_conn.show(),this.proxy_tracker_conn.show(),1<a&&6>a?this.proxy_host_resolve.show():this.proxy_host_resolve.hide()):(this.hostname.hide(),this.port.hide(),this.proxy_host_resolve.hide(),this.proxy_peer_conn.hide(),this.proxy_tracker_conn.hide());3==a||5==a?(this.username.show(),this.password.show()): -(this.username.hide(),this.password.hide())}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Proxy=Ext.extend(Ext.form.FormPanel,{constructor:function(a){a=Ext.apply({border:!1,title:_("Proxy"),header:!1,layout:"form",autoScroll:!0},a);Deluge.preferences.Proxy.superclass.constructor.call(this,a)},initComponent:function(){Deluge.preferences.Proxy.superclass.initComponent.call(this);this.proxy=this.add(new Deluge.preferences.ProxyField({title:_("Proxy"),name:"proxy"}));this.proxy.on("change",this.onProxyChange,this);deluge.preferences.getOptionsManager().bind("proxy",this.proxy)}, -getValue:function(){return{proxy:this.proxy.getValue()}},setValue:function(a){for(var b in a)this[b].setValue(a[b])},onProxyChange:function(a,b,c){b=this.getValue();var d=Ext.apply({},b);d[a.getName()]=c;this.fireEvent("change",this,b,d)}});Ext.namespace("Deluge.preferences"); -Deluge.preferences.Queue=Ext.extend(Ext.form.FormPanel,{border:!1,title:_("Queue"),header:!1,layout:"form",initComponent:function(){Deluge.preferences.Queue.superclass.initComponent.call(this);var a=deluge.preferences.getOptionsManager(),b=this.add({xtype:"fieldset",border:!1,title:_("New Torrents"),style:"padding-top: 5px; margin-bottom: 0px;",autoHeight:!0,labelWidth:1,defaultType:"checkbox"});a.bind("queue_new_to_top",b.add({fieldLabel:"",labelSeparator:"",height:22,boxLabel:_("Queue to top"), -name:"queue_new_to_top"}));b=this.add({xtype:"fieldset",border:!1,title:_("Active Torrents"),autoHeight:!0,labelWidth:150,defaultType:"spinnerfield",style:"padding-top: 5px; margin-bottom: 0px"});a.bind("max_active_limit",b.add({fieldLabel:_("Total:"),labelSeparator:"",name:"max_active_limit",value:8,width:80,decimalPrecision:0,minValue:-1,maxValue:99999}));a.bind("max_active_downloading",b.add({fieldLabel:_("Downloading:"),labelSeparator:"",name:"max_active_downloading",value:3,width:80,decimalPrecision:0, -minValue:-1,maxValue:99999}));a.bind("max_active_seeding",b.add({fieldLabel:_("Seeding:"),labelSeparator:"",name:"max_active_seeding",value:5,width:80,decimalPrecision:0,minValue:-1,maxValue:99999}));a.bind("dont_count_slow_torrents",b.add({xtype:"checkbox",name:"dont_count_slow_torrents",height:22,hideLabel:!0,boxLabel:_("Ignore slow torrents")}));a.bind("auto_manage_prefer_seeds",b.add({xtype:"checkbox",name:"auto_manage_prefer_seeds",hideLabel:!0,boxLabel:_("Prefer seeding torrents")}));b=this.add({xtype:"fieldset", -border:!1,title:_("Seeding Rotation"),autoHeight:!0,labelWidth:150,defaultType:"spinnerfield",style:"padding-top: 5px; margin-bottom: 0px"});a.bind("share_ratio_limit",b.add({fieldLabel:_("Share Ratio:"),labelSeparator:"",name:"share_ratio_limit",value:8,width:80,incrementValue:0.1,minValue:-1,maxValue:99999,alternateIncrementValue:1,decimalPrecision:2}));a.bind("seed_time_ratio_limit",b.add({fieldLabel:_("Time Ratio:"),labelSeparator:"",name:"seed_time_ratio_limit",value:3,width:80,incrementValue:0.1, -minValue:-1,maxValue:99999,alternateIncrementValue:1,decimalPrecision:2}));a.bind("seed_time_limit",b.add({fieldLabel:_("Time (m):"),labelSeparator:"",name:"seed_time_limit",value:5,width:80,decimalPrecision:0,minValue:-1,maxValue:99999}));b=this.add({xtype:"fieldset",border:!1,autoHeight:!0,style:"padding-top: 5px; margin-bottom: 0px",title:_("Share Ratio Reached"),layout:"table",layoutConfig:{columns:2},labelWidth:0,defaultType:"checkbox",defaults:{fieldLabel:"",labelSeparator:""}});this.stopAtRatio= -b.add({name:"stop_seed_at_ratio",boxLabel:_("Share Ratio:")});this.stopAtRatio.on("check",this.onStopRatioCheck,this);a.bind("stop_seed_at_ratio",this.stopAtRatio);this.stopRatio=b.add({xtype:"spinnerfield",name:"stop_seed_ratio",ctCls:"x-deluge-indent-checkbox",disabled:!0,value:"2.0",width:60,incrementValue:0.1,minValue:-1,maxValue:99999,alternateIncrementValue:1,decimalPrecision:2});a.bind("stop_seed_ratio",this.stopRatio);this.removeAtRatio=b.add({xtype:"radiogroup",columns:1,colspan:2,disabled:!0, -style:"margin-left: 10px",items:[{boxLabel:_("Pause torrent"),name:"at_ratio",inputValue:!1,checked:!0},{boxLabel:_("Remove torrent"),name:"at_ratio",inputValue:!0}]});a.bind("remove_seed_at_ratio",this.removeAtRatio)},onStopRatioCheck:function(a,b){this.stopRatio.setDisabled(!b);this.removeAtRatio.setDisabled(!b)}});Ext.ns("Deluge"); -Deluge.StatusbarMenu=Ext.extend(Ext.menu.Menu,{initComponent:function(){Deluge.StatusbarMenu.superclass.initComponent.call(this);this.otherWin=new Deluge.OtherLimitWindow(this.initialConfig.otherWin||{});this.items.each(function(a){if("menucheckitem"==a.getXType())if("other"==a.value)a.on("click",this.onOtherClicked,this);else a.on("checkchange",this.onLimitChanged,this)},this)},setValue:function(a){var b=!1;this.value=a=0==a?-1:a;var c=null;this.items.each(function(d){d.setChecked&&(d.suspendEvents(), -d.value==a?(d.setChecked(!0),b=!0):d.setChecked(!1),d.resumeEvents());"other"==d.value&&(c=d)});b||(c.suspendEvents(),c.setChecked(!0),c.resumeEvents())},onLimitChanged:function(a,b){if(b&&"other"!=a.value){var c={};c[a.group]=a.value;deluge.client.core.set_config(c,{success:function(){deluge.ui.update()}})}},onOtherClicked:function(a,b){this.otherWin.group=a.group;this.otherWin.setValue(this.value);this.otherWin.show()}});Ext.namespace("Deluge"); -Deluge.OptionsManager=Ext.extend(Ext.util.Observable,{constructor:function(a){a=a||{};this.binds={};this.changed={};this.options=a&&a.options||{};this.focused=null;this.addEvents({add:!0,changed:!0,reset:!0});this.on("changed",this.onChange,this);Deluge.OptionsManager.superclass.constructor.call(this)},addOptions:function(a){this.options=Ext.applyIf(this.options,a)},bind:function(a,b){this.binds[a]=this.binds[a]||[];this.binds[a].push(b);b._doption=a;b.on("focus",this.onFieldFocus,this);b.on("blur", -this.onFieldBlur,this);b.on("change",this.onFieldChange,this);b.on("check",this.onFieldChange,this);b.on("spin",this.onFieldChange,this);return b},commit:function(){this.options=Ext.apply(this.options,this.changed);this.reset()},convertValueType:function(a,b){if(Ext.type(a)!=Ext.type(b))switch(Ext.type(a)){case "string":b=String(b);break;case "number":b=Number(b);break;case "boolean":"string"==Ext.type(b)?(b=b.toLowerCase(),b="true"==b||"1"==b||"on"==b?!0:!1):b=Boolean(b)}return b},get:function(){if(1== -arguments.length){var a=arguments[0];return this.isDirty(a)?this.changed[a]:this.options[a]}var b={};Ext.each(arguments,function(a){this.has(a)&&(b[a]=this.isDirty(a)?this.changed[a]:this.options[a])},this);return b},getDefault:function(a){return this.options[a]},getDirty:function(){return this.changed},isDirty:function(a){return!Ext.isEmpty(this.changed[a])},has:function(a){return this.options[a]},reset:function(){this.changed={}},set:function(a,b){if(void 0!==a)if("object"==typeof a){var c=a;this.options= -Ext.apply(this.options,c);for(a in c)this.onChange(a,c[a])}else this.options[a]=b,this.onChange(a,b)},update:function(a,b){if(void 0!==a)if(void 0===b)for(var c in a)this.update(c,a[c]);else{c=this.getDefault(a);b=this.convertValueType(c,b);var d=this.get(a);d!=b&&(c==b?this.isDirty(a)&&delete this.changed[a]:this.changed[a]=b,this.fireEvent("changed",a,b,d))}},onFieldBlur:function(a,b){this.focused==a&&(this.focused=null)},onFieldChange:function(a,b){a.field&&(a=a.field);this.update(a._doption,a.getValue())}, -onFieldFocus:function(a,b){this.focused=a},onChange:function(a,b,c){Ext.isEmpty(this.binds[a])||Ext.each(this.binds[a],function(a){a!=this.focused&&a.setValue(b)},this)}});Ext.namespace("Deluge.about"); -Deluge.about.AboutWindow=Ext.extend(Ext.Window,{id:"AboutWindow",title:_("About Deluge"),height:330,width:270,iconCls:"x-deluge-main-panel",resizable:!1,plain:!0,layout:{type:"vbox",align:"center"},buttonAlign:"center",initComponent:function(){Deluge.about.AboutWindow.superclass.initComponent.call(this);this.addEvents({build_ready:!0});var a=this,b=function(){deluge.client.core.get_libtorrent_version({success:function(b){d+="<br/>"+_("libtorrent:")+" "+b;Ext.getCmp("about_comment").setText(d,!1); -a.fireEvent("build_ready")}})},c=deluge.version,d=_("A peer-to-peer file sharing program\nutilizing the BitTorrent protocol.").replace("\n","<br/>")+"<br/><br/>"+_("Client:")+" "+c+"<br/>";deluge.client.web.connected({success:function(a){a?deluge.client.daemon.get_version({success:function(a){d+=_("Server:")+" "+a+"<br/>";b()}}):this.fireEvent("build_ready")},failure:function(){this.fireEvent("build_ready")},scope:this});this.add([{xtype:"box",style:"padding-top: 5px",height:80,width:240,cls:"x-deluge-logo", -hideLabel:!0},{xtype:"label",style:"padding-top: 10px; font-weight: bold; font-size: 16px;",text:_("Deluge")+" "+c},{xtype:"label",id:"about_comment",style:"padding-top: 10px; text-align:center; font-size: 12px;",html:d},{xtype:"label",style:"padding-top: 10px; font-size: 10px;",text:_("Copyright 2007-2018 Deluge Team")},{xtype:"label",style:"padding-top: 5px; font-size: 12px;",html:'<a href="https://deluge-torrent.org" target="_blank">deluge-torrent.org</a>'}]);this.addButton(_("Close"),this.onCloseClick, -this)},show:function(){this.on("build_ready",function(){Deluge.about.AboutWindow.superclass.show.call(this)})},onCloseClick:function(){this.close()}});Ext.namespace("Deluge");Deluge.About=function(){(new Deluge.about.AboutWindow).show()};Ext.ns("Deluge"); -Deluge.AddConnectionWindow=Ext.extend(Ext.Window,{title:_("Add Connection"),iconCls:"x-deluge-add-window-icon",layout:"fit",width:300,height:195,constrainHeader:!0,bodyStyle:"padding: 10px 5px;",closeAction:"hide",initComponent:function(){Deluge.AddConnectionWindow.superclass.initComponent.call(this);this.addEvents("hostadded");this.addButton(_("Close"),this.hide,this);this.addButton(_("Add"),this.onAddClick,this);this.on("hide",this.onHide,this);this.form=this.add({xtype:"form",defaultType:"textfield", -baseCls:"x-plain",labelWidth:60,items:[{fieldLabel:_("Host:"),labelSeparator:"",name:"host",anchor:"75%",value:""},{xtype:"spinnerfield",fieldLabel:_("Port:"),labelSeparator:"",name:"port",strategy:{xtype:"number",decimalPrecision:0,minValue:-1,maxValue:65535},value:"58846",anchor:"40%"},{fieldLabel:_("Username:"),labelSeparator:"",name:"username",anchor:"75%",value:""},{fieldLabel:_("Password:"),labelSeparator:"",anchor:"75%",name:"password",inputType:"password",value:""}]})},onAddClick:function(){var a= -this.form.getForm().getValues();deluge.client.web.add_host(a.host,Number(a.port),a.username,a.password,{success:function(a){a[0]?this.fireEvent("hostadded"):Ext.MessageBox.show({title:_("Error"),msg:String.format(_("Unable to add host: {0}"),a[1]),buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"});this.hide()},scope:this})},onHide:function(){this.form.getForm().reset()}});Ext.ns("Deluge");var trackerUrlTest=/(((^https?)|(^udp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i; -Ext.apply(Ext.form.VTypes,{trackerUrl:function(a,b){return trackerUrlTest.test(a)},trackerUrlText:"Not a valid tracker url"}); -Deluge.AddTrackerWindow=Ext.extend(Ext.Window,{title:_("Add Tracker"),layout:"fit",width:375,height:150,plain:!0,closable:!0,resizable:!1,constrainHeader:!0,bodyStyle:"padding: 5px",buttonAlign:"right",closeAction:"hide",iconCls:"x-deluge-edit-trackers",initComponent:function(){Deluge.AddTrackerWindow.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancelClick,this);this.addButton(_("Add"),this.onAddClick,this);this.addEvents("add");this.form=this.add({xtype:"form",defaultType:"textarea", -baseCls:"x-plain",labelWidth:55,items:[{fieldLabel:_("Trackers:"),labelSeparator:"",name:"trackers",anchor:"100%"}]})},onAddClick:function(){var a=this.form.getForm().findField("trackers").getValue(),a=a.split("\n"),b=[];Ext.each(a,function(a){Ext.form.VTypes.trackerUrl(a)&&b.push(a)},this);this.fireEvent("add",b);this.hide();this.form.getForm().findField("trackers").setValue("")},onCancelClick:function(){this.form.getForm().findField("trackers").setValue("");this.hide()}});Ext.namespace("Ext.ux.util"); -Ext.ux.util.RpcClient=Ext.extend(Ext.util.Observable,{_components:[],_methods:[],_requests:{},_url:null,_optionKeys:["scope","success","failure"],constructor:function(a){Ext.ux.util.RpcClient.superclass.constructor.call(this,a);this._url=a.url||null;this._id=0;this.addEvents("connected","error");this.reloadMethods()},reloadMethods:function(){this._execute("system.listMethods",{success:this._setMethods,scope:this})},_execute:function(a,b){b=b||{};b.params=b.params||[];b.id=this._id;var c=Ext.encode({method:a, -params:b.params,id:b.id});this._id++;return Ext.Ajax.request({url:this._url,method:"POST",success:this._onSuccess,failure:this._onFailure,scope:this,jsonData:c,options:b})},_onFailure:function(a,b){var c=b.options;errorObj={id:c.id,result:null,error:{msg:"HTTP: "+a.status+" "+a.statusText,code:255}};this.fireEvent("error",errorObj,a,b);"function"==Ext.type(c.failure)&&(c.scope?c.failure.call(c.scope,errorObj,a,b):c.failure(errorObj,a,b))},_onSuccess:function(a,b){var c=Ext.decode(a.responseText), -d=b.options;c.error?(this.fireEvent("error",c,a,b),"function"==Ext.type(d.failure)&&(d.scope?d.failure.call(d.scope,c,a,b):d.failure(c,a,b))):"function"==Ext.type(d.success)&&(d.scope?d.success.call(d.scope,c.result,c,a,b):d.success(c.result,c,a,b))},_parseArgs:function(a){var b=[];Ext.each(a,function(a){b.push(a)});a=b[b.length-1];if("object"==Ext.type(a)){var c=Ext.keys(a),d=!1;Ext.each(this._optionKeys,function(a){-1<c.indexOf(a)&&(d=!0)});d?b.remove(a):a={}}else a={};a.params=b;return a},_setMethods:function(a){var b= -{},c=this;Ext.each(a,function(a){var d=a.split("."),e=b[d[0]]||{};e[d[1]]=function(){var b=c._parseArgs(arguments);return c._execute(a,b)};b[d[0]]=e});for(var d in b)c[d]=b[d];Ext.each(this._components,function(a){!a in b&&delete this[a]},this);this._components=Ext.keys(b);this.fireEvent("connected",this)}}); -Deluge.ConnectionManager=Ext.extend(Ext.Window,{layout:"fit",width:300,height:220,bodyStyle:"padding: 10px 5px;",buttonAlign:"right",closeAction:"hide",closable:!0,plain:!0,constrainHeader:!0,title:_("Connection Manager"),iconCls:"x-deluge-connect-window-icon",initComponent:function(){Deluge.ConnectionManager.superclass.initComponent.call(this);this.on("hide",this.onHide,this);this.on("show",this.onShow,this);deluge.events.on("login",this.onLogin,this);deluge.events.on("logout",this.onLogout,this); -this.addButton(_("Close"),this.onClose,this);this.addButton(_("Connect"),this.onConnect,this);this.list=new Ext.list.ListView({store:new Ext.data.ArrayStore({fields:[{name:"status",mapping:4},{name:"host",mapping:1},{name:"port",mapping:2},{name:"user",mapping:3},{name:"version",mapping:5}],id:0}),columns:[{header:_("Status"),width:0.24,sortable:!0,tpl:new Ext.XTemplate("<tpl if=\"status == 'Online'\">",_("Online"),"</tpl>","<tpl if=\"status == 'Offline'\">",_("Offline"),"</tpl>","<tpl if=\"status == 'Connected'\">", -_("Connected"),"</tpl>"),dataIndex:"status"},{id:"host",header:_("Host"),width:0.51,sortable:!0,tpl:"{user}@{host}:{port}",dataIndex:"host"},{header:_("Version"),width:0.25,sortable:!0,tpl:'<tpl if="version">{version}</tpl>',dataIndex:"version"}],singleSelect:!0,listeners:{selectionchange:{fn:this.onSelectionChanged,scope:this}}});this.panel=this.add({autoScroll:!0,items:[this.list],bbar:new Ext.Toolbar({buttons:[{id:"cm-add",cls:"x-btn-text-icon",text:_("Add"),iconCls:"icon-add",handler:this.onAddClick, -scope:this},{id:"cm-edit",cls:"x-btn-text-icon",text:_("Edit"),iconCls:"icon-edit",handler:this.onEditClick,scope:this},{id:"cm-remove",cls:"x-btn-text-icon",text:_("Remove"),iconCls:"icon-remove",handler:this.onRemoveClick,disabled:!0,scope:this},"->",{id:"cm-stop",cls:"x-btn-text-icon",text:_("Stop Daemon"),iconCls:"icon-error",handler:this.onStopClick,disabled:!0,scope:this}]})});this.update=this.update.createDelegate(this)},checkConnected:function(){deluge.client.web.connected({success:function(a){a? -deluge.events.fire("connect"):this.show()},scope:this})},disconnect:function(a){deluge.events.fire("disconnect");a&&!this.isVisible()&&this.show()},loadHosts:function(){deluge.client.web.get_hosts({success:this.onGetHosts,scope:this})},update:function(){this.list.getStore().each(function(a){deluge.client.web.get_host_status(a.id,{success:this.onGetHostStatus,scope:this})},this)},updateButtons:function(a){var b=this.buttons[1],c=a.get("status");b.enable();"connected"==c.toLowerCase()?b.setText(_("Disconnect")): -(b.setText(_("Connect")),"online"!=c.toLowerCase()&&b.disable());"connected"==c.toLowerCase()||"online"==c.toLowerCase()?(this.stopHostButton.enable(),this.stopHostButton.setText(_("Stop Daemon"))):"127.0.0.1"==a.get("host")||"localhost"==a.get("host")?(this.stopHostButton.enable(),this.stopHostButton.setText(_("Start Daemon"))):this.stopHostButton.disable()},onAddClick:function(a,b){this.addWindow||(this.addWindow=new Deluge.AddConnectionWindow,this.addWindow.on("hostadded",this.onHostChange,this)); -this.addWindow.show()},onEditClick:function(a,b){var c=this.list.getSelectedRecords()[0];c&&(this.editWindow||(this.editWindow=new Deluge.EditConnectionWindow,this.editWindow.on("hostedited",this.onHostChange,this)),this.editWindow.show(c))},onHostChange:function(){this.loadHosts()},onClose:function(a){this.hide()},onConnect:function(a){if(a=this.list.getSelectedRecords()[0]){var b=this,c=function(){deluge.client.web.disconnect({success:function(a){this.update(this);deluge.events.fire("disconnect")}, -scope:b})};"connected"==a.get("status").toLowerCase()?c():(-1<this.list.getStore().find("status","Connected",0,!1,!1)&&c(),deluge.client.web.connect(a.id,{success:function(a){deluge.client.reloadMethods();deluge.client.on("connected",function(a){deluge.events.fire("connect")},this,{single:!0})}}),this.hide())}},onGetHosts:function(a){this.list.getStore().loadData(a);Ext.each(a,function(a){deluge.client.web.get_host_status(a[0],{success:this.onGetHostStatus,scope:this})},this)},onGetHostStatus:function(a){var b= -this.list.getStore().getById(a[0]);b.set("status",a[1]);b.set("version",a[2]);b.commit();(a=this.list.getSelectedRecords()[0])&&a==b&&this.updateButtons(b)},onHide:function(){this.running&&window.clearInterval(this.running)},onLogin:function(){deluge.config.first_login?Ext.MessageBox.confirm(_("Change Default Password"),_("We recommend changing the default password.<br><br>Would you like to change it now?"),function(a){this.checkConnected();"yes"==a&&(deluge.preferences.show(),deluge.preferences.selectPage("Interface")); -deluge.client.web.set_config({first_login:!1})},this):this.checkConnected()},onLogout:function(){this.disconnect();!this.hidden&&this.rendered&&this.hide()},onRemoveClick:function(a){var b=this.list.getSelectedRecords()[0];b&&deluge.client.web.remove_host(b.id,{success:function(a){a?this.list.getStore().remove(b):Ext.MessageBox.show({title:_("Error"),msg:a[1],buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"})},scope:this})},onSelectionChanged:function(a,b){b[0]? -(this.editHostButton.enable(),this.removeHostButton.enable(),this.stopHostButton.enable(),this.stopHostButton.setText(_("Stop Daemon")),this.updateButtons(this.list.getRecord(b[0]))):(this.editHostButton.disable(),this.removeHostButton.disable(),this.stopHostButton.disable())},onShow:function(){if(!this.addHostButton){var a=this.panel.getBottomToolbar();this.addHostButton=a.items.get("cm-add");this.editHostButton=a.items.get("cm-edit");this.removeHostButton=a.items.get("cm-remove");this.stopHostButton= -a.items.get("cm-stop")}this.loadHosts();this.running||(this.running=window.setInterval(this.update,2E3,this))},onStopClick:function(a,b){var c=this.list.getSelectedRecords()[0];c&&("Offline"==c.get("status")?deluge.client.web.start_daemon(c.get("port")):deluge.client.web.stop_daemon(c.id,{success:function(a){a[0]||Ext.MessageBox.show({title:_("Error"),msg:a[1],buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"})}}))}}); -Deluge.CopyMagnet=Ext.extend(Ext.Window,{title:_("Copy Magnet URI"),width:375,closeAction:"hide",iconCls:"icon-magnet-copy",initComponent:function(){Deluge.CopyMagnet.superclass.initComponent.call(this);form=this.add({xtype:"form",defaultType:"textfield",hideLabels:!0});this.magnetURI=form.add({name:"URI",anchor:"100%"});this.addButton(_("Close"),this.onClose,this);this.addButton(_("Copy"),this.onCopy,this)},show:function(a){Deluge.CopyMagnet.superclass.show.call(this);a=deluge.torrents.getSelected(); -deluge.client.core.get_magnet_uri(a.id,{success:this.onRequestComplete,scope:this})},onRequestComplete:function(a){this.magnetURI.setValue(a)},onCopy:function(){this.magnetURI.focus();this.magnetURI.el.dom.select();document.execCommand("copy")},onClose:function(){this.hide()}});deluge.copyMagnetWindow=new Deluge.CopyMagnet;Ext.state.Manager.setProvider(new Ext.state.CookieProvider({expires:new Date((new Date).getTime()+31536E7)})); -Ext.apply(Ext,{isObjectEmpty:function(a){for(var b in a)return!1;return!0},areObjectsEqual:function(a,b){var c=!0;if(!a||!b)return!1;for(var d in a)a[d]!=b[d]&&(c=!1);return c},keys:function(a){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push(c);return b},values:function(a){var b=[],c;for(c in a)a.hasOwnProperty(c)&&b.push(a[c]);return b},splat:function(a){var b=Ext.type(a);return b?"array"!=b?[a]:a:[]}});Ext.getKeys=Ext.keys;Ext.BLANK_IMAGE_URL=deluge.config.base+"images/s.gif"; -Ext.USE_NATIVE_JSON=!0; -Ext.apply(Deluge,{pluginStore:{},progressTpl:'<div class="x-progress-wrap x-progress-renderered"><div class="x-progress-inner"><div style="width: {2}px" class="x-progress-bar"><div style="z-index: 99; width: {3}px" class="x-progress-text"><div style="width: {1}px;">{0}</div></div></div><div class="x-progress-text x-progress-text-back"><div style="width: {1}px;">{0}</div></div></div></div>',progressBar:function(a,b,c,d){d=Ext.value(d,10);a=(b/100*a).toFixed(0);return String.format(Deluge.progressTpl,c, -b,a-1,0<a-d?a-d:0)},createPlugin:function(a){return new Deluge.pluginStore[a]},hasPlugin:function(a){return Deluge.pluginStore[a]?!0:!1},registerPlugin:function(a,b){Deluge.pluginStore[a]=b}});deluge.plugins={};FILE_PRIORITY={"0":"Skip",1:"Low",2:"Low",3:"Low",4:"Normal",5:"High",6:"High",7:"High",9:"Mixed",Skip:0,Low:1,Normal:4,High:7,Mixed:9}; -FILE_PRIORITY_CSS={"0":"x-no-download",1:"x-low-download",2:"x-low-download",3:"x-low-download",4:"x-normal-download",5:"x-high-download",6:"x-high-download",7:"x-high-download",9:"x-mixed-download"};Ext.ns("Deluge"); -Deluge.EditConnectionWindow=Ext.extend(Ext.Window,{title:_("Edit Connection"),iconCls:"x-deluge-add-window-icon",layout:"fit",width:300,height:195,constrainHeader:!0,bodyStyle:"padding: 10px 5px;",closeAction:"hide",initComponent:function(){Deluge.EditConnectionWindow.superclass.initComponent.call(this);this.addEvents("hostedited");this.addButton(_("Close"),this.hide,this);this.addButton(_("Edit"),this.onEditClick,this);this.on("hide",this.onHide,this);this.form=this.add({xtype:"form",defaultType:"textfield", -baseCls:"x-plain",labelWidth:60,items:[{fieldLabel:_("Host:"),labelSeparator:"",name:"host",anchor:"75%",value:""},{xtype:"spinnerfield",fieldLabel:_("Port:"),labelSeparator:"",name:"port",strategy:{xtype:"number",decimalPrecision:0,minValue:0,maxValue:65535},anchor:"40%",value:58846},{fieldLabel:_("Username:"),labelSeparator:"",name:"username",anchor:"75%",value:""},{fieldLabel:_("Password:"),labelSeparator:"",anchor:"75%",name:"password",inputType:"password",value:""}]})},show:function(a){Deluge.EditConnectionWindow.superclass.show.call(this); -this.form.getForm().findField("host").setValue(a.get("host"));this.form.getForm().findField("port").setValue(a.get("port"));this.form.getForm().findField("username").setValue(a.get("user"));this.host_id=a.id},onEditClick:function(){var a=this.form.getForm().getValues();deluge.client.web.edit_host(this.host_id,a.host,Number(a.port),a.username,a.password,{success:function(a){a?this.fireEvent("hostedited"):(console.log(a),Ext.MessageBox.show({title:_("Error"),msg:String.format(_("Unable to edit host")), -buttons:Ext.MessageBox.OK,modal:!1,icon:Ext.MessageBox.ERROR,iconCls:"x-deluge-icon-error"}));this.hide()},scope:this})},onHide:function(){this.form.getForm().reset()}});Ext.ns("Deluge"); -Deluge.EditTrackerWindow=Ext.extend(Ext.Window,{title:_("Edit Tracker"),layout:"fit",width:375,height:110,plain:!0,closable:!0,resizable:!1,constrainHeader:!0,bodyStyle:"padding: 5px",buttonAlign:"right",closeAction:"hide",iconCls:"x-deluge-edit-trackers",initComponent:function(){Deluge.EditTrackerWindow.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancelClick,this);this.addButton(_("Save"),this.onSaveClick,this);this.on("hide",this.onHide,this);this.form=this.add({xtype:"form", -defaultType:"textfield",baseCls:"x-plain",labelWidth:55,items:[{fieldLabel:_("Tracker:"),labelSeparator:"",name:"tracker",anchor:"100%"}]})},show:function(a){Deluge.EditTrackerWindow.superclass.show.call(this);this.record=a;this.form.getForm().findField("tracker").setValue(a.data.url)},onCancelClick:function(){this.hide()},onHide:function(){this.form.getForm().findField("tracker").setValue("")},onSaveClick:function(){var a=this.form.getForm().findField("tracker").getValue();this.record.set("url", -a);this.record.commit();this.hide()}});Ext.ns("Deluge"); -Deluge.EditTrackersWindow=Ext.extend(Ext.Window,{title:_("Edit Trackers"),layout:"fit",width:350,height:220,plain:!0,closable:!0,resizable:!0,constrainHeader:!0,bodyStyle:"padding: 5px",buttonAlign:"right",closeAction:"hide",iconCls:"x-deluge-edit-trackers",initComponent:function(){Deluge.EditTrackersWindow.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancelClick,this);this.addButton(_("OK"),this.onOkClick,this);this.addEvents("save");this.on("show",this.onShow,this);this.on("save", -this.onSave,this);this.addWindow=new Deluge.AddTrackerWindow;this.addWindow.on("add",this.onAddTrackers,this);this.editWindow=new Deluge.EditTrackerWindow;this.list=new Ext.list.ListView({store:new Ext.data.JsonStore({root:"trackers",fields:["tier","url"]}),columns:[{header:_("Tier"),width:0.1,dataIndex:"tier"},{header:_("Tracker"),width:0.9,dataIndex:"url",tpl:new Ext.XTemplate("{url:htmlEncode}")}],columnSort:{sortClasses:["",""]},stripeRows:!0,singleSelect:!0,listeners:{dblclick:{fn:this.onListNodeDblClicked, -scope:this},selectionchange:{fn:this.onSelect,scope:this}}});this.panel=this.add({items:[this.list],autoScroll:!0,bbar:new Ext.Toolbar({items:[{text:_("Up"),iconCls:"icon-up",handler:this.onUpClick,scope:this},{text:_("Down"),iconCls:"icon-down",handler:this.onDownClick,scope:this},"->",{text:_("Add"),iconCls:"icon-add",handler:this.onAddClick,scope:this},{text:_("Edit"),iconCls:"icon-edit-trackers",handler:this.onEditClick,scope:this},{text:_("Remove"),iconCls:"icon-remove",handler:this.onRemoveClick, -scope:this}]})})},onAddClick:function(){this.addWindow.show()},onAddTrackers:function(a){var b=this.list.getStore();Ext.each(a,function(a){var d=!1,f=-1;b.each(function(b){b.get("tier")>f&&(f=b.get("tier"));if(a==b.get("tracker"))return d=!0,!1},this);d||b.add(new b.recordType({tier:f+1,url:a}))},this)},onCancelClick:function(){this.hide()},onEditClick:function(){var a=this.list.getSelectedRecords()[0];a&&this.editWindow.show(a)},onHide:function(){this.list.getStore().removeAll()},onListNodeDblClicked:function(a, -b,c,d){this.editWindow.show(this.list.getRecord(c))},onOkClick:function(){var a=[];this.list.getStore().each(function(b){a.push({tier:b.get("tier"),url:b.get("url")})},this);deluge.client.core.set_torrent_trackers(this.torrentId,a,{failure:this.onSaveFail,scope:this});this.hide()},onRemoveClick:function(){var a=this.list.getSelectedRecords()[0];a&&this.list.getStore().remove(a)},onRequestComplete:function(a){this.list.getStore().loadData(a);this.list.getStore().sort("tier","ASC")},onSaveFail:function(){}, -onSelect:function(a){a.getSelectionCount()&&this.panel.getBottomToolbar().items.get(4).enable()},onShow:function(){this.panel.getBottomToolbar().items.get(4).disable();var a=deluge.torrents.getSelected();this.torrentId=a.id;deluge.client.core.get_torrent_status(a.id,["trackers"],{success:this.onRequestComplete,scope:this})},onDownClick:function(){var a=this.list.getSelectedRecords()[0];a&&(a.set("tier",a.get("tier")+1),a.store.sort("tier","ASC"),a.store.commitChanges(),this.list.select(a.store.indexOf(a)))}, -onUpClick:function(){var a=this.list.getSelectedRecords()[0];a&&0!=a.get("tier")&&(a.set("tier",a.get("tier")-1),a.store.sort("tier","ASC"),a.store.commitChanges(),this.list.select(a.store.indexOf(a)))}}); -Deluge.EventsManager=Ext.extend(Ext.util.Observable,{constructor:function(){this.toRegister=[];this.on("login",this.onLogin,this);Deluge.EventsManager.superclass.constructor.call(this)},addListener:function(a,b,c,d){this.addEvents(a);/[A-Z]/.test(a.substring(0,1))&&(deluge.client?deluge.client.web.register_event_listener(a):this.toRegister.push(a));Deluge.EventsManager.superclass.addListener.call(this,a,b,c,d)},getEvents:function(){deluge.client.web.get_events({success:this.onGetEventsSuccess,failure:this.onGetEventsFailure, -scope:this})},start:function(){Ext.each(this.toRegister,function(a){deluge.client.web.register_event_listener(a)});this.running=!0;this.errorCount=0;this.getEvents()},stop:function(){this.running=!1},onLogin:function(){this.start()},onGetEventsSuccess:function(a){this.running&&(a&&Ext.each(a,function(a){var c=a[1];c.splice(0,0,a[0]);this.fireEvent.apply(this,c)},this),this.getEvents())},onGetEventsFailure:function(a,b){this.running&&(!b.isTimeout&&3<=this.errorCount++?this.stop():this.getEvents())}}); -Deluge.EventsManager.prototype.on=Deluge.EventsManager.prototype.addListener;Deluge.EventsManager.prototype.fire=Deluge.EventsManager.prototype.fireEvent;deluge.events=new Deluge.EventsManager;Ext.namespace("Deluge"); -Deluge.FileBrowser=Ext.extend(Ext.Window,{title:_("File Browser"),width:500,height:400,initComponent:function(){Deluge.FileBrowser.superclass.initComponent.call(this);this.add({xtype:"toolbar",items:[{text:_("Back"),iconCls:"icon-back"},{text:_("Forward"),iconCls:"icon-forward"},{text:_("Up"),iconCls:"icon-up"},{text:_("Home"),iconCls:"icon-home"}]})}});Ext.ns("Deluge"); -Deluge.FilterPanel=Ext.extend(Ext.Panel,{autoScroll:!0,border:!1,show_zero:null,initComponent:function(){Deluge.FilterPanel.superclass.initComponent.call(this);this.filterType=this.initialConfig.filter;var a="";"state"==this.filterType?a=_("States"):"tracker_host"==this.filterType?a=_("Trackers"):"owner"==this.filterType?a=_("Owner"):"label"==this.filterType?a=_("Labels"):(a=this.filterType.replace("_"," "),parts=a.split(" "),a="",Ext.each(parts,function(b){fl=b.substring(0,1).toUpperCase();a+=fl+ -b.substring(1)+" "}));this.setTitle(_(a));var b=Deluge.FilterPanel.templates[this.filterType]?Deluge.FilterPanel.templates[this.filterType]:'<div class="x-deluge-filter x-deluge-{filter:lowercase}">{filter} ({count})</div>';this.list=this.add({xtype:"listview",singleSelect:!0,hideHeaders:!0,reserveScrollOffset:!0,store:new Ext.data.ArrayStore({idIndex:0,fields:["filter","count"]}),columns:[{id:"filter",sortable:!1,tpl:b,dataIndex:"filter"}]});this.relayEvents(this.list,["selectionchange"])},getState:function(){if(this.list.getSelectionCount()){var a= -this.list.getSelectedRecords()[0];if(a&&"All"!=a.id)return a.id}},getStates:function(){return this.states},getStore:function(){return this.list.getStore()},updateStates:function(a){this.states={};Ext.each(a,function(a){this.states[a[0]]=a[1]},this);if(!(null==this.show_zero?deluge.config.sidebar_show_zero:this.show_zero)){var b=[];Ext.each(a,function(a){(0<a[1]||"All"==a[0])&&b.push(a)});a=b}var c=this.getStore(),d={};Ext.each(a,function(a,b){var e=c.getById(a[0]);e||(e=new c.recordType({filter:a[0], -count:a[1]}),e.id=a[0],c.insert(b,e));e.beginEdit();e.set("filter",_(a[0]));e.set("count",a[1]);e.endEdit();d[a[0]]=!0},this);c.each(function(a){if(!d[a.id]){c.remove(a);var b=this.list.getSelectedRecords()[0];b&&b.id==a.id&&this.list.select(0)}},this);c.commitChanges();this.list.getSelectionCount()||this.list.select(0)}});Deluge.FilterPanel.templates={tracker_host:'<div class="x-deluge-filter" style="background-image: url('+deluge.config.base+'tracker/{filter});">{filter:htmlEncode} ({count})</div>'}; -Deluge.Formatters=function(){var a={"&":"&",">":">","<":"<",'"':""","'":"'"},b=RegExp("("+Object.keys(a).join("|")+")","g"),c=function(b,c){return a[c]};return Formatters={date:function(a){function b(a,c){for(var d=a+"";d.length<c;)d="0"+d;return d}a=new Date(1E3*a);return String.format("{0}/{1}/{2} {3}:{4}:{5}",b(a.getDate(),2),b(a.getMonth()+1,2),a.getFullYear(),b(a.getHours(),2),b(a.getMinutes(),2),b(a.getSeconds(),2))},size:function(a,b){if(!a&&!b)return"";a/=1024;if(1024>a)return a.toFixed(1)+ -" KiB";a/=1024;return 1024>a?a.toFixed(1)+" MiB":(a/1024).toFixed(1)+" GiB"},sizeShort:function(a,b){if(!a&&!b)return"";a/=1024;if(1024>a)return a.toFixed(1)+" K";a/=1024;return 1024>a?a.toFixed(1)+" M":(a/1024).toFixed(1)+" G"},speed:function(a,b){return!a&&!b?"":fsize(a,b)+"/s"},timeRemaining:function(a){if(0>=a)return"∞";a=a.toFixed(0);if(60>a)return a+"s";a/=60;if(60>a){var b=Math.floor(a);a=Math.round(60*(a-b));return 0<a?b+"m "+a+"s":b+"m"}a/=60;if(24>a){var c=Math.floor(a),b=Math.round(60* -(a-c));return 0<b?c+"h "+b+"m":c+"h"}a/=24;b=Math.floor(a);c=Math.round(24*(a-b));return 0<c?b+"d "+c+"h":b+"d"},plain:function(a){return a},cssClassEscape:function(a){return a.toLowerCase().replace(".","_")},htmlEncode:function(a){return!a?a:String(a).replace(b,c)}}}();var fsize=Deluge.Formatters.size,fsize_short=Deluge.Formatters.sizeShort,fspeed=Deluge.Formatters.speed,ftime=Deluge.Formatters.timeRemaining,fdate=Deluge.Formatters.date,fplain=Deluge.Formatters.plain; -Ext.util.Format.cssClassEscape=Deluge.Formatters.cssClassEscape;Ext.util.Format.htmlEncode=Deluge.Formatters.htmlEncode; -Deluge.Keys={Grid:"queue name total_wanted state progress num_seeds total_seeds num_peers total_peers download_payload_rate upload_payload_rate eta ratio distributed_copies is_auto_managed time_added tracker_host download_location last_seen_complete total_done total_uploaded max_download_speed max_upload_speed seeds_peers_ratio total_remaining completed_time time_since_transfer".split(" "),Status:"total_done total_payload_download total_uploaded total_payload_upload next_announce tracker_status num_pieces piece_length is_auto_managed active_time seeding_time time_since_transfer seed_rank last_seen_complete completed_time owner public shared".split(" "), -Files:["files","file_progress","file_priorities"],Peers:["peers"],Details:"name download_location total_size num_files message tracker_host comment creator".split(" "),Options:"max_download_speed max_upload_speed max_connections max_upload_slots is_auto_managed stop_at_ratio stop_ratio remove_at_ratio private prioritize_first_last move_completed move_completed_path super_seeding".split(" ")};Ext.each(Deluge.Keys.Grid,function(a){Deluge.Keys.Status.push(a)}); -Deluge.LoginWindow=Ext.extend(Ext.Window,{firstShow:!0,bodyStyle:"padding: 10px 5px;",buttonAlign:"center",closable:!1,closeAction:"hide",iconCls:"x-deluge-login-window-icon",layout:"fit",modal:!0,plain:!0,resizable:!1,title:_("Login"),width:300,height:120,initComponent:function(){Deluge.LoginWindow.superclass.initComponent.call(this);this.on("show",this.onShow,this);this.addButton({text:_("Login"),handler:this.onLogin,scope:this});this.form=this.add({xtype:"form",baseCls:"x-plain",labelWidth:120, -labelAlign:"right",defaults:{width:110},defaultType:"textfield"});this.passwordField=this.form.add({xtype:"textfield",fieldLabel:_("Password:"),labelSeparator:"",grow:!0,growMin:"110",growMax:"145",id:"_password",name:"password",inputType:"password"});this.passwordField.on("specialkey",this.onSpecialKey,this)},logout:function(){deluge.events.fire("logout");deluge.client.auth.delete_session({success:function(a){this.show(!0)},scope:this})},show:function(a){this.firstShow&&(deluge.client.on("error", -this.onClientError,this),this.firstShow=!1);if(a)return Deluge.LoginWindow.superclass.show.call(this);deluge.client.auth.check_session({success:function(a){a?deluge.events.fire("login"):this.show(!0)},failure:function(a){this.show(!0)},scope:this})},onSpecialKey:function(a,b){if(13==b.getKey())this.onLogin()},onLogin:function(){var a=this.passwordField;deluge.client.auth.login(a.getValue(),{success:function(b){b?(deluge.events.fire("login"),this.hide(),a.setRawValue("")):Ext.MessageBox.show({title:_("Login Failed"), -msg:_("You entered an incorrect password"),buttons:Ext.MessageBox.OK,modal:!1,fn:function(){a.focus(!0,10)},icon:Ext.MessageBox.WARNING,iconCls:"x-deluge-icon-warning"})},scope:this})},onClientError:function(a,b,c){1==a.error.code&&(deluge.events.fire("logout"),this.show(!0))},onShow:function(){this.passwordField.focus(!0,300)}}); -deluge.menus={onTorrentActionSetOpt:function(a,b){var c=deluge.torrents.getSelectedIds(),d=a.initialConfig.torrentAction,f={};f[d[0]]=d[1];deluge.client.core.set_torrent_options(c,f)},onTorrentActionMethod:function(a,b){var c=deluge.torrents.getSelectedIds();deluge.client.core[a.initialConfig.torrentAction](c,{success:function(){deluge.ui.update()}})},onTorrentActionShow:function(a,b){var c=deluge.torrents.getSelectedIds();switch(a.initialConfig.torrentAction){case "copy_magnet":deluge.copyMagnetWindow.show(); -break;case "edit_trackers":deluge.editTrackers.show();break;case "remove":deluge.removeWindow.show(c);break;case "move":deluge.moveStorage.show(c)}}}; -deluge.menus.torrent=new Ext.menu.Menu({id:"torrentMenu",items:[{torrentAction:"pause_torrent",text:_("Pause"),iconCls:"icon-pause",handler:deluge.menus.onTorrentActionMethod,scope:deluge.menus},{torrentAction:"resume_torrent",text:_("Resume"),iconCls:"icon-resume",handler:deluge.menus.onTorrentActionMethod,scope:deluge.menus},"-",{text:_("Options"),iconCls:"icon-options",hideOnClick:!1,menu:new Ext.menu.Menu({items:[{text:_("D/L Speed Limit"),iconCls:"x-deluge-downloading",hideOnClick:!1,menu:new Ext.menu.Menu({items:[{torrentAction:["max_download_speed", -5],text:_("5 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_download_speed",10],text:_("10 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_download_speed",30],text:_("30 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_download_speed",80],text:_("80 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_download_speed",300],text:_("300 KiB/s"), -handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_download_speed",-1],text:_("Unlimited"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus}]})},{text:_("U/L Speed Limit"),iconCls:"x-deluge-seeding",hideOnClick:!1,menu:new Ext.menu.Menu({items:[{torrentAction:["max_upload_speed",5],text:_("5 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_speed",10],text:_("10 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt, -scope:deluge.menus},{torrentAction:["max_upload_speed",30],text:_("30 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_speed",80],text:_("80 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_speed",300],text:_("300 KiB/s"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_speed",-1],text:_("Unlimited"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus}]})}, -{text:_("Connection Limit"),iconCls:"x-deluge-connections",hideOnClick:!1,menu:new Ext.menu.Menu({items:[{torrentAction:["max_connections",50],text:"50",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_connections",100],text:"100",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_connections",200],text:"200",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_connections",300],text:"300",handler:deluge.menus.onTorrentActionSetOpt, -scope:deluge.menus},{torrentAction:["max_connections",500],text:"500",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_connections",-1],text:_("Unlimited"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus}]})},{text:_("Upload Slot Limit"),iconCls:"icon-upload-slots",hideOnClick:!1,menu:new Ext.menu.Menu({items:[{torrentAction:["max_upload_slots",0],text:"0",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_slots", -1],text:"1",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_slots",2],text:"2",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_slots",3],text:"3",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_slots",5],text:"5",handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["max_upload_slots",-1],text:_("Unlimited"),handler:deluge.menus.onTorrentActionSetOpt, -scope:deluge.menus}]})},{id:"auto_managed",text:_("Auto Managed"),hideOnClick:!1,menu:new Ext.menu.Menu({items:[{torrentAction:["auto_managed",!0],text:_("On"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus},{torrentAction:["auto_managed",!1],text:_("Off"),handler:deluge.menus.onTorrentActionSetOpt,scope:deluge.menus}]})}]})},"-",{text:_("Queue"),iconCls:"icon-queue",hideOnClick:!1,menu:new Ext.menu.Menu({items:[{torrentAction:"queue_top",text:_("Top"),iconCls:"icon-top",handler:deluge.menus.onTorrentActionMethod, -scope:deluge.menus},{torrentAction:"queue_up",text:_("Up"),iconCls:"icon-up",handler:deluge.menus.onTorrentActionMethod,scope:deluge.menus},{torrentAction:"queue_down",text:_("Down"),iconCls:"icon-down",handler:deluge.menus.onTorrentActionMethod,scope:deluge.menus},{torrentAction:"queue_bottom",text:_("Bottom"),iconCls:"icon-bottom",handler:deluge.menus.onTorrentActionMethod,scope:deluge.menus}]})},"-",{torrentAction:"copy_magnet",text:_("Copy Magnet URI"),iconCls:"icon-magnet-copy",handler:deluge.menus.onTorrentActionShow, -scope:deluge.menus},{torrentAction:"force_reannounce",text:_("Update Tracker"),iconCls:"icon-update-tracker",handler:deluge.menus.onTorrentActionMethod,scope:deluge.menus},{torrentAction:"edit_trackers",text:_("Edit Trackers"),iconCls:"icon-edit-trackers",handler:deluge.menus.onTorrentActionShow,scope:deluge.menus},"-",{torrentAction:"remove",text:_("Remove Torrent"),iconCls:"icon-remove",handler:deluge.menus.onTorrentActionShow,scope:deluge.menus},"-",{torrentAction:"force_recheck",text:_("Force Recheck"), -iconCls:"icon-recheck",handler:deluge.menus.onTorrentActionMethod,scope:deluge.menus},{torrentAction:"move",text:_("Move Download Folder"),iconCls:"icon-move",handler:deluge.menus.onTorrentActionShow,scope:deluge.menus}]}); -deluge.menus.filePriorities=new Ext.menu.Menu({id:"filePrioritiesMenu",items:[{id:"expandAll",text:_("Expand All"),iconCls:"icon-expand-all"},"-",{id:"skip",text:_("Skip"),iconCls:"icon-do-not-download",filePriority:FILE_PRIORITY.Skip},{id:"low",text:_("Low"),iconCls:"icon-low",filePriority:FILE_PRIORITY.Low},{id:"normal",text:_("Normal"),iconCls:"icon-normal",filePriority:FILE_PRIORITY.Normal},{id:"high",text:_("High"),iconCls:"icon-high",filePriority:FILE_PRIORITY.High}]});Ext.namespace("Deluge"); -Deluge.MoveStorage=Ext.extend(Ext.Window,{constructor:function(a){a=Ext.apply({title:_("Move Download Folder"),width:375,height:110,layout:"fit",buttonAlign:"right",closeAction:"hide",closable:!0,iconCls:"x-deluge-move-storage",plain:!0,constrainHeader:!0,resizable:!1},a);Deluge.MoveStorage.superclass.constructor.call(this,a)},initComponent:function(){Deluge.MoveStorage.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancel,this);this.addButton(_("Move"),this.onMove,this);this.form= -this.add({xtype:"form",border:!1,defaultType:"textfield",width:300,bodyStyle:"padding: 5px"});this.moveLocation=this.form.add({fieldLabel:_("Download Folder"),name:"location",width:240})},hide:function(){Deluge.MoveStorage.superclass.hide.call(this);this.torrentIds=null},show:function(a){Deluge.MoveStorage.superclass.show.call(this);this.torrentIds=a},onCancel:function(){this.hide()},onMove:function(){var a=this.moveLocation.getValue();deluge.client.core.move_storage(this.torrentIds,a);this.hide()}}); -deluge.moveStorage=new Deluge.MoveStorage; -Deluge.MultiOptionsManager=Ext.extend(Deluge.OptionsManager,{constructor:function(a){this.currentId=null;this.stored={};Deluge.MultiOptionsManager.superclass.constructor.call(this,a)},changeId:function(a,b){var c=this.currentId;this.currentId=a;if(!b)for(var d in this.options)this.binds[d]&&Ext.each(this.binds[d],function(a){a.setValue(this.get(d))},this);return c},commit:function(){this.stored[this.currentId]=Ext.apply(this.stored[this.currentId],this.changed[this.currentId]);this.reset()},get:function(){if(1== -arguments.length){var a=arguments[0];return this.isDirty(a)?this.changed[this.currentId][a]:this.getDefault(a)}if(0==arguments.length){var b={};for(a in this.options)b[a]=this.isDirty(a)?this.changed[this.currentId][a]:this.getDefault(a)}else b={},Ext.each(arguments,function(a){b[a]=this.isDirty(a)?this.changed[this.currentId][a]:this.getDefault(a)},this);return b},getDefault:function(a){return this.has(a)?this.stored[this.currentId][a]:this.options[a]},getDirty:function(){return this.changed[this.currentId]? -this.changed[this.currentId]:{}},isDirty:function(a){return this.changed[this.currentId]&&!Ext.isEmpty(this.changed[this.currentId][a])},has:function(a){return this.stored[this.currentId]&&!Ext.isEmpty(this.stored[this.currentId][a])},reset:function(){this.changed[this.currentId]&&delete this.changed[this.currentId];this.stored[this.currentId]&&delete this.stored[this.currentId]},resetAll:function(){this.changed={};this.stored={};this.changeId(null)},setDefault:function(a,b){if(void 0!==a)if(void 0=== -b)for(var c in a)this.setDefault(c,a[c]);else c=this.getDefault(a),b=this.convertValueType(c,b),c!=b&&(this.stored[this.currentId]||(this.stored[this.currentId]={}),this.stored[this.currentId][a]=b,this.isDirty(a)||this.fireEvent("changed",a,b,c))},update:function(a,b){if(void 0!==a)if(void 0===b)for(var c in a)this.update(c,a[c]);else{this.changed[this.currentId]||(this.changed[this.currentId]={});c=this.getDefault(a);b=this.convertValueType(c,b);var d=this.get(a);d!=b&&(c==b?this.isDirty(a)&&delete this.changed[this.currentId][a]: -this.changed[this.currentId][a]=b,this.fireEvent("changed",a,b,d))}}});Ext.ns("Deluge"); -Deluge.OtherLimitWindow=Ext.extend(Ext.Window,{layout:"fit",width:210,height:100,constrainHeader:!0,closeAction:"hide",initComponent:function(){Deluge.OtherLimitWindow.superclass.initComponent.call(this);this.form=this.add({xtype:"form",baseCls:"x-plain",bodyStyle:"padding: 5px",layout:"hbox",layoutConfig:{pack:"start"},items:[{xtype:"spinnerfield",name:"limit"}]});this.initialConfig.unit?this.form.add({border:!1,baseCls:"x-plain",bodyStyle:"padding: 5px",html:this.initialConfig.unit}):this.setSize(180, -100);this.addButton(_("Cancel"),this.onCancelClick,this);this.addButton(_("OK"),this.onOkClick,this);this.afterMethod("show",this.doFocusField,this)},setValue:function(a){this.form.getForm().setValues({limit:a})},onCancelClick:function(){this.form.getForm().reset();this.hide()},onOkClick:function(){var a={};a[this.group]=this.form.getForm().getValues().limit;deluge.client.core.set_config(a,{success:function(){deluge.ui.update()}});this.hide()},doFocusField:function(){this.form.getForm().findField("limit").focus(!0, -10)}});Ext.ns("Deluge"); -Deluge.Plugin=Ext.extend(Ext.util.Observable,{name:null,constructor:function(a){this.isDelugePlugin=!0;this.addEvents({enabled:!0,disabled:!0});Deluge.Plugin.superclass.constructor.call(this,a)},disable:function(){this.fireEvent("disabled",this);if(this.onDisable)this.onDisable()},enable:function(){deluge.client.reloadMethods();this.fireEvent("enable",this);if(this.onEnable)this.onEnable()},registerTorrentStatus:function(a,b,c){c=c||{};var d=c.colCfg||{};c=c.storeCfg||{};c=Ext.apply(c,{name:a});deluge.torrents.meta.fields.push(c); -deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta);d=Ext.apply(d,{header:b,dataIndex:a});b=deluge.torrents.columns.slice(0);b.push(d);deluge.torrents.colModel.setConfig(b);deluge.torrents.columns=b;Deluge.Keys.Grid.push(a);deluge.torrents.getView().refresh(!0)},deregisterTorrentStatus:function(a){var b=[];Ext.each(deluge.torrents.meta.fields,function(c){c.name!=a&&b.push(c)});deluge.torrents.meta.fields=b;deluge.torrents.getStore().reader.onMetaChange(deluge.torrents.meta);var c= -[];Ext.each(deluge.torrents.columns,function(b){b.dataIndex!=a&&c.push(b)});deluge.torrents.colModel.setConfig(c);deluge.torrents.columns=c;var d=[];Ext.each(Deluge.Keys.Grid,function(b){b==a&&d.push(b)});Deluge.Keys.Grid=d;deluge.torrents.getView().refresh(!0)}});Ext.ns("Deluge.plugins"); -Deluge.RemoveWindow=Ext.extend(Ext.Window,{title:_("Remove Torrent"),layout:"fit",width:350,height:100,constrainHeader:!0,buttonAlign:"right",closeAction:"hide",closable:!0,iconCls:"x-deluge-remove-window-icon",plain:!0,bodyStyle:"padding: 5px; padding-left: 10px;",html:"Are you sure you wish to remove the torrent (s)?",initComponent:function(){Deluge.RemoveWindow.superclass.initComponent.call(this);this.addButton(_("Cancel"),this.onCancel,this);this.addButton(_("Remove With Data"),this.onRemoveData, -this);this.addButton(_("Remove Torrent"),this.onRemove,this)},remove:function(a){deluge.client.core.remove_torrents(this.torrentIds,a,{success:function(a){!0==a&&console.log("Error(s) occured when trying to delete torrent(s).");this.onRemoved(this.torrentIds)},scope:this,torrentIds:this.torrentIds})},show:function(a){Deluge.RemoveWindow.superclass.show.call(this);this.torrentIds=a},onCancel:function(){this.hide();this.torrentIds=null},onRemove:function(){this.remove(!1)},onRemoveData:function(){this.remove(!0)}, -onRemoved:function(a){deluge.events.fire("torrentsRemoved",a);this.hide();deluge.ui.update()}});deluge.removeWindow=new Deluge.RemoveWindow; -Deluge.Sidebar=Ext.extend(Ext.Panel,{panels:{},selected:null,constructor:function(a){a=Ext.apply({id:"sidebar",region:"west",cls:"deluge-sidebar",title:_("Filters"),layout:"accordion",split:!0,width:200,minSize:100,collapsible:!0},a);Deluge.Sidebar.superclass.constructor.call(this,a)},initComponent:function(){Deluge.Sidebar.superclass.initComponent.call(this);deluge.events.on("disconnect",this.onDisconnect,this)},createFilter:function(a,b){var c=new Deluge.FilterPanel({filter:a});c.on("selectionchange", -function(a,b){deluge.ui.update()});this.add(c);this.doLayout();this.panels[a]=c;c.header.on("click",function(a){deluge.config.sidebar_multiple_filters||deluge.ui.update();c.list.getSelectionCount()||c.list.select(0)});this.fireEvent("filtercreate",this,c);c.updateStates(b);this.fireEvent("afterfiltercreate",this,c)},getFilter:function(a){return this.panels[a]},getFilterStates:function(){var a={};if(deluge.config.sidebar_multiple_filters)this.items.each(function(b){var c=b.getState();null!=c&&(a[b.filterType]= -c)},this);else{var b=this.getLayout().activeItem;if(b){var c=b.getState();if(null==!c)return;a[b.filterType]=c}}return a},hasFilter:function(a){return this.panels[a]?!0:!1},onDisconnect:function(){for(var a in this.panels)this.remove(this.panels[a]);this.panels={};this.selected=null},onFilterSelect:function(a,b,c){deluge.ui.update()},update:function(a){for(var b in a){var c=a[b];-1<Ext.getKeys(this.panels).indexOf(b)?this.panels[b].updateStates(c):this.createFilter(b,c)}Ext.each(Ext.keys(this.panels), -function(b){-1==Ext.keys(a).indexOf(b)&&(this.remove(this.panels[b]),this.doLayout(),delete this.panels[b])},this)}});Ext.namespace("Deluge"); -Deluge.Statusbar=Ext.extend(Ext.ux.StatusBar,{constructor:function(a){a=Ext.apply({id:"deluge-statusbar",defaultIconCls:"x-deluge-statusbar x-not-connected",defaultText:_("Not Connected")},a);Deluge.Statusbar.superclass.constructor.call(this,a)},initComponent:function(){Deluge.Statusbar.superclass.initComponent.call(this);deluge.events.on("connect",this.onConnect,this);deluge.events.on("disconnect",this.onDisconnect,this)},createButtons:function(){this.buttons=this.add({id:"statusbar-connections", -text:" ",cls:"x-btn-text-icon",iconCls:"x-deluge-connections",tooltip:_("Connections"),menu:new Deluge.StatusbarMenu({items:[{text:"50",value:"50",group:"max_connections_global",checked:!1},{text:"100",value:"100",group:"max_connections_global",checked:!1},{text:"200",value:"200",group:"max_connections_global",checked:!1},{text:"300",value:"300",group:"max_connections_global",checked:!1},{text:"500",value:"500",group:"max_connections_global",checked:!1},{text:_("Unlimited"),value:"-1",group:"max_connections_global", -checked:!1},"-",{text:_("Other"),value:"other",group:"max_connections_global",checked:!1}],otherWin:{title:_("Set Maximum Connections")}})},"-",{id:"statusbar-downspeed",text:" ",cls:"x-btn-text-icon",iconCls:"x-deluge-downloading",tooltip:_("Download Speed"),menu:new Deluge.StatusbarMenu({items:[{value:"5",text:_("5 KiB/s"),group:"max_download_speed",checked:!1},{value:"10",text:_("10 KiB/s"),group:"max_download_speed",checked:!1},{value:"30",text:_("30 KiB/s"),group:"max_download_speed",checked:!1}, -{value:"80",text:_("80 KiB/s"),group:"max_download_speed",checked:!1},{value:"300",text:_("300 KiB/s"),group:"max_download_speed",checked:!1},{value:"-1",text:_("Unlimited"),group:"max_download_speed",checked:!1},"-",{value:"other",text:_("Other"),group:"max_download_speed",checked:!1}],otherWin:{title:_("Set Maximum Download Speed"),unit:_("KiB/s")}})},"-",{id:"statusbar-upspeed",text:" ",cls:"x-btn-text-icon",iconCls:"x-deluge-seeding",tooltip:_("Upload Speed"),menu:new Deluge.StatusbarMenu({items:[{value:"5", -text:_("5 KiB/s"),group:"max_upload_speed",checked:!1},{value:"10",text:_("10 KiB/s"),group:"max_upload_speed",checked:!1},{value:"30",text:_("30 KiB/s"),group:"max_upload_speed",checked:!1},{value:"80",text:_("80 KiB/s"),group:"max_upload_speed",checked:!1},{value:"300",text:_("300 KiB/s"),group:"max_upload_speed",checked:!1},{value:"-1",text:_("Unlimited"),group:"max_upload_speed",checked:!1},"-",{value:"other",text:_("Other"),group:"max_upload_speed",checked:!1}],otherWin:{title:_("Set Maximum Upload Speed"), -unit:_("KiB/s")}})},"-",{id:"statusbar-traffic",text:" ",cls:"x-btn-text-icon",iconCls:"x-deluge-traffic",tooltip:_("Protocol Traffic Download/Upload"),handler:function(){deluge.preferences.show();deluge.preferences.selectPage("Network")}},"-",{id:"statusbar-externalip",text:" ",cls:"x-btn-text",tooltip:_("External IP Address")},"-",{id:"statusbar-dht",text:" ",cls:"x-btn-text-icon",iconCls:"x-deluge-dht",tooltip:_("DHT Nodes")},"-",{id:"statusbar-freespace",text:" ",cls:"x-btn-text-icon",iconCls:"x-deluge-freespace", -tooltip:_("Freespace in download folder"),handler:function(){deluge.preferences.show();deluge.preferences.selectPage("Downloads")}});this.created=!0},onConnect:function(){this.setStatus({iconCls:"x-connected",text:""});this.created?Ext.each(this.buttons,function(a){a.show();a.enable()}):this.createButtons();this.doLayout()},onDisconnect:function(){this.clearStatus({useDefaults:!0});Ext.each(this.buttons,function(a){a.hide();a.disable()});this.doLayout()},update:function(a){function b(a){return a+ -" KiB/s"}if(a){var c=function(a,b){var c=this.items.get("statusbar-"+a);if(0<b.limit.value)var e=b.value.formatter?b.value.formatter(b.value.value,!0):b.value.value,l=b.limit.formatter?b.limit.formatter(b.limit.value,!0):b.limit.value,e=String.format(b.format,e,l);else e=b.value.formatter?b.value.formatter(b.value.value,!0):b.value.value;c.setText(e);c.menu&&c.menu.setValue(b.limit.value)}.createDelegate(this);c("connections",{value:{value:a.num_connections},limit:{value:a.max_num_connections},format:"{0} ({1})"}); -c("downspeed",{value:{value:a.download_rate,formatter:Deluge.Formatters.speed},limit:{value:a.max_download,formatter:b},format:"{0} ({1})"});c("upspeed",{value:{value:a.upload_rate,formatter:Deluge.Formatters.speed},limit:{value:a.max_upload,formatter:b},format:"{0} ({1})"});c("traffic",{value:{value:a.download_protocol_rate,formatter:Deluge.Formatters.speed},limit:{value:a.upload_protocol_rate,formatter:Deluge.Formatters.speed},format:"{0}/{1}"});this.items.get("statusbar-dht").setText(a.dht_nodes); -this.items.get("statusbar-freespace").setText(0<=a.free_space?fsize(a.free_space):_("Error"));this.items.get("statusbar-externalip").setText(String.format(_("<b>IP</b> {0}"),a.external_ip?a.external_ip:_("n/a")))}}}); -Deluge.Toolbar=Ext.extend(Ext.Toolbar,{constructor:function(a){a=Ext.apply({items:[{id:"tbar-deluge-text",text:_("Deluge"),iconCls:"x-deluge-main-panel",handler:this.onAboutClick},new Ext.Toolbar.Separator,{id:"create",disabled:!0,hidden:!0,text:_("Create"),iconCls:"icon-create",handler:this.onTorrentAction},{id:"add",disabled:!0,text:_("Add"),iconCls:"icon-add",handler:this.onTorrentAdd},{id:"remove",disabled:!0,text:_("Remove"),iconCls:"icon-remove",handler:this.onTorrentAction},new Ext.Toolbar.Separator, -{id:"pause",disabled:!0,text:_("Pause"),iconCls:"icon-pause",handler:this.onTorrentAction},{id:"resume",disabled:!0,text:_("Resume"),iconCls:"icon-resume",handler:this.onTorrentAction},new Ext.Toolbar.Separator,{id:"up",cls:"x-btn-text-icon",disabled:!0,text:_("Up"),iconCls:"icon-up",handler:this.onTorrentAction},{id:"down",disabled:!0,text:_("Down"),iconCls:"icon-down",handler:this.onTorrentAction},new Ext.Toolbar.Separator,{id:"preferences",text:_("Preferences"),iconCls:"x-deluge-preferences",handler:this.onPreferencesClick, -scope:this},{id:"connectionman",text:_("Connection Manager"),iconCls:"x-deluge-connection-manager",handler:this.onConnectionManagerClick,scope:this},"->",{id:"help",iconCls:"icon-help",text:_("Help"),handler:this.onHelpClick,scope:this},{id:"logout",iconCls:"icon-logout",disabled:!0,text:_("Logout"),handler:this.onLogout,scope:this}]},a);Deluge.Toolbar.superclass.constructor.call(this,a)},connectedButtons:"add remove pause resume up down".split(" "),initComponent:function(){Deluge.Toolbar.superclass.initComponent.call(this); -deluge.events.on("connect",this.onConnect,this);deluge.events.on("login",this.onLogin,this)},onConnect:function(){Ext.each(this.connectedButtons,function(a){this.items.get(a).enable()},this)},onDisconnect:function(){Ext.each(this.connectedButtons,function(a){this.items.get(a).disable()},this)},onLogin:function(){this.items.get("logout").enable()},onLogout:function(){this.items.get("logout").disable();deluge.login.logout()},onConnectionManagerClick:function(){deluge.connectionManager.show()},onHelpClick:function(){window.open("http://dev.deluge-torrent.org/wiki/UserGuide")}, -onAboutClick:function(){(new Deluge.about.AboutWindow).show()},onPreferencesClick:function(){deluge.preferences.show()},onTorrentAction:function(a){var b=deluge.torrents.getSelections(),c=[];Ext.each(b,function(a){c.push(a.id)});switch(a.id){case "remove":deluge.removeWindow.show(c);break;case "pause":case "resume":deluge.client.core[a.id+"_torrent"](c,{success:function(){deluge.ui.update()}});break;case "up":case "down":deluge.client.core["queue_"+a.id](c,{success:function(){deluge.ui.update()}})}}, -onTorrentAdd:function(){deluge.add.show()}}); -(function(){function a(a){if(a)return fspeed(a)}function b(a){return-1==a?"":fspeed(1024*a)}function c(a,b,c){return 0>a?"∞":parseFloat((new Number(a)).toFixed(3))}function d(a){return 0<a?fdate(a):_("Never")}Deluge.TorrentGrid=Ext.extend(Ext.grid.GridPanel,{torrents:{},columns:[{id:"queue",header:"#",width:30,sortable:!0,renderer:function(a){return-1==a?"":a+1},dataIndex:"queue"},{id:"name",header:_("Name"),width:150,sortable:!0,renderer:function(a,b,c){return String.format('<div class="torrent-name x-deluge-{0}">{1}</div>', -c.data.state.toLowerCase(),Ext.util.Format.htmlEncode(a))},dataIndex:"name"},{header:_("Size"),width:75,sortable:!0,renderer:fsize,dataIndex:"total_wanted"},{header:_("Progress"),width:150,sortable:!0,renderer:function(a,b,c){a=new Number(a);c=_(c.data.state)+" "+a.toFixed(2)+"%";b=new Number((this.style?this.style:b.style).match(/\w+:\s*(\d+)\w+/)[1]);return Deluge.progressBar(a,b-8,c)},dataIndex:"progress"},{header:_("Seeds"),hidden:!0,width:60,sortable:!0,renderer:function(a,b,c){return-1<c.data.total_seeds? -String.format("{0} ({1})",a,c.data.total_seeds):a},dataIndex:"num_seeds"},{header:_("Peers"),hidden:!0,width:60,sortable:!0,renderer:function(a,b,c){return-1<c.data.total_peers?String.format("{0} ({1})",a,c.data.total_peers):a},dataIndex:"num_peers"},{header:_("Down Speed"),width:80,sortable:!0,renderer:a,dataIndex:"download_payload_rate"},{header:_("Up Speed"),width:80,sortable:!0,renderer:a,dataIndex:"upload_payload_rate"},{header:_("ETA"),width:60,sortable:!0,renderer:function(a){return 0===a? -"":-1>=a?"∞":ftime(a)},dataIndex:"eta"},{header:_("Ratio"),hidden:!0,width:60,sortable:!0,renderer:c,dataIndex:"ratio"},{header:_("Avail"),hidden:!0,width:60,sortable:!0,renderer:c,dataIndex:"distributed_copies"},{header:_("Added"),hidden:!0,width:80,sortable:!0,renderer:fdate,dataIndex:"time_added"},{header:_("Complete Seen"),hidden:!0,width:80,sortable:!0,renderer:d,dataIndex:"last_seen_complete"},{header:_("Completed"),hidden:!0,width:80,sortable:!0,renderer:d,dataIndex:"completed_time"}, -{header:_("Tracker"),hidden:!0,width:120,sortable:!0,renderer:function(a,b,c){return String.format('<div style="background: url('+deluge.config.base+'tracker/{0}) no-repeat; padding-left: 20px;">{0}</div>',Ext.util.Format.htmlEncode(a))},dataIndex:"tracker_host"},{header:_("Download Folder"),hidden:!0,width:120,sortable:!0,renderer:fplain,dataIndex:"download_location"},{header:_("Owner"),width:80,sortable:!0,renderer:fplain,dataIndex:"owner"},{header:_("Public"),hidden:!0,width:80,sortable:!0,renderer:fplain, -dataIndex:"public"},{header:_("Shared"),hidden:!0,width:80,sortable:!0,renderer:fplain,dataIndex:"shared"},{header:_("Downloaded"),hidden:!0,width:75,sortable:!0,renderer:fsize,dataIndex:"total_done"},{header:_("Uploaded"),hidden:!0,width:75,sortable:!0,renderer:fsize,dataIndex:"total_uploaded"},{header:_("Remaining"),hidden:!0,width:75,sortable:!0,renderer:fsize,dataIndex:"total_remaining"},{header:_("Down Limit"),hidden:!0,width:75,sortable:!0,renderer:b,dataIndex:"max_download_speed"},{header:_("Up Limit"), -hidden:!0,width:75,sortable:!0,renderer:b,dataIndex:"max_upload_speed"},{header:_("Seeds:Peers"),hidden:!0,width:75,sortable:!0,renderer:c,dataIndex:"seeds_peers_ratio"},{header:_("Last Transfer"),hidden:!0,width:75,sortable:!0,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:function(a){return 0===a?Number.MAX_VALUE:-1>=a?Number.MAX_SAFE_INTEGER:a}},{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:!0,stopEvent:!0,handler:function(){deluge.torrents.getSelectionModel().selectAll()}},{key:[46],stopEvent:!0,handler:function(){ids=deluge.torrents.getSelectedIds();deluge.removeWindow.show(ids)}}], -constructor:function(a){a=Ext.apply({id:"torrentGrid",store:new Ext.data.JsonStore(this.meta),columns:this.columns,keys:this.keys,region:"center",cls:"deluge-torrents",stripeRows:!0,autoExpandColumn:"name",autoExpandMin:150,deferredRender:!1,autoScroll:!0,stateful:!0,view:new Ext.ux.grid.BufferView({rowHeight:26,scrollDelay:!1})},a);Deluge.TorrentGrid.superclass.constructor.call(this,a)},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(a,b,c){c.stopEvent();a=a.getSelectionModel();a.isSelected(b)||a.selectRow(b);deluge.menus.torrent.showAt(c.getPoint())})},getTorrent:function(a){return this.getStore().getAt(a)},getSelected:function(){return this.getSelectionModel().getSelected()},getSelections:function(){return this.getSelectionModel().getSelections()},getSelectedId:function(){return this.getSelectionModel().getSelected().id}, -getSelectedIds:function(){var a=[];Ext.each(this.getSelectionModel().getSelections(),function(b){a.push(b.id)});return a},update:function(a,b){var c=this.getStore();b&&(c.removeAll(),this.torrents={});var d=[],h;for(h in a){var m=a[h];if(this.torrents[h]){var k=c.getById(h);k.beginEdit();for(var n in m)k.get(n)!=m[n]&&k.set(n,m[n]);k.endEdit()}else k=new Deluge.data.Torrent(m),k.id=h,this.torrents[h]=1,d.push(k)}c.add(d);c.each(function(b){a[b.id]||(c.remove(b),delete this.torrents[b.id])},this); -c.commitChanges();(d=c.getSortState())&&c.sort(d.field,d.direction)},onDisconnect:function(){this.getStore().removeAll();this.torrents={}},onTorrentsRemoved:function(a){var b=this.getSelectionModel();Ext.each(a,function(a){var c=this.getStore().getById(a);b.isSelected(c)&&b.deselectRow(this.getStore().indexOf(c));this.getStore().remove(c);delete this.torrents[a]},this)}});deluge.torrents=new Deluge.TorrentGrid})(); -var TORRENT_STATE_TRANSLATION=[_("All"),_("Active"),_("Allocating"),_("Checking"),_("Downloading"),_("Seeding"),_("Paused"),_("Checking"),_("Queued"),_("Error")]; -deluge.ui={errorCount:0,filters:null,initialize:function(){deluge.add=new Deluge.add.AddWindow;deluge.details=new Deluge.details.DetailsPanel;deluge.connectionManager=new Deluge.ConnectionManager;deluge.editTrackers=new Deluge.EditTrackersWindow;deluge.login=new Deluge.LoginWindow;deluge.preferences=new Deluge.preferences.PreferencesWindow;deluge.sidebar=new Deluge.Sidebar;deluge.statusbar=new Deluge.Statusbar;deluge.toolbar=new Deluge.Toolbar;this.detailsPanel=new Ext.Panel({id:"detailsPanel",cls:"detailsPanel", -region:"south",split:!0,height:215,minSize:100,collapsible:!0,layout:"fit",items:[deluge.details]});this.MainPanel=new Ext.Panel({id:"mainPanel",iconCls:"x-deluge-main-panel",layout:"border",border:!1,tbar:deluge.toolbar,items:[deluge.sidebar,this.detailsPanel,deluge.torrents],bbar:deluge.statusbar});this.Viewport=new Ext.Viewport({layout:"fit",items:[this.MainPanel]});deluge.events.on("connect",this.onConnect,this);deluge.events.on("disconnect",this.onDisconnect,this);deluge.events.on("PluginDisabledEvent", -this.onPluginDisabled,this);deluge.events.on("PluginEnabledEvent",this.onPluginEnabled,this);deluge.client=new Ext.ux.util.RpcClient({url:deluge.config.base+"json"});for(var a in Deluge.pluginStore)a=Deluge.createPlugin(a),a.enable(),deluge.plugins[a.name]=a;Ext.QuickTips.init();deluge.client.on("connected",function(a){deluge.login.show()},this,{single:!0});this.update=this.update.createDelegate(this);this.checkConnection=this.checkConnection.createDelegate(this);this.originalTitle=document.title}, -checkConnection:function(){deluge.client.web.connected({success:this.onConnectionSuccess,failure:this.onConnectionError,scope:this})},update:function(){var a=deluge.sidebar.getFilterStates();this.oldFilters=this.filters;this.filters=a;deluge.client.web.update_ui(Deluge.Keys.Grid,a,{success:this.onUpdate,failure:this.onUpdateError,scope:this});deluge.details.update()},onConnectionError:function(a){},onConnectionSuccess:function(a){deluge.statusbar.setStatus({iconCls:"x-deluge-statusbar icon-ok",text:_("Connection restored")}); -clearInterval(this.checking);a||deluge.connectionManager.show()},onUpdateError:function(a){2==this.errorCount&&(Ext.MessageBox.show({title:_("Lost Connection"),msg:_("The connection to the webserver has been lost!"),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.ERROR}),deluge.events.fire("disconnect"),deluge.statusbar.setStatus({text:_("Lost connection to webserver")}),this.checking=setInterval(this.checkConnection,2E3));this.errorCount++},onUpdate:function(a){a.connected?(deluge.config.show_session_speed&& -(document.title="D: "+fsize_short(a.stats.download_rate,!0)+" U: "+fsize_short(a.stats.upload_rate,!0)+" - "+this.originalTitle),Ext.areObjectsEqual(this.filters,this.oldFilters)?deluge.torrents.update(a.torrents):deluge.torrents.update(a.torrents,!0),deluge.statusbar.update(a.stats),deluge.sidebar.update(a.filters),this.errorCount=0):deluge.connectionManager.disconnect(!0)},onConnect:function(){this.running||(this.running=setInterval(this.update,2E3),this.update());deluge.client.web.get_plugins({success:this.onGotPlugins, -scope:this})},onDisconnect:function(){this.stop()},onGotPlugins:function(a){Ext.each(a.enabled_plugins,function(a){deluge.plugins[a]||deluge.client.web.get_plugin_resources(a,{success:this.onGotPluginResources,scope:this})},this)},onPluginEnabled:function(a){deluge.plugins[a]?deluge.plugins[a].enable():deluge.client.web.get_plugin_resources(a,{success:this.onGotPluginResources,scope:this})},onGotPluginResources:function(a){Ext.each(Deluge.debug?a.debug_scripts:a.scripts,function(b){Ext.ux.JSLoader({url:deluge.config.base+ -b,onLoad:this.onPluginLoaded,pluginName:a.name})},this)},onPluginDisabled:function(a){deluge.plugins[a]&&deluge.plugins[a].disable()},onPluginLoaded:function(a){Deluge.hasPlugin(a.pluginName)&&(plugin=Deluge.createPlugin(a.pluginName),plugin.enable(),deluge.plugins[plugin.name]=plugin)},stop:function(){this.running&&(clearInterval(this.running),this.running=!1,deluge.torrents.getStore().removeAll())}};Ext.onReady(function(a){deluge.ui.initialize()}); diff --git a/deluge/ui/web/js/deluge-all/ConnectionManager.js b/deluge/ui/web/js/deluge-all/ConnectionManager.js index 5261726..2e61e22 100644 --- a/deluge/ui/web/js/deluge-all/ConnectionManager.js +++ b/deluge/ui/web/js/deluge-all/ConnectionManager.js @@ -162,13 +162,23 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, { }, update: function () { + this.updating = setTimeout(this.update, 2000); this.list.getStore().each(function (r) { deluge.client.web.get_host_status(r.id, { - success: this.onGetHostStatus, + success: this.onUpdate, scope: this, }); }, this); }, + onUpdate: function (host) { + if (!this.isVisible()) return; + this.onGetHostStatus(host); + + if (this.updating) { + clearTimeout(this.updating); + } + this.updating = setTimeout(this.update, 2000); + }, /** * Updates the buttons in the Connection Manager UI according to the @@ -312,7 +322,10 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, { // private onHide: function () { - if (this.running) window.clearInterval(this.running); + if (this.updating) { + window.clearTimeout(this.updating); + this.updating = undefined; + } }, // private @@ -396,8 +409,8 @@ Deluge.ConnectionManager = Ext.extend(Ext.Window, { this.stopHostButton = bbar.items.get('cm-stop'); } this.loadHosts(); - if (this.running) return; - this.running = window.setInterval(this.update, 2000, this); + if (this.updating) return; + this.updating = window.setTimeout(this.update, 2000); }, // private diff --git a/deluge/ui/web/js/deluge-all/Sidebar.js b/deluge/ui/web/js/deluge-all/Sidebar.js index eb08a89..a6512b2 100644 --- a/deluge/ui/web/js/deluge-all/Sidebar.js +++ b/deluge/ui/web/js/deluge-all/Sidebar.js @@ -60,14 +60,16 @@ Deluge.Sidebar = Ext.extend(Ext.Panel, { this.doLayout(); this.panels[filter] = panel; - panel.header.on('click', function (header) { - if (!deluge.config.sidebar_multiple_filters) { - deluge.ui.update(); - } - if (!panel.list.getSelectionCount()) { - panel.list.select(0); - } - }); + if (panel.header) { + panel.header.on('click', function (header) { + if (!deluge.config.sidebar_multiple_filters) { + deluge.ui.update(); + } + if (!panel.list.getSelectionCount()) { + panel.list.select(0); + } + }); + } this.fireEvent('filtercreate', this, panel); panel.updateStates(states); diff --git a/deluge/ui/web/js/deluge-all/UI.js b/deluge/ui/web/js/deluge-all/UI.js index cc877d5..f7edc84 100644 --- a/deluge/ui/web/js/deluge-all/UI.js +++ b/deluge/ui/web/js/deluge-all/UI.js @@ -134,14 +134,24 @@ deluge.ui = { deluge.details.update(); }, - onConnectionError: function (error) {}, + onConnectionError: function (error) { + if (this.checking) { + clearTimeout(this.checking); + } + this.checking = setTimeout(this.checkConnection, 2000); + }, onConnectionSuccess: function (result) { + if (this.checking) { + clearTimeout(this.checking); + this.checking = undefined; + } + this.running = setTimeout(this.update, 2000); + this.update(); deluge.statusbar.setStatus({ iconCls: 'x-deluge-statusbar icon-ok', text: _('Connection restored'), }); - clearInterval(this.checking); if (!result) { deluge.connectionManager.show(); } @@ -159,9 +169,13 @@ deluge.ui = { deluge.statusbar.setStatus({ text: _('Lost connection to webserver'), }); - this.checking = setInterval(this.checkConnection, 2000); + this.checking = setTimeout(this.checkConnection, 2000); } this.errorCount++; + if (this.running) { + clearTimeout(this.running); + this.running = undefined; + } }, /** @@ -170,10 +184,15 @@ deluge.ui = { * Updates the various components in the interface. */ onUpdate: function (data) { + if (this.running) { + clearTimeout(this.running); + this.running = undefined; + } if (!data['connected']) { deluge.connectionManager.disconnect(true); return; } + this.running = setTimeout(this.update, 2000); if (deluge.config.show_session_speed) { document.title = @@ -201,7 +220,7 @@ deluge.ui = { */ onConnect: function () { if (!this.running) { - this.running = setInterval(this.update, 2000); + this.running = setTimeout(this.update, 2000); this.update(); } deluge.client.web.get_plugins({ @@ -280,8 +299,8 @@ deluge.ui = { */ stop: function () { if (this.running) { - clearInterval(this.running); - this.running = false; + clearTimeout(this.running); + this.running = undefined; deluge.torrents.getStore().removeAll(); } }, diff --git a/deluge/ui/web/js/deluge-all/details/FilesTab.js b/deluge/ui/web/js/deluge-all/details/FilesTab.js index 60de832..36ef968 100644 --- a/deluge/ui/web/js/deluge-all/details/FilesTab.js +++ b/deluge/ui/web/js/deluge-all/details/FilesTab.js @@ -214,7 +214,9 @@ Deluge.details.FilesTab = Ext.extend(Ext.ux.tree.TreeGrid, { { success: function () { Ext.each(nodes, function (node) { - node.setColumnValue(3, baseItem.filePriority); + node.attributes.priority = + baseItem.filePriority; + node.ui.updateColumns(); }); }, scope: this, diff --git a/deluge/ui/web/js/deluge-all/details/OptionsTab.js b/deluge/ui/web/js/deluge-all/details/OptionsTab.js index 7e59cba..f8a08be 100644 --- a/deluge/ui/web/js/deluge-all/details/OptionsTab.js +++ b/deluge/ui/web/js/deluge-all/details/OptionsTab.js @@ -86,7 +86,7 @@ Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, { xtype: 'number', decimalPrecision: 1, minValue: -1, - maxValue: 99999, + maxValue: 9999999, }, }); this.fieldsets.bandwidth.add({ @@ -113,7 +113,7 @@ Deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, { xtype: 'number', decimalPrecision: 1, minValue: -1, - maxValue: 99999, + maxValue: 9999999, }, }); this.fieldsets.bandwidth.add({ diff --git a/deluge/ui/web/js/deluge-all/preferences/BandwidthPage.js b/deluge/ui/web/js/deluge-all/preferences/BandwidthPage.js index 8c32da5..563dedd 100644 --- a/deluge/ui/web/js/deluge-all/preferences/BandwidthPage.js +++ b/deluge/ui/web/js/deluge-all/preferences/BandwidthPage.js @@ -40,7 +40,7 @@ Deluge.preferences.Bandwidth = Ext.extend(Ext.form.FormPanel, { defaultType: 'spinnerfield', defaults: { minValue: -1, - maxValue: 99999, + maxValue: 9999999, }, style: 'margin-bottom: 0px; padding-bottom: 0px;', autoHeight: true, diff --git a/deluge/ui/web/js/deluge-all/preferences/DaemonPage.js b/deluge/ui/web/js/deluge-all/preferences/DaemonPage.js index 1787826..da205c2 100644 --- a/deluge/ui/web/js/deluge-all/preferences/DaemonPage.js +++ b/deluge/ui/web/js/deluge-all/preferences/DaemonPage.js @@ -40,7 +40,7 @@ Deluge.preferences.Daemon = Ext.extend(Ext.form.FormPanel, { value: 58846, decimalPrecision: 0, minValue: -1, - maxValue: 99999, + maxValue: 65535, }) ); diff --git a/deluge/ui/web/js/deluge-all/preferences/InterfacePage.js b/deluge/ui/web/js/deluge-all/preferences/InterfacePage.js index b6b76eb..1b710f2 100644 --- a/deluge/ui/web/js/deluge-all/preferences/InterfacePage.js +++ b/deluge/ui/web/js/deluge-all/preferences/InterfacePage.js @@ -140,7 +140,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, { fieldLabel: _('Session Timeout:'), decimalPrecision: 0, minValue: -1, - maxValue: 99999, + maxValue: Number.MAX_SAFE_INTEGER || Number.MAX_VALUE, }) ); om.bind( diff --git a/deluge/ui/web/js/extjs/ext-extensions-debug.js b/deluge/ui/web/js/extjs/ext-extensions-debug.js deleted file mode 100644 index 8a05e61..0000000 --- a/deluge/ui/web/js/extjs/ext-extensions-debug.js +++ /dev/null @@ -1,2927 +0,0 @@ -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -Ext.ns('Ext.ux.form'); - -/** - * @class Ext.ux.form.FileUploadField - * @extends Ext.form.TextField - * Creates a file upload field. - * @xtype fileuploadfield - */ -Ext.ux.form.FileUploadField = Ext.extend(Ext.form.TextField, { - /** - * @cfg {String} buttonText The button text to display on the upload button (defaults to - * 'Browse...'). Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text - * value will be used instead if available. - */ - buttonText: 'Browse...', - /** - * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible - * text field (defaults to false). If true, all inherited TextField members will still be available. - */ - buttonOnly: false, - /** - * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field - * (defaults to 3). Note that this only applies if {@link #buttonOnly} = false. - */ - buttonOffset: 3, - - /** - * @cfg {Boolean} multiple True to select more than one file. (defaults to false). - * Note that this only applies if the HTML doc is using HTML5. - */ - multiple: false, - - /** - * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object. - */ - - // private - readOnly: true, - - /** - * @hide - * @method autoSize - */ - autoSize: Ext.emptyFn, - - // private - initComponent: function () { - Ext.ux.form.FileUploadField.superclass.initComponent.call(this); - - this.addEvents( - /** - * @event fileselected - * Fires when the underlying file input field's value has changed from the user - * selecting a new file from the system file selection dialog. - * @param {Ext.ux.form.FileUploadField} this - * @param {String} value The file value returned by the underlying file input field - */ - 'fileselected' - ); - }, - - // private - onRender: function (ct, position) { - Ext.ux.form.FileUploadField.superclass.onRender.call( - this, - ct, - position - ); - - this.wrap = this.el.wrap({ cls: 'x-form-field-wrap x-form-file-wrap' }); - this.el.addClass('x-form-file-text'); - this.el.dom.removeAttribute('name'); - this.createFileInput(); - - var btnCfg = Ext.applyIf(this.buttonCfg || {}, { - text: this.buttonText, - }); - this.button = new Ext.Button( - Ext.apply(btnCfg, { - renderTo: this.wrap, - cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : ''), - }) - ); - - if (this.buttonOnly) { - this.el.hide(); - this.wrap.setWidth(this.button.getEl().getWidth()); - } - - this.bindListeners(); - this.resizeEl = this.positionEl = this.wrap; - }, - - bindListeners: function () { - this.fileInput.on({ - scope: this, - mouseenter: function () { - this.button.addClass(['x-btn-over', 'x-btn-focus']); - }, - mouseleave: function () { - this.button.removeClass([ - 'x-btn-over', - 'x-btn-focus', - 'x-btn-click', - ]); - }, - mousedown: function () { - this.button.addClass('x-btn-click'); - }, - mouseup: function () { - this.button.removeClass([ - 'x-btn-over', - 'x-btn-focus', - 'x-btn-click', - ]); - }, - change: function () { - var value = this.fileInput.dom.files; - // Fallback to value. - if (!value) value = this.fileInput.dom.value; - this.setValue(value); - this.fireEvent('fileselected', this, value); - }, - }); - }, - - createFileInput: function () { - this.fileInput = this.wrap.createChild({ - id: this.getFileInputId(), - name: this.name || this.getId(), - cls: 'x-form-file', - tag: 'input', - type: 'file', - size: 1, - }); - this.fileInput.dom.multiple = this.multiple; - }, - - reset: function () { - if (this.rendered) { - this.fileInput.remove(); - this.createFileInput(); - this.bindListeners(); - } - Ext.ux.form.FileUploadField.superclass.reset.call(this); - }, - - // private - getFileInputId: function () { - return this.id + '-file'; - }, - - // private - onResize: function (w, h) { - Ext.ux.form.FileUploadField.superclass.onResize.call(this, w, h); - - this.wrap.setWidth(w); - - if (!this.buttonOnly) { - var w = - this.wrap.getWidth() - - this.button.getEl().getWidth() - - this.buttonOffset; - this.el.setWidth(w); - } - }, - - // private - onDestroy: function () { - Ext.ux.form.FileUploadField.superclass.onDestroy.call(this); - Ext.destroy(this.fileInput, this.button, this.wrap); - }, - - onDisable: function () { - Ext.ux.form.FileUploadField.superclass.onDisable.call(this); - this.doDisable(true); - }, - - onEnable: function () { - Ext.ux.form.FileUploadField.superclass.onEnable.call(this); - this.doDisable(false); - }, - - // private - doDisable: function (disabled) { - this.fileInput.dom.disabled = disabled; - this.button.setDisabled(disabled); - }, - - // private - preFocus: Ext.emptyFn, - - // private - alignErrorIcon: function () { - this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]); - }, -}); - -Ext.reg('fileuploadfield', Ext.ux.form.FileUploadField); - -// backwards compat -Ext.form.FileUploadField = Ext.ux.form.FileUploadField; -/** - * Ext.ux.form.RadioGroup.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. - */ - -// Allow radiogroups to be treated as a single form element. -Ext.override(Ext.form.RadioGroup, { - afterRender: function () { - this.items.each(function (i) { - this.relayEvents(i, ['check']); - }, this); - if (this.lazyValue) { - this.setValue(this.value); - delete this.value; - delete this.lazyValue; - } - Ext.form.RadioGroup.superclass.afterRender.call(this); - }, - - getName: function () { - return this.items.first().getName(); - }, - - getValue: function () { - return this.items.first().getGroupValue(); - }, - - setValue: function (v) { - if (!this.items.each) { - this.value = v; - this.lazyValue = true; - return; - } - this.items.each(function (item) { - if (item.rendered) { - var checked = item.el.getValue() == String(v); - item.el.dom.checked = checked; - item.el.dom.defaultChecked = checked; - item.wrap[checked ? 'addClass' : 'removeClass']( - item.checkedCls - ); - } - }); - }, -}); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -Ext.ns('Ext.ux.form'); - -/** - * @class Ext.ux.form.SpinnerField - * @extends Ext.form.NumberField - * Creates a field utilizing Ext.ux.Spinner - * @xtype spinnerfield - */ -Ext.ux.form.SpinnerField = Ext.extend(Ext.form.NumberField, { - actionMode: 'wrap', - deferHeight: true, - autoSize: Ext.emptyFn, - onBlur: Ext.emptyFn, - adjustSize: Ext.BoxComponent.prototype.adjustSize, - - constructor: function (config) { - var spinnerConfig = Ext.copyTo( - {}, - config, - 'incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass' - ); - - var spl = (this.spinner = new Ext.ux.Spinner(spinnerConfig)); - - var plugins = config.plugins - ? Ext.isArray(config.plugins) - ? config.plugins.push(spl) - : [config.plugins, spl] - : spl; - - Ext.ux.form.SpinnerField.superclass.constructor.call( - this, - Ext.apply(config, { plugins: plugins }) - ); - }, - - // private - getResizeEl: function () { - return this.wrap; - }, - - // private - getPositionEl: function () { - return this.wrap; - }, - - // private - alignErrorIcon: function () { - if (this.wrap) { - this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]); - } - }, - - validateBlur: function () { - return true; - }, -}); - -Ext.reg('spinnerfield', Ext.ux.form.SpinnerField); - -//backwards compat -Ext.form.SpinnerField = Ext.ux.form.SpinnerField; -/** - * Ext.ux.form.SpinnerField.js - * - * Copyright (c) Damien Churchill 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. - */ - -Ext.override(Ext.ux.form.SpinnerField, { - onBlur: Ext.form.Field.prototype.onBlur, -}); -/** - * Ext.ux.form.SpinnerGroup.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. - */ -Ext.ns('Ext.ux.form'); - -/** - * - */ -Ext.ux.form.SpinnerGroup = Ext.extend(Ext.form.CheckboxGroup, { - // private - defaultType: 'spinnerfield', - anchor: '98%', - - // private - groupCls: 'x-form-spinner-group', - - colCfg: {}, - - // private - onRender: function (ct, position) { - if (!this.el) { - var panelCfg = { - cls: this.groupCls, - layout: 'column', - border: false, - renderTo: ct, - }; - var colCfg = Ext.apply( - { - defaultType: this.defaultType, - layout: 'form', - border: false, - labelWidth: 60, - defaults: { - hideLabel: true, - anchor: '60%', - }, - }, - this.colCfg - ); - - if (this.items[0].items) { - // The container has standard ColumnLayout configs, so pass them in directly - - Ext.apply(panelCfg, { - layoutConfig: { columns: this.items.length }, - defaults: this.defaults, - items: this.items, - }); - for (var i = 0, len = this.items.length; i < len; i++) { - Ext.applyIf(this.items[i], colCfg); - } - } else { - // The container has field item configs, so we have to generate the column - // panels first then move the items into the columns as needed. - - var numCols, - cols = []; - - if (typeof this.columns == 'string') { - // 'auto' so create a col per item - this.columns = this.items.length; - } - if (!Ext.isArray(this.columns)) { - var cs = []; - for (var i = 0; i < this.columns; i++) { - cs.push((100 / this.columns) * 0.01); // distribute by even % - } - this.columns = cs; - } - - numCols = this.columns.length; - - // Generate the column configs with the correct width setting - for (var i = 0; i < numCols; i++) { - var cc = Ext.apply({ items: [] }, colCfg); - cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = - this.columns[i]; - if (this.defaults) { - cc.defaults = Ext.apply( - cc.defaults || {}, - this.defaults - ); - } - cols.push(cc); - } - - // Distribute the original items into the columns - if (this.vertical) { - var rows = Math.ceil(this.items.length / numCols), - ri = 0; - for (var i = 0, len = this.items.length; i < len; i++) { - if (i > 0 && i % rows == 0) { - ri++; - } - if (this.items[i].fieldLabel) { - this.items[i].hideLabel = false; - } - cols[ri].items.push(this.items[i]); - } - } else { - for (var i = 0, len = this.items.length; i < len; i++) { - var ci = i % numCols; - if (this.items[i].fieldLabel) { - this.items[i].hideLabel = false; - } - cols[ci].items.push(this.items[i]); - } - } - - Ext.apply(panelCfg, { - layoutConfig: { columns: numCols }, - items: cols, - }); - } - - this.panel = new Ext.Panel(panelCfg); - this.el = this.panel.getEl(); - - if (this.forId && this.itemCls) { - var l = this.el.up(this.itemCls).child('label', true); - if (l) { - l.setAttribute('htmlFor', this.forId); - } - } - - var fields = this.panel.findBy(function (c) { - return c.isFormField; - }, this); - - this.items = new Ext.util.MixedCollection(); - this.items.addAll(fields); - - this.items.each(function (field) { - field.on('spin', this.onFieldChange, this); - field.on('change', this.onFieldChange, this); - }, this); - - if (this.lazyValueSet) { - this.setValue(this.value); - delete this.value; - delete this.lazyValueSet; - } - - if (this.lazyRawValueSet) { - this.setRawValue(this.rawValue); - delete this.rawValue; - delete this.lazyRawValueSet; - } - } - - Ext.ux.form.SpinnerGroup.superclass.onRender.call(this, ct, position); - }, - - onFieldChange: function (spinner) { - this.fireEvent('change', this, this.getValue()); - }, - - initValue: Ext.emptyFn, - - getValue: function () { - var value = [this.items.getCount()]; - this.items.each(function (item, i) { - value[i] = Number(item.getValue()); - }); - return value; - }, - - getRawValue: function () { - var value = [this.items.getCount()]; - this.items.each(function (item, i) { - value[i] = Number(item.getRawValue()); - }); - return value; - }, - - setValue: function (value) { - if (!this.rendered) { - this.value = value; - this.lazyValueSet = true; - } else { - this.items.each(function (item, i) { - item.setValue(value[i]); - }); - } - }, - - setRawValue: function (value) { - if (!this.rendered) { - this.rawValue = value; - this.lazyRawValueSet = true; - } else { - this.items.each(function (item, i) { - item.setRawValue(value[i]); - }); - } - }, -}); -Ext.reg('spinnergroup', Ext.ux.form.SpinnerGroup); -/** - * Ext.ux.form.ToggleField.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. - */ -Ext.namespace('Ext.ux.form'); - -/** - * Ext.ux.form.ToggleField class - * - * @author Damien Churchill - * @version v0.1 - * - * @class Ext.ux.form.ToggleField - * @extends Ext.form.TriggerField - */ -Ext.ux.form.ToggleField = Ext.extend(Ext.form.Field, { - cls: 'x-toggle-field', - - initComponent: function () { - Ext.ux.form.ToggleField.superclass.initComponent.call(this); - - this.toggle = new Ext.form.Checkbox(); - this.toggle.on('check', this.onToggleCheck, this); - - this.input = new Ext.form.TextField({ - disabled: true, - }); - }, - - onRender: function (ct, position) { - if (!this.el) { - this.panel = new Ext.Panel({ - cls: this.groupCls, - layout: 'table', - layoutConfig: { - columns: 2, - }, - border: false, - renderTo: ct, - }); - this.panel.ownerCt = this; - this.el = this.panel.getEl(); - - this.panel.add(this.toggle); - this.panel.add(this.input); - this.panel.doLayout(); - - this.toggle.getEl().parent().setStyle('padding-right', '10px'); - } - Ext.ux.form.ToggleField.superclass.onRender.call(this, ct, position); - }, - - // private - onResize: function (w, h) { - this.panel.setSize(w, h); - this.panel.doLayout(); - - // we substract 10 for the padding :-) - var inputWidth = w - this.toggle.getSize().width - 25; - this.input.setSize(inputWidth, h); - }, - - onToggleCheck: function (toggle, checked) { - this.input.setDisabled(!checked); - }, -}); -Ext.reg('togglefield', Ext.ux.form.ToggleField); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -Ext.ns('Ext.ux.grid'); - -/** - * @class Ext.ux.grid.BufferView - * @extends Ext.grid.GridView - * A custom GridView which renders rows on an as-needed basis. - */ -Ext.ux.grid.BufferView = Ext.extend(Ext.grid.GridView, { - /** - * @cfg {Number} rowHeight - * The height of a row in the grid. - */ - rowHeight: 19, - - /** - * @cfg {Number} borderHeight - * The combined height of border-top and border-bottom of a row. - */ - borderHeight: 2, - - /** - * @cfg {Boolean/Number} scrollDelay - * The number of milliseconds before rendering rows out of the visible - * viewing area. Defaults to 100. Rows will render immediately with a config - * of false. - */ - scrollDelay: 100, - - /** - * @cfg {Number} cacheSize - * The number of rows to look forward and backwards from the currently viewable - * area. The cache applies only to rows that have been rendered already. - */ - cacheSize: 20, - - /** - * @cfg {Number} cleanDelay - * The number of milliseconds to buffer cleaning of extra rows not in the - * cache. - */ - cleanDelay: 500, - - initTemplates: function () { - Ext.ux.grid.BufferView.superclass.initTemplates.call(this); - var ts = this.templates; - // empty div to act as a place holder for a row - ts.rowHolder = new Ext.Template( - '<div class="x-grid3-row {alt}" style="{tstyle}"></div>' - ); - ts.rowHolder.disableFormats = true; - ts.rowHolder.compile(); - - ts.rowBody = new Ext.Template( - '<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">', - '<tbody><tr>{cells}</tr>', - this.enableRowBody - ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' - : '', - '</tbody></table>' - ); - ts.rowBody.disableFormats = true; - ts.rowBody.compile(); - }, - - getStyleRowHeight: function () { - return Ext.isBorderBox - ? this.rowHeight + this.borderHeight - : this.rowHeight; - }, - - getCalculatedRowHeight: function () { - return this.rowHeight + this.borderHeight; - }, - - getVisibleRowCount: function () { - var rh = this.getCalculatedRowHeight(), - visibleHeight = this.scroller.dom.clientHeight; - return visibleHeight < 1 ? 0 : Math.ceil(visibleHeight / rh); - }, - - getVisibleRows: function () { - var count = this.getVisibleRowCount(), - sc = this.scroller.dom.scrollTop, - start = - sc === 0 - ? 0 - : Math.floor(sc / this.getCalculatedRowHeight()) - 1; - return { - first: Math.max(start, 0), - last: Math.min(start + count + 2, this.ds.getCount() - 1), - }; - }, - - doRender: function (cs, rs, ds, startRow, colCount, stripe, onlyBody) { - var ts = this.templates, - ct = ts.cell, - rt = ts.row, - rb = ts.rowBody, - last = colCount - 1, - rh = this.getStyleRowHeight(), - vr = this.getVisibleRows(), - tstyle = 'width:' + this.getTotalWidth() + ';height:' + rh + 'px;', - // buffers - buf = [], - cb, - c, - p = {}, - rp = { tstyle: tstyle }, - r; - for (var j = 0, len = rs.length; j < len; j++) { - r = rs[j]; - cb = []; - var rowIndex = j + startRow, - visible = rowIndex >= vr.first && rowIndex <= vr.last; - if (visible) { - for (var i = 0; i < colCount; i++) { - c = cs[i]; - p.id = c.id; - p.css = - i === 0 - ? 'x-grid3-cell-first ' - : i == last - ? 'x-grid3-cell-last ' - : ''; - p.attr = p.cellAttr = ''; - p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds); - p.style = c.style; - if (p.value === undefined || p.value === '') { - p.value = ' '; - } - if (r.dirty && typeof r.modified[c.name] !== 'undefined') { - p.css += ' x-grid3-dirty-cell'; - } - cb[cb.length] = ct.apply(p); - } - } - var alt = []; - if (stripe && (rowIndex + 1) % 2 === 0) { - alt[0] = 'x-grid3-row-alt'; - } - if (r.dirty) { - alt[1] = ' x-grid3-dirty-row'; - } - rp.cols = colCount; - if (this.getRowClass) { - alt[2] = this.getRowClass(r, rowIndex, rp, ds); - } - rp.alt = alt.join(' '); - rp.cells = cb.join(''); - buf[buf.length] = !visible - ? ts.rowHolder.apply(rp) - : onlyBody - ? rb.apply(rp) - : rt.apply(rp); - } - return buf.join(''); - }, - - isRowRendered: function (index) { - var row = this.getRow(index); - return row && row.childNodes.length > 0; - }, - - syncScroll: function () { - Ext.ux.grid.BufferView.superclass.syncScroll.apply(this, arguments); - this.update(); - }, - - // a (optionally) buffered method to update contents of gridview - update: function () { - if (this.scrollDelay) { - if (!this.renderTask) { - this.renderTask = new Ext.util.DelayedTask(this.doUpdate, this); - } - this.renderTask.delay(this.scrollDelay); - } else { - this.doUpdate(); - } - }, - - onRemove: function (ds, record, index, isUpdate) { - Ext.ux.grid.BufferView.superclass.onRemove.apply(this, arguments); - if (isUpdate !== true) { - this.update(); - } - }, - - doUpdate: function () { - if (this.getVisibleRowCount() > 0) { - var g = this.grid, - cm = g.colModel, - ds = g.store, - cs = this.getColumnData(), - vr = this.getVisibleRows(), - row; - for (var i = vr.first; i <= vr.last; i++) { - // if row is NOT rendered and is visible, render it - if (!this.isRowRendered(i) && (row = this.getRow(i))) { - var html = this.doRender( - cs, - [ds.getAt(i)], - ds, - i, - cm.getColumnCount(), - g.stripeRows, - true - ); - row.innerHTML = html; - } - } - this.clean(); - } - }, - - // a buffered method to clean rows - clean: function () { - if (!this.cleanTask) { - this.cleanTask = new Ext.util.DelayedTask(this.doClean, this); - } - this.cleanTask.delay(this.cleanDelay); - }, - - doClean: function () { - if (this.getVisibleRowCount() > 0) { - var vr = this.getVisibleRows(); - vr.first -= this.cacheSize; - vr.last += this.cacheSize; - - var i = 0, - rows = this.getRows(); - // if first is less than 0, all rows have been rendered - // so lets clean the end... - if (vr.first <= 0) { - i = vr.last + 1; - } - for (var len = this.ds.getCount(); i < len; i++) { - // if current row is outside of first and last and - // has content, update the innerHTML to nothing - if ((i < vr.first || i > vr.last) && rows[i].innerHTML) { - rows[i].innerHTML = ''; - } - } - } - }, - - removeTask: function (name) { - var task = this[name]; - if (task && task.cancel) { - task.cancel(); - this[name] = null; - } - }, - - destroy: function () { - this.removeTask('cleanTask'); - this.removeTask('renderTask'); - Ext.ux.grid.BufferView.superclass.destroy.call(this); - }, - - layout: function () { - Ext.ux.grid.BufferView.superclass.layout.call(this); - this.update(); - }, -}); -/** - * Ext.ux.layout.FormLayoutFix.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. - */ - -// Taken from http://extjs.com/forum/showthread.php?t=75273 -// remove spaces for hidden elements and make show(), hide(), enable() and disable() act on -// the label. don't use hideLabel with this. -Ext.override(Ext.layout.FormLayout, { - renderItem: function (c, position, target) { - if ( - c && - !c.rendered && - (c.isFormField || c.fieldLabel) && - c.inputType != 'hidden' - ) { - var args = this.getTemplateArgs(c); - if (typeof position == 'number') { - position = target.dom.childNodes[position] || null; - } - if (position) { - c.formItem = this.fieldTpl.insertBefore(position, args, true); - } else { - c.formItem = this.fieldTpl.append(target, args, true); - } - c.actionMode = 'formItem'; - c.render('x-form-el-' + c.id); - c.container = c.formItem; - c.actionMode = 'container'; - } else { - Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments); - } - }, -}); -/** - * Ext.ux.tree.MultiSelectionModelFix.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. - */ - -/** - * This enhances the MSM to allow for shift selecting in tree grids etc. - * @author Damien Churchill <damoxc@gmail.com> - */ -Ext.override(Ext.tree.MultiSelectionModel, { - onNodeClick: function (node, e) { - if (e.ctrlKey && this.isSelected(node)) { - this.unselect(node); - } else if (e.shiftKey && !this.isSelected(node)) { - var parentNode = node.parentNode; - // We can only shift select files in the same node - if (this.lastSelNode.parentNode.id != parentNode.id) return; - - // Get the node indexes - var fi = parentNode.indexOf(node), - li = parentNode.indexOf(this.lastSelNode); - - // Select the last clicked node and wipe old selections - this.select(this.lastSelNode, e, false, true); - - // Swap the values if required - if (fi > li) { - (fi = fi + li), (li = fi - li), (fi = fi - li); - } - - // Select all the nodes - parentNode.eachChild(function (n) { - var i = parentNode.indexOf(n); - if (fi < i && i < li) { - this.select(n, e, true, true); - } - }, this); - - // Select the clicked node - this.select(node, e, true); - } else { - this.select(node, e, e.ctrlKey); - } - }, - - select: function (node, e, keepExisting, suppressEvent) { - if (keepExisting !== true) { - this.clearSelections(true); - } - if (this.isSelected(node)) { - this.lastSelNode = node; - return node; - } - this.selNodes.push(node); - this.selMap[node.id] = node; - this.lastSelNode = node; - node.ui.onSelectedChange(true); - if (suppressEvent !== true) { - this.fireEvent('selectionchange', this, this.selNodes); - } - return node; - }, -}); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -Ext.ns('Ext.ux.tree'); - -/** - * @class Ext.ux.tree.TreeGrid - * @extends Ext.tree.TreePanel - * - * @xtype treegrid - */ -Ext.ux.tree.TreeGrid = Ext.extend(Ext.tree.TreePanel, { - rootVisible: false, - useArrows: true, - lines: false, - borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell - cls: 'x-treegrid', - - columnResize: true, - enableSort: true, - reserveScrollOffset: true, - enableHdMenu: true, - - columnsText: 'Columns', - - initComponent: function () { - if (!this.root) { - this.root = new Ext.tree.AsyncTreeNode({ text: 'Root' }); - } - - // initialize the loader - var l = this.loader; - if (!l) { - l = new Ext.ux.tree.TreeGridLoader({ - dataUrl: this.dataUrl, - requestMethod: this.requestMethod, - store: this.store, - }); - } else if (Ext.isObject(l) && !l.load) { - l = new Ext.ux.tree.TreeGridLoader(l); - } - this.loader = l; - - Ext.ux.tree.TreeGrid.superclass.initComponent.call(this); - - this.initColumns(); - - if (this.enableSort) { - this.treeGridSorter = new Ext.ux.tree.TreeGridSorter( - this, - this.enableSort - ); - } - - if (this.columnResize) { - this.colResizer = new Ext.tree.ColumnResizer(this.columnResize); - this.colResizer.init(this); - } - - var c = this.columns; - if (!this.internalTpl) { - this.internalTpl = new Ext.XTemplate( - '<div class="x-grid3-header">', - '<div class="x-treegrid-header-inner">', - '<div class="x-grid3-header-offset">', - '<table style="table-layout: fixed;" cellspacing="0" cellpadding="0" border="0"><colgroup><tpl for="columns"><col /></tpl></colgroup>', - '<thead><tr class="x-grid3-hd-row">', - '<tpl for="columns">', - '<td class="x-grid3-hd x-grid3-cell x-treegrid-hd" style="text-align: {align};" id="', - this.id, - '-xlhd-{#}">', - '<div class="x-grid3-hd-inner x-treegrid-hd-inner" unselectable="on">', - this.enableHdMenu - ? '<a class="x-grid3-hd-btn" href="#"></a>' - : '', - '{header}<img class="x-grid3-sort-icon" src="', - Ext.BLANK_IMAGE_URL, - '" />', - '</div>', - '</td></tpl>', - '</tr></thead>', - '</table>', - '</div></div>', - '</div>', - '<div class="x-treegrid-root-node">', - '<table class="x-treegrid-root-table" cellpadding="0" cellspacing="0" style="table-layout: fixed;"></table>', - '</div>' - ); - } - - if (!this.colgroupTpl) { - this.colgroupTpl = new Ext.XTemplate( - '<colgroup><tpl for="columns"><col style="width: {width}px"/></tpl></colgroup>' - ); - } - }, - - initColumns: function () { - var cs = this.columns, - len = cs.length, - columns = [], - i, - c; - - for (i = 0; i < len; i++) { - c = cs[i]; - if (!c.isColumn) { - c.xtype = c.xtype - ? /^tg/.test(c.xtype) - ? c.xtype - : 'tg' + c.xtype - : 'tgcolumn'; - c = Ext.create(c); - } - c.init(this); - columns.push(c); - - if (this.enableSort !== false && c.sortable !== false) { - c.sortable = true; - this.enableSort = true; - } - } - - this.columns = columns; - }, - - onRender: function () { - Ext.tree.TreePanel.superclass.onRender.apply(this, arguments); - - this.el.addClass('x-treegrid'); - - this.outerCt = this.body.createChild({ - cls: - 'x-tree-root-ct x-treegrid-ct ' + - (this.useArrows - ? 'x-tree-arrows' - : this.lines - ? 'x-tree-lines' - : 'x-tree-no-lines'), - }); - - this.internalTpl.overwrite(this.outerCt, { columns: this.columns }); - - this.mainHd = Ext.get(this.outerCt.dom.firstChild); - this.innerHd = Ext.get(this.mainHd.dom.firstChild); - this.innerBody = Ext.get(this.outerCt.dom.lastChild); - this.innerCt = Ext.get(this.innerBody.dom.firstChild); - - this.colgroupTpl.insertFirst(this.innerCt, { columns: this.columns }); - - if (this.hideHeaders) { - this.el.child('.x-grid3-header').setDisplayed('none'); - } else if (this.enableHdMenu !== false) { - this.hmenu = new Ext.menu.Menu({ id: this.id + '-hctx' }); - if (this.enableColumnHide !== false) { - this.colMenu = new Ext.menu.Menu({ - id: this.id + '-hcols-menu', - }); - this.colMenu.on({ - scope: this, - beforeshow: this.beforeColMenuShow, - itemclick: this.handleHdMenuClick, - }); - this.hmenu.add({ - itemId: 'columns', - hideOnClick: false, - text: this.columnsText, - menu: this.colMenu, - iconCls: 'x-cols-icon', - }); - } - this.hmenu.on('itemclick', this.handleHdMenuClick, this); - } - }, - - setRootNode: function (node) { - node.attributes.uiProvider = Ext.ux.tree.TreeGridRootNodeUI; - node = Ext.ux.tree.TreeGrid.superclass.setRootNode.call(this, node); - if (this.innerCt) { - this.colgroupTpl.insertFirst(this.innerCt, { - columns: this.columns, - }); - } - return node; - }, - - clearInnerCt: function () { - if (Ext.isIE) { - var dom = this.innerCt.dom; - while (dom.firstChild) { - dom.removeChild(dom.firstChild); - } - } else { - Ext.ux.tree.TreeGrid.superclass.clearInnerCt.call(this); - } - }, - - initEvents: function () { - Ext.ux.tree.TreeGrid.superclass.initEvents.apply(this, arguments); - - this.mon(this.innerBody, 'scroll', this.syncScroll, this); - this.mon(this.innerHd, 'click', this.handleHdDown, this); - this.mon(this.mainHd, { - scope: this, - mouseover: this.handleHdOver, - mouseout: this.handleHdOut, - }); - }, - - onResize: function (w, h) { - Ext.ux.tree.TreeGrid.superclass.onResize.apply(this, arguments); - - var bd = this.innerBody.dom; - var hd = this.innerHd.dom; - - if (!bd) { - return; - } - - if (Ext.isNumber(h)) { - bd.style.height = - this.body.getHeight(true) - hd.offsetHeight + 'px'; - } - - if (Ext.isNumber(w)) { - var sw = Ext.num(this.scrollOffset, Ext.getScrollBarWidth()); - if ( - this.reserveScrollOffset || - bd.offsetWidth - bd.clientWidth > 10 - ) { - this.setScrollOffset(sw); - } else { - var me = this; - setTimeout(function () { - me.setScrollOffset( - bd.offsetWidth - bd.clientWidth > 10 ? sw : 0 - ); - }, 10); - } - } - }, - - updateColumnWidths: function () { - var cols = this.columns, - colCount = cols.length, - groups = this.outerCt.query('colgroup'), - groupCount = groups.length, - c, - g, - i, - j; - - for (i = 0; i < colCount; i++) { - c = cols[i]; - for (j = 0; j < groupCount; j++) { - g = groups[j]; - g.childNodes[i].style.width = (c.hidden ? 0 : c.width) + 'px'; - } - } - - for ( - i = 0, groups = this.innerHd.query('td'), len = groups.length; - i < len; - i++ - ) { - c = Ext.fly(groups[i]); - if (cols[i] && cols[i].hidden) { - c.addClass('x-treegrid-hd-hidden'); - } else { - c.removeClass('x-treegrid-hd-hidden'); - } - } - - var tcw = this.getTotalColumnWidth(); - Ext.fly(this.innerHd.dom.firstChild).setWidth( - tcw + (this.scrollOffset || 0) - ); - this.outerCt.select('table').setWidth(tcw); - this.syncHeaderScroll(); - }, - - getVisibleColumns: function () { - var columns = [], - cs = this.columns, - len = cs.length, - i; - - for (i = 0; i < len; i++) { - if (!cs[i].hidden) { - columns.push(cs[i]); - } - } - return columns; - }, - - getTotalColumnWidth: function () { - var total = 0; - for ( - var i = 0, cs = this.getVisibleColumns(), len = cs.length; - i < len; - i++ - ) { - total += cs[i].width; - } - return total; - }, - - setScrollOffset: function (scrollOffset) { - this.scrollOffset = scrollOffset; - this.updateColumnWidths(); - }, - - // private - handleHdDown: function (e, t) { - var hd = e.getTarget('.x-treegrid-hd'); - - if (hd && Ext.fly(t).hasClass('x-grid3-hd-btn')) { - var ms = this.hmenu.items, - cs = this.columns, - index = this.findHeaderIndex(hd), - c = cs[index], - sort = c.sortable; - - e.stopEvent(); - Ext.fly(hd).addClass('x-grid3-hd-menu-open'); - this.hdCtxIndex = index; - - this.fireEvent('headerbuttonclick', ms, c, hd, index); - - this.hmenu.on( - 'hide', - function () { - Ext.fly(hd).removeClass('x-grid3-hd-menu-open'); - }, - this, - { single: true } - ); - - this.hmenu.show(t, 'tl-bl?'); - } else if (hd) { - var index = this.findHeaderIndex(hd); - this.fireEvent('headerclick', this.columns[index], hd, index); - } - }, - - // private - handleHdOver: function (e, t) { - var hd = e.getTarget('.x-treegrid-hd'); - if (hd && !this.headersDisabled) { - index = this.findHeaderIndex(hd); - this.activeHdRef = t; - this.activeHdIndex = index; - var el = Ext.get(hd); - this.activeHdRegion = el.getRegion(); - el.addClass('x-grid3-hd-over'); - this.activeHdBtn = el.child('.x-grid3-hd-btn'); - if (this.activeHdBtn) { - this.activeHdBtn.dom.style.height = - hd.firstChild.offsetHeight - 1 + 'px'; - } - } - }, - - // private - handleHdOut: function (e, t) { - var hd = e.getTarget('.x-treegrid-hd'); - if (hd && (!Ext.isIE || !e.within(hd, true))) { - this.activeHdRef = null; - Ext.fly(hd).removeClass('x-grid3-hd-over'); - hd.style.cursor = ''; - } - }, - - findHeaderIndex: function (hd) { - hd = hd.dom || hd; - var cs = hd.parentNode.childNodes; - for (var i = 0, c; (c = cs[i]); i++) { - if (c == hd) { - return i; - } - } - return -1; - }, - - // private - beforeColMenuShow: function () { - var cols = this.columns, - colCount = cols.length, - i, - c; - this.colMenu.removeAll(); - for (i = 1; i < colCount; i++) { - c = cols[i]; - if (c.hideable !== false) { - this.colMenu.add( - new Ext.menu.CheckItem({ - itemId: 'col-' + i, - text: c.header, - checked: !c.hidden, - hideOnClick: false, - disabled: c.hideable === false, - }) - ); - } - } - }, - - // private - handleHdMenuClick: function (item) { - var index = this.hdCtxIndex, - id = item.getItemId(); - - if ( - this.fireEvent( - 'headermenuclick', - this.columns[index], - id, - index - ) !== false - ) { - index = id.substr(4); - if (index > 0 && this.columns[index]) { - this.setColumnVisible(index, !item.checked); - } - } - - return true; - }, - - setColumnVisible: function (index, visible) { - this.columns[index].hidden = !visible; - this.updateColumnWidths(); - }, - - /** - * Scrolls the grid to the top - */ - scrollToTop: function () { - this.innerBody.dom.scrollTop = 0; - this.innerBody.dom.scrollLeft = 0; - }, - - // private - syncScroll: function () { - this.syncHeaderScroll(); - var mb = this.innerBody.dom; - this.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop); - }, - - // private - syncHeaderScroll: function () { - var mb = this.innerBody.dom; - this.innerHd.dom.scrollLeft = mb.scrollLeft; - this.innerHd.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore) - }, - - registerNode: function (n) { - Ext.ux.tree.TreeGrid.superclass.registerNode.call(this, n); - if (!n.uiProvider && !n.isRoot && !n.ui.isTreeGridNodeUI) { - n.ui = new Ext.ux.tree.TreeGridNodeUI(n); - } - }, -}); - -Ext.reg('treegrid', Ext.ux.tree.TreeGrid); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -/** - * @class Ext.tree.ColumnResizer - * @extends Ext.util.Observable - */ -Ext.tree.ColumnResizer = Ext.extend(Ext.util.Observable, { - /** - * @cfg {Number} minWidth The minimum width the column can be dragged to. - * Defaults to <tt>14</tt>. - */ - minWidth: 14, - - constructor: function (config) { - Ext.apply(this, config); - Ext.tree.ColumnResizer.superclass.constructor.call(this); - }, - - init: function (tree) { - this.tree = tree; - tree.on('render', this.initEvents, this); - }, - - initEvents: function (tree) { - tree.mon(tree.innerHd, 'mousemove', this.handleHdMove, this); - this.tracker = new Ext.dd.DragTracker({ - onBeforeStart: this.onBeforeStart.createDelegate(this), - onStart: this.onStart.createDelegate(this), - onDrag: this.onDrag.createDelegate(this), - onEnd: this.onEnd.createDelegate(this), - tolerance: 3, - autoStart: 300, - }); - this.tracker.initEl(tree.innerHd); - tree.on('beforedestroy', this.tracker.destroy, this.tracker); - }, - - handleHdMove: function (e, t) { - var hw = 5, - x = e.getPageX(), - hd = e.getTarget('.x-treegrid-hd', 3, true); - - if (hd) { - var r = hd.getRegion(), - ss = hd.dom.style, - pn = hd.dom.parentNode; - - if (x - r.left <= hw && hd.dom !== pn.firstChild) { - var ps = hd.dom.previousSibling; - while (ps && Ext.fly(ps).hasClass('x-treegrid-hd-hidden')) { - ps = ps.previousSibling; - } - if (ps) { - this.activeHd = Ext.get(ps); - ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize'; - } - } else if (r.right - x <= hw) { - var ns = hd.dom; - while (ns && Ext.fly(ns).hasClass('x-treegrid-hd-hidden')) { - ns = ns.previousSibling; - } - if (ns) { - this.activeHd = Ext.get(ns); - ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize'; - } - } else { - delete this.activeHd; - ss.cursor = ''; - } - } - }, - - onBeforeStart: function (e) { - this.dragHd = this.activeHd; - return !!this.dragHd; - }, - - onStart: function (e) { - this.dragHeadersDisabled = this.tree.headersDisabled; - this.tree.headersDisabled = true; - this.proxy = this.tree.body.createChild({ cls: 'x-treegrid-resizer' }); - this.proxy.setHeight(this.tree.body.getHeight()); - - var x = this.tracker.getXY()[0]; - - this.hdX = this.dragHd.getX(); - this.hdIndex = this.tree.findHeaderIndex(this.dragHd); - - this.proxy.setX(this.hdX); - this.proxy.setWidth(x - this.hdX); - - this.maxWidth = - this.tree.outerCt.getWidth() - - this.tree.innerBody.translatePoints(this.hdX).left; - }, - - onDrag: function (e) { - var cursorX = this.tracker.getXY()[0]; - this.proxy.setWidth( - (cursorX - this.hdX).constrain(this.minWidth, this.maxWidth) - ); - }, - - onEnd: function (e) { - var nw = this.proxy.getWidth(), - tree = this.tree, - disabled = this.dragHeadersDisabled; - - this.proxy.remove(); - delete this.dragHd; - - tree.columns[this.hdIndex].width = nw; - tree.updateColumnWidths(); - - setTimeout(function () { - tree.headersDisabled = disabled; - }, 100); - }, -}); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -(function () { - Ext.override(Ext.list.Column, { - init: function () { - var types = Ext.data.Types, - st = this.sortType; - - if (this.type) { - if (Ext.isString(this.type)) { - this.type = - Ext.data.Types[this.type.toUpperCase()] || types.AUTO; - } - } else { - this.type = types.AUTO; - } - - // named sortTypes are supported, here we look them up - if (Ext.isString(st)) { - this.sortType = Ext.data.SortTypes[st]; - } else if (Ext.isEmpty(st)) { - this.sortType = this.type.sortType; - } - }, - }); - - Ext.tree.Column = Ext.extend(Ext.list.Column, {}); - Ext.tree.NumberColumn = Ext.extend(Ext.list.NumberColumn, {}); - Ext.tree.DateColumn = Ext.extend(Ext.list.DateColumn, {}); - Ext.tree.BooleanColumn = Ext.extend(Ext.list.BooleanColumn, {}); - - Ext.reg('tgcolumn', Ext.tree.Column); - Ext.reg('tgnumbercolumn', Ext.tree.NumberColumn); - Ext.reg('tgdatecolumn', Ext.tree.DateColumn); - Ext.reg('tgbooleancolumn', Ext.tree.BooleanColumn); -})(); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -/** - * @class Ext.ux.tree.TreeGridLoader - * @extends Ext.tree.TreeLoader - */ -Ext.ux.tree.TreeGridLoader = Ext.extend(Ext.tree.TreeLoader, { - createNode: function (attr) { - if (!attr.uiProvider) { - attr.uiProvider = Ext.ux.tree.TreeGridNodeUI; - } - return Ext.tree.TreeLoader.prototype.createNode.call(this, attr); - }, -}); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -/** - * @class Ext.ux.tree.TreeGridNodeUI - * @extends Ext.tree.TreeNodeUI - */ -Ext.ux.tree.TreeGridNodeUI = Ext.extend(Ext.tree.TreeNodeUI, { - isTreeGridNodeUI: true, - - renderElements: function (n, a, targetNode, bulkRender) { - var t = n.getOwnerTree(), - cols = t.columns, - c = cols[0], - i, - buf, - len; - - this.indentMarkup = n.parentNode - ? n.parentNode.ui.getChildIndent() - : ''; - - buf = [ - '<tbody class="x-tree-node">', - '<tr ext:tree-node-id="', - n.id, - '" class="x-tree-node-el x-tree-node-leaf ', - a.cls, - '">', - '<td class="x-treegrid-col">', - '<span class="x-tree-node-indent">', - this.indentMarkup, - '</span>', - '<img src="', - this.emptyIcon, - '" class="x-tree-ec-icon x-tree-elbow" />', - '<img src="', - a.icon || this.emptyIcon, - '" class="x-tree-node-icon', - a.icon ? ' x-tree-node-inline-icon' : '', - a.iconCls ? ' ' + a.iconCls : '', - '" unselectable="on" />', - '<a hidefocus="on" class="x-tree-node-anchor" href="', - a.href ? a.href : '#', - '" tabIndex="1" ', - a.hrefTarget ? ' target="' + a.hrefTarget + '"' : '', - '>', - '<span unselectable="on">', - c.tpl ? c.tpl.apply(a) : a[c.dataIndex] || c.text, - '</span></a>', - '</td>', - ]; - - for (i = 1, len = cols.length; i < len; i++) { - c = cols[i]; - buf.push( - '<td class="x-treegrid-col ', - c.cls ? c.cls : '', - '">', - '<div unselectable="on" class="x-treegrid-text"', - c.align ? ' style="text-align: ' + c.align + ';"' : '', - '>', - c.tpl ? c.tpl.apply(a) : a[c.dataIndex], - '</div>', - '</td>' - ); - } - - buf.push( - '</tr><tr class="x-tree-node-ct"><td colspan="', - cols.length, - '">', - '<table class="x-treegrid-node-ct-table" cellpadding="0" cellspacing="0" style="table-layout: fixed; display: none; width: ', - t.innerCt.getWidth(), - 'px;"><colgroup>' - ); - for (i = 0, len = cols.length; i < len; i++) { - buf.push( - '<col style="width: ', - cols[i].hidden ? 0 : cols[i].width, - 'px;" />' - ); - } - buf.push('</colgroup></table></td></tr></tbody>'); - - if (bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()) { - this.wrap = Ext.DomHelper.insertHtml( - 'beforeBegin', - n.nextSibling.ui.getEl(), - buf.join('') - ); - } else { - this.wrap = Ext.DomHelper.insertHtml( - 'beforeEnd', - targetNode, - buf.join('') - ); - } - - this.elNode = this.wrap.childNodes[0]; - this.ctNode = this.wrap.childNodes[1].firstChild.firstChild; - var cs = this.elNode.firstChild.childNodes; - this.indentNode = cs[0]; - this.ecNode = cs[1]; - this.iconNode = cs[2]; - this.anchor = cs[3]; - this.textNode = cs[3].firstChild; - }, - - // private - animExpand: function (cb) { - this.ctNode.style.display = ''; - Ext.ux.tree.TreeGridNodeUI.superclass.animExpand.call(this, cb); - }, -}); - -Ext.ux.tree.TreeGridRootNodeUI = Ext.extend(Ext.tree.TreeNodeUI, { - isTreeGridNodeUI: true, - - // private - render: function () { - if (!this.rendered) { - this.wrap = this.ctNode = this.node.ownerTree.innerCt.dom; - this.node.expanded = true; - } - - if (Ext.isWebKit) { - // weird table-layout: fixed issue in webkit - var ct = this.ctNode; - ct.style.tableLayout = null; - (function () { - ct.style.tableLayout = 'fixed'; - }.defer(1)); - } - }, - - destroy: function () { - if (this.elNode) { - Ext.dd.Registry.unregister(this.elNode.id); - } - delete this.node; - }, - - collapse: Ext.emptyFn, - expand: Ext.emptyFn, -}); -/** - * Ext.ux.tree.TreeGridNodeUIFix.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. - */ - -Ext.override(Ext.ux.tree.TreeGridNodeUI, { - updateColumns: function () { - if (!this.rendered) return; - - var a = this.node.attributes, - t = this.node.getOwnerTree(), - cols = t.columns, - c = cols[0]; - - // Update the first column - this.anchor.firstChild.innerHTML = c.tpl - ? c.tpl.apply(a) - : a[c.dataIndex] || c.text; - - // Update the remaining columns - for (i = 1, len = cols.length; i < len; i++) { - c = cols[i]; - this.elNode.childNodes[i].firstChild.innerHTML = c.tpl - ? c.tpl.apply(a) - : a[c.dataIndex] || c.text; - } - }, -}); -Ext.tree.RenderColumn = Ext.extend(Ext.tree.Column, { - constructor: function (c) { - c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}'); - c.tpl.format = c.renderer; - c.tpl.col = this; - Ext.tree.RenderColumn.superclass.constructor.call(this, c); - }, -}); -Ext.reg('tgrendercolumn', Ext.tree.RenderColumn); -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -Ext.ns('Ext.ux.tree'); - -/** - * @class Ext.ux.tree.TreeGridSorter - * @extends Ext.tree.TreeSorter - * Provides sorting of nodes in a {@link Ext.ux.tree.TreeGrid}. The TreeGridSorter automatically monitors events on the - * associated TreeGrid that might affect the tree's sort order (beforechildrenrendered, append, insert and textchange). - * Example usage:<br /> - * <pre><code> - new Ext.ux.tree.TreeGridSorter(myTreeGrid, { - folderSort: true, - dir: "desc", - sortType: function(node) { - // sort by a custom, typed attribute: - return parseInt(node.id, 10); - } - }); - </code></pre> - * @constructor - * @param {TreeGrid} tree - * @param {Object} config - */ -Ext.ux.tree.TreeGridSorter = Ext.extend(Ext.tree.TreeSorter, { - /** - * @cfg {Array} sortClasses The CSS classes applied to a header when it is sorted. (defaults to <tt>['sort-asc', 'sort-desc']</tt>) - */ - sortClasses: ['sort-asc', 'sort-desc'], - /** - * @cfg {String} sortAscText The text displayed in the 'Sort Ascending' menu item (defaults to <tt>'Sort Ascending'</tt>) - */ - sortAscText: 'Sort Ascending', - /** - * @cfg {String} sortDescText The text displayed in the 'Sort Descending' menu item (defaults to <tt>'Sort Descending'</tt>) - */ - sortDescText: 'Sort Descending', - - constructor: function (tree, config) { - if (!Ext.isObject(config)) { - config = { - property: tree.columns[0].dataIndex || 'text', - folderSort: true, - }; - } - - Ext.ux.tree.TreeGridSorter.superclass.constructor.apply( - this, - arguments - ); - - this.tree = tree; - tree.on('headerclick', this.onHeaderClick, this); - tree.ddAppendOnly = true; - - var me = this; - this.defaultSortFn = function (n1, n2) { - var desc = me.dir && me.dir.toLowerCase() == 'desc', - prop = me.property || 'text', - sortType = me.sortType, - caseSensitive = me.caseSensitive === true, - leafAttr = me.leafAttr || 'leaf', - attr1 = n1.attributes, - attr2 = n2.attributes; - - if (me.folderSort) { - if (attr1[leafAttr] && !attr2[leafAttr]) { - return 1; - } - if (!attr1[leafAttr] && attr2[leafAttr]) { - return -1; - } - } - var prop1 = attr1[prop], - prop2 = attr2[prop], - v1 = sortType - ? sortType(prop1) - : caseSensitive - ? prop1 - : prop1.toUpperCase(); - v2 = sortType - ? sortType(prop2) - : caseSensitive - ? prop2 - : prop2.toUpperCase(); - - if (v1 < v2) { - return desc ? +1 : -1; - } else if (v1 > v2) { - return desc ? -1 : +1; - } else { - return 0; - } - }; - - tree.on('afterrender', this.onAfterTreeRender, this, { single: true }); - tree.on('headermenuclick', this.onHeaderMenuClick, this); - }, - - onAfterTreeRender: function () { - if (this.tree.hmenu) { - this.tree.hmenu.insert( - 0, - { - itemId: 'asc', - text: this.sortAscText, - cls: 'xg-hmenu-sort-asc', - }, - { - itemId: 'desc', - text: this.sortDescText, - cls: 'xg-hmenu-sort-desc', - } - ); - } - this.updateSortIcon(0, 'asc'); - }, - - onHeaderMenuClick: function (c, id, index) { - if (id === 'asc' || id === 'desc') { - this.onHeaderClick(c, null, index); - return false; - } - }, - - onHeaderClick: function (c, el, i) { - if (c && !this.tree.headersDisabled) { - var me = this; - - me.property = c.dataIndex; - me.dir = c.dir = c.dir === 'desc' ? 'asc' : 'desc'; - me.sortType = c.sortType; - me.caseSensitive === Ext.isBoolean(c.caseSensitive) - ? c.caseSensitive - : this.caseSensitive; - me.sortFn = c.sortFn || this.defaultSortFn; - - this.tree.root.cascade(function (n) { - if (!n.isLeaf()) { - me.updateSort(me.tree, n); - } - }); - - this.updateSortIcon(i, c.dir); - } - }, - - // private - updateSortIcon: function (col, dir) { - var sc = this.sortClasses, - hds = this.tree.innerHd.select('td').removeClass(sc); - hds.item(col).addClass(sc[dir == 'desc' ? 1 : 0]); - }, -}); -Ext.ux.JSLoader = function (options) { - Ext.ux.JSLoader.scripts[++Ext.ux.JSLoader.index] = { - url: options.url, - success: true, - jsLoadObj: null, - options: options, - onLoad: options.onLoad || Ext.emptyFn, - onError: options.onError || Ext.ux.JSLoader.stdError, - scope: options.scope || this, - }; - - Ext.Ajax.request({ - url: options.url, - scriptIndex: Ext.ux.JSLoader.index, - success: function (response, options) { - var script = Ext.ux.JSLoader.scripts[options.scriptIndex]; - try { - eval(response.responseText); - } catch (e) { - script.success = false; - script.onError(script.options, e); - } - if (script.success) { - script.onLoad.call(script.scope, script.options); - } - }, - failure: function (response, options) { - var script = Ext.ux.JSLoader.scripts[options.scriptIndex]; - script.success = false; - script.onError(script.options, response.status); - }, - }); -}; -Ext.ux.JSLoader.index = 0; -Ext.ux.JSLoader.scripts = []; -Ext.ux.JSLoader.stdError = function (options, e) { - window.alert( - 'Error loading script:\n\n' + options.url + '\n\nstatus: ' + e - ); -}; -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -/** - * @class Ext.ux.Spinner - * @extends Ext.util.Observable - * Creates a Spinner control utilized by Ext.ux.form.SpinnerField - */ -Ext.ux.Spinner = Ext.extend(Ext.util.Observable, { - incrementValue: 1, - alternateIncrementValue: 5, - triggerClass: 'x-form-spinner-trigger', - splitterClass: 'x-form-spinner-splitter', - alternateKey: Ext.EventObject.shiftKey, - defaultValue: 0, - accelerate: false, - - constructor: function (config) { - Ext.ux.Spinner.superclass.constructor.call(this, config); - Ext.apply(this, config); - this.mimicing = false; - }, - - init: function (field) { - this.field = field; - - field.afterMethod('onRender', this.doRender, this); - field.afterMethod('onEnable', this.doEnable, this); - field.afterMethod('onDisable', this.doDisable, this); - field.afterMethod('afterRender', this.doAfterRender, this); - field.afterMethod('onResize', this.doResize, this); - field.afterMethod('onFocus', this.doFocus, this); - field.beforeMethod('onDestroy', this.doDestroy, this); - }, - - doRender: function (ct, position) { - var el = (this.el = this.field.getEl()); - var f = this.field; - - if (!f.wrap) { - f.wrap = this.wrap = el.wrap({ - cls: 'x-form-field-wrap', - }); - } else { - this.wrap = f.wrap.addClass('x-form-field-wrap'); - } - - this.trigger = this.wrap.createChild({ - tag: 'img', - src: Ext.BLANK_IMAGE_URL, - cls: 'x-form-trigger ' + this.triggerClass, - }); - - if (!f.width) { - this.wrap.setWidth(el.getWidth() + this.trigger.getWidth()); - } - - this.splitter = this.wrap.createChild({ - tag: 'div', - cls: this.splitterClass, - style: 'width:13px; height:2px;', - }); - this.splitter - .setRight(Ext.isIE ? 1 : 2) - .setTop(10) - .show(); - - this.proxy = this.trigger.createProxy('', this.splitter, true); - this.proxy.addClass('x-form-spinner-proxy'); - this.proxy.setStyle('left', '0px'); - this.proxy.setSize(14, 1); - this.proxy.hide(); - this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, 'SpinnerDrag', { - dragElId: this.proxy.id, - }); - - this.initTrigger(); - this.initSpinner(); - }, - - doAfterRender: function () { - var y; - if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) { - this.el.position(); - this.el.setY(y); - } - }, - - doEnable: function () { - if (this.wrap) { - this.disabled = false; - this.wrap.removeClass(this.field.disabledClass); - } - }, - - doDisable: function () { - if (this.wrap) { - this.disabled = true; - this.wrap.addClass(this.field.disabledClass); - this.el.removeClass(this.field.disabledClass); - } - }, - - doResize: function (w, h) { - if (typeof w == 'number') { - this.el.setWidth(w - this.trigger.getWidth()); - } - this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth()); - }, - - doFocus: function () { - if (!this.mimicing) { - this.wrap.addClass('x-trigger-wrap-focus'); - this.mimicing = true; - Ext.get(Ext.isIE ? document.body : document).on( - 'mousedown', - this.mimicBlur, - this, - { - delay: 10, - } - ); - this.el.on('keydown', this.checkTab, this); - } - }, - - // private - checkTab: function (e) { - if (e.getKey() == e.TAB) { - this.triggerBlur(); - } - }, - - // private - mimicBlur: function (e) { - if (!this.wrap.contains(e.target) && this.field.validateBlur(e)) { - this.triggerBlur(); - } - }, - - // private - triggerBlur: function () { - this.mimicing = false; - Ext.get(Ext.isIE ? document.body : document).un( - 'mousedown', - this.mimicBlur, - this - ); - this.el.un('keydown', this.checkTab, this); - this.field.beforeBlur(); - this.wrap.removeClass('x-trigger-wrap-focus'); - this.field.onBlur.call(this.field); - }, - - initTrigger: function () { - this.trigger.addClassOnOver('x-form-trigger-over'); - this.trigger.addClassOnClick('x-form-trigger-click'); - }, - - initSpinner: function () { - this.field.addEvents({ - spin: true, - spinup: true, - spindown: true, - }); - - this.keyNav = new Ext.KeyNav(this.el, { - up: function (e) { - e.preventDefault(); - this.onSpinUp(); - }, - - down: function (e) { - e.preventDefault(); - this.onSpinDown(); - }, - - pageUp: function (e) { - e.preventDefault(); - this.onSpinUpAlternate(); - }, - - pageDown: function (e) { - e.preventDefault(); - this.onSpinDownAlternate(); - }, - - scope: this, - }); - - this.repeater = new Ext.util.ClickRepeater(this.trigger, { - accelerate: this.accelerate, - }); - this.field.mon(this.repeater, 'click', this.onTriggerClick, this, { - preventDefault: true, - }); - - this.field.mon(this.trigger, { - mouseover: this.onMouseOver, - mouseout: this.onMouseOut, - mousemove: this.onMouseMove, - mousedown: this.onMouseDown, - mouseup: this.onMouseUp, - scope: this, - preventDefault: true, - }); - - this.field.mon(this.wrap, 'mousewheel', this.handleMouseWheel, this); - - this.dd.setXConstraint(0, 0, 10); - this.dd.setYConstraint(1500, 1500, 10); - this.dd.endDrag = this.endDrag.createDelegate(this); - this.dd.startDrag = this.startDrag.createDelegate(this); - this.dd.onDrag = this.onDrag.createDelegate(this); - }, - - onMouseOver: function () { - if (this.disabled) { - return; - } - var middle = this.getMiddle(); - this.tmpHoverClass = - Ext.EventObject.getPageY() < middle - ? 'x-form-spinner-overup' - : 'x-form-spinner-overdown'; - this.trigger.addClass(this.tmpHoverClass); - }, - - //private - onMouseOut: function () { - this.trigger.removeClass(this.tmpHoverClass); - }, - - //private - onMouseMove: function () { - if (this.disabled) { - return; - } - var middle = this.getMiddle(); - if ( - (Ext.EventObject.getPageY() > middle && - this.tmpHoverClass == 'x-form-spinner-overup') || - (Ext.EventObject.getPageY() < middle && - this.tmpHoverClass == 'x-form-spinner-overdown') - ) { - } - }, - - //private - onMouseDown: function () { - if (this.disabled) { - return; - } - var middle = this.getMiddle(); - this.tmpClickClass = - Ext.EventObject.getPageY() < middle - ? 'x-form-spinner-clickup' - : 'x-form-spinner-clickdown'; - this.trigger.addClass(this.tmpClickClass); - }, - - //private - onMouseUp: function () { - this.trigger.removeClass(this.tmpClickClass); - }, - - //private - onTriggerClick: function () { - if (this.disabled || this.el.dom.readOnly) { - return; - } - var middle = this.getMiddle(); - var ud = Ext.EventObject.getPageY() < middle ? 'Up' : 'Down'; - this['onSpin' + ud](); - }, - - //private - getMiddle: function () { - var t = this.trigger.getTop(); - var h = this.trigger.getHeight(); - var middle = t + h / 2; - return middle; - }, - - //private - //checks if control is allowed to spin - isSpinnable: function () { - if (this.disabled || this.el.dom.readOnly) { - Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly - return false; - } - return true; - }, - - handleMouseWheel: function (e) { - //disable scrolling when not focused - if (this.wrap.hasClass('x-trigger-wrap-focus') == false) { - return; - } - - var delta = e.getWheelDelta(); - if (delta > 0) { - this.onSpinUp(); - e.stopEvent(); - } else if (delta < 0) { - this.onSpinDown(); - e.stopEvent(); - } - }, - - //private - startDrag: function () { - this.proxy.show(); - this._previousY = Ext.fly(this.dd.getDragEl()).getTop(); - }, - - //private - endDrag: function () { - this.proxy.hide(); - }, - - //private - onDrag: function () { - if (this.disabled) { - return; - } - var y = Ext.fly(this.dd.getDragEl()).getTop(); - var ud = ''; - - if (this._previousY > y) { - ud = 'Up'; - } //up - if (this._previousY < y) { - ud = 'Down'; - } //down - if (ud != '') { - this['onSpin' + ud](); - } - - this._previousY = y; - }, - - //private - onSpinUp: function () { - if (this.isSpinnable() == false) { - return; - } - if (Ext.EventObject.shiftKey == true) { - this.onSpinUpAlternate(); - return; - } else { - this.spin(false, false); - } - this.field.fireEvent('spin', this); - this.field.fireEvent('spinup', this); - }, - - //private - onSpinDown: function () { - if (this.isSpinnable() == false) { - return; - } - if (Ext.EventObject.shiftKey == true) { - this.onSpinDownAlternate(); - return; - } else { - this.spin(true, false); - } - this.field.fireEvent('spin', this); - this.field.fireEvent('spindown', this); - }, - - //private - onSpinUpAlternate: function () { - if (this.isSpinnable() == false) { - return; - } - this.spin(false, true); - this.field.fireEvent('spin', this); - this.field.fireEvent('spinup', this); - }, - - //private - onSpinDownAlternate: function () { - if (this.isSpinnable() == false) { - return; - } - this.spin(true, true); - this.field.fireEvent('spin', this); - this.field.fireEvent('spindown', this); - }, - - spin: function (down, alternate) { - var v = parseFloat(this.field.getValue()); - var incr = - alternate == true - ? this.alternateIncrementValue - : this.incrementValue; - down == true ? (v -= incr) : (v += incr); - - v = isNaN(v) ? this.defaultValue : v; - v = this.fixBoundries(v); - this.field.setRawValue(v); - }, - - fixBoundries: function (value) { - var v = value; - - if (this.field.minValue != undefined && v < this.field.minValue) { - v = this.field.minValue; - } - if (this.field.maxValue != undefined && v > this.field.maxValue) { - v = this.field.maxValue; - } - - return this.fixPrecision(v); - }, - - // private - fixPrecision: function (value) { - var nan = isNaN(value); - if ( - !this.field.allowDecimals || - this.field.decimalPrecision == -1 || - nan || - !value - ) { - return nan ? '' : value; - } - return parseFloat( - parseFloat(value).toFixed(this.field.decimalPrecision) - ); - }, - - doDestroy: function () { - if (this.trigger) { - this.trigger.remove(); - } - if (this.wrap) { - this.wrap.remove(); - delete this.field.wrap; - } - - if (this.splitter) { - this.splitter.remove(); - } - - if (this.dd) { - this.dd.unreg(); - this.dd = null; - } - - if (this.proxy) { - this.proxy.remove(); - } - - if (this.repeater) { - this.repeater.purgeListeners(); - } - if (this.mimicing) { - Ext.get(Ext.isIE ? document.body : document).un( - 'mousedown', - this.mimicBlur, - this - ); - } - }, -}); - -//backwards compat -Ext.form.Spinner = Ext.ux.Spinner; -/** - * Ext JS Library 3.4.0 - * Copyright(c) 2006-2011 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -/** - * @class Ext.ux.StatusBar - * <p>Basic status bar component that can be used as the bottom toolbar of any {@link Ext.Panel}. In addition to - * supporting the standard {@link Ext.Toolbar} interface for adding buttons, menus and other items, the StatusBar - * provides a greedy status element that can be aligned to either side and has convenient methods for setting the - * status text and icon. You can also indicate that something is processing using the {@link #showBusy} method.</p> - * <pre><code> -new Ext.Panel({ - title: 'StatusBar', - // etc. - bbar: new Ext.ux.StatusBar({ - id: 'my-status', - - // defaults to use when the status is cleared: - defaultText: 'Default status text', - defaultIconCls: 'default-icon', - - // values to set initially: - text: 'Ready', - iconCls: 'ready-icon', - - // any standard Toolbar items: - items: [{ - text: 'A Button' - }, '-', 'Plain Text'] - }) -}); - -// Update the status bar later in code: -var sb = Ext.getCmp('my-status'); -sb.setStatus({ - text: 'OK', - iconCls: 'ok-icon', - clear: true // auto-clear after a set interval -}); - -// Set the status bar to show that something is processing: -sb.showBusy(); - -// processing.... - -sb.clearStatus(); // once completeed -</code></pre> - * @extends Ext.Toolbar - * @constructor - * Creates a new StatusBar - * @param {Object/Array} config A config object - */ -Ext.ux.StatusBar = Ext.extend(Ext.Toolbar, { - /** - * @cfg {String} statusAlign - * The alignment of the status element within the overall StatusBar layout. When the StatusBar is rendered, - * it creates an internal div containing the status text and icon. Any additional Toolbar items added in the - * StatusBar's {@link #items} config, or added via {@link #add} or any of the supported add* methods, will be - * rendered, in added order, to the opposite side. The status element is greedy, so it will automatically - * expand to take up all sapce left over by any other items. Example usage: - * <pre><code> -// Create a left-aligned status bar containing a button, -// separator and text item that will be right-aligned (default): -new Ext.Panel({ - title: 'StatusBar', - // etc. - bbar: new Ext.ux.StatusBar({ - defaultText: 'Default status text', - id: 'status-id', - items: [{ - text: 'A Button' - }, '-', 'Plain Text'] - }) -}); - -// By adding the statusAlign config, this will create the -// exact same toolbar, except the status and toolbar item -// layout will be reversed from the previous example: -new Ext.Panel({ - title: 'StatusBar', - // etc. - bbar: new Ext.ux.StatusBar({ - defaultText: 'Default status text', - id: 'status-id', - statusAlign: 'right', - items: [{ - text: 'A Button' - }, '-', 'Plain Text'] - }) -}); -</code></pre> - */ - /** - * @cfg {String} defaultText - * The default {@link #text} value. This will be used anytime the status bar is cleared with the - * <tt>useDefaults:true</tt> option (defaults to ''). - */ - /** - * @cfg {String} defaultIconCls - * The default {@link #iconCls} value (see the iconCls docs for additional details about customizing the icon). - * This will be used anytime the status bar is cleared with the <tt>useDefaults:true</tt> option (defaults to ''). - */ - /** - * @cfg {String} text - * A string that will be <b>initially</b> set as the status message. This string - * will be set as innerHTML (html tags are accepted) for the toolbar item. - * If not specified, the value set for <code>{@link #defaultText}</code> - * will be used. - */ - /** - * @cfg {String} iconCls - * A CSS class that will be <b>initially</b> set as the status bar icon and is - * expected to provide a background image (defaults to ''). - * Example usage:<pre><code> -// Example CSS rule: -.x-statusbar .x-status-custom { - padding-left: 25px; - background: transparent url(images/custom-icon.gif) no-repeat 3px 2px; -} - -// Setting a default icon: -var sb = new Ext.ux.StatusBar({ - defaultIconCls: 'x-status-custom' -}); - -// Changing the icon: -sb.setStatus({ - text: 'New status', - iconCls: 'x-status-custom' -}); -</code></pre> - */ - - /** - * @cfg {String} cls - * The base class applied to the containing element for this component on render (defaults to 'x-statusbar') - */ - cls: 'x-statusbar', - /** - * @cfg {String} busyIconCls - * The default <code>{@link #iconCls}</code> applied when calling - * <code>{@link #showBusy}</code> (defaults to <tt>'x-status-busy'</tt>). - * It can be overridden at any time by passing the <code>iconCls</code> - * argument into <code>{@link #showBusy}</code>. - */ - busyIconCls: 'x-status-busy', - /** - * @cfg {String} busyText - * The default <code>{@link #text}</code> applied when calling - * <code>{@link #showBusy}</code> (defaults to <tt>'Loading...'</tt>). - * It can be overridden at any time by passing the <code>text</code> - * argument into <code>{@link #showBusy}</code>. - */ - busyText: 'Loading...', - /** - * @cfg {Number} autoClear - * The number of milliseconds to wait after setting the status via - * <code>{@link #setStatus}</code> before automatically clearing the status - * text and icon (defaults to <tt>5000</tt>). Note that this only applies - * when passing the <tt>clear</tt> argument to <code>{@link #setStatus}</code> - * since that is the only way to defer clearing the status. This can - * be overridden by specifying a different <tt>wait</tt> value in - * <code>{@link #setStatus}</code>. Calls to <code>{@link #clearStatus}</code> - * always clear the status bar immediately and ignore this value. - */ - autoClear: 5000, - - /** - * @cfg {String} emptyText - * The text string to use if no text has been set. Defaults to - * <tt>' '</tt>). If there are no other items in the toolbar using - * an empty string (<tt>''</tt>) for this value would end up in the toolbar - * height collapsing since the empty string will not maintain the toolbar - * height. Use <tt>''</tt> if the toolbar should collapse in height - * vertically when no text is specified and there are no other items in - * the toolbar. - */ - emptyText: ' ', - - // private - activeThreadId: 0, - - // private - initComponent: function () { - if (this.statusAlign == 'right') { - this.cls += ' x-status-right'; - } - Ext.ux.StatusBar.superclass.initComponent.call(this); - }, - - // private - afterRender: function () { - Ext.ux.StatusBar.superclass.afterRender.call(this); - - var right = this.statusAlign == 'right'; - this.currIconCls = this.iconCls || this.defaultIconCls; - this.statusEl = new Ext.Toolbar.TextItem({ - cls: 'x-status-text ' + (this.currIconCls || ''), - text: this.text || this.defaultText || '', - }); - - if (right) { - this.add('->'); - this.add(this.statusEl); - } else { - this.insert(0, this.statusEl); - this.insert(1, '->'); - } - this.doLayout(); - }, - - /** - * Sets the status {@link #text} and/or {@link #iconCls}. Also supports automatically clearing the - * status that was set after a specified interval. - * @param {Object/String} config A config object specifying what status to set, or a string assumed - * to be the status text (and all other options are defaulted as explained below). A config - * object containing any or all of the following properties can be passed:<ul> - * <li><tt>text</tt> {String} : (optional) The status text to display. If not specified, any current - * status text will remain unchanged.</li> - * <li><tt>iconCls</tt> {String} : (optional) The CSS class used to customize the status icon (see - * {@link #iconCls} for details). If not specified, any current iconCls will remain unchanged.</li> - * <li><tt>clear</tt> {Boolean/Number/Object} : (optional) Allows you to set an internal callback that will - * automatically clear the status text and iconCls after a specified amount of time has passed. If clear is not - * specified, the new status will not be auto-cleared and will stay until updated again or cleared using - * {@link #clearStatus}. If <tt>true</tt> is passed, the status will be cleared using {@link #autoClear}, - * {@link #defaultText} and {@link #defaultIconCls} via a fade out animation. If a numeric value is passed, - * it will be used as the callback interval (in milliseconds), overriding the {@link #autoClear} value. - * All other options will be defaulted as with the boolean option. To customize any other options, - * you can pass an object in the format:<ul> - * <li><tt>wait</tt> {Number} : (optional) The number of milliseconds to wait before clearing - * (defaults to {@link #autoClear}).</li> - * <li><tt>anim</tt> {Number} : (optional) False to clear the status immediately once the callback - * executes (defaults to true which fades the status out).</li> - * <li><tt>useDefaults</tt> {Number} : (optional) False to completely clear the status text and iconCls - * (defaults to true which uses {@link #defaultText} and {@link #defaultIconCls}).</li> - * </ul></li></ul> - * Example usage:<pre><code> -// Simple call to update the text -statusBar.setStatus('New status'); - -// Set the status and icon, auto-clearing with default options: -statusBar.setStatus({ - text: 'New status', - iconCls: 'x-status-custom', - clear: true -}); - -// Auto-clear with custom options: -statusBar.setStatus({ - text: 'New status', - iconCls: 'x-status-custom', - clear: { - wait: 8000, - anim: false, - useDefaults: false - } -}); -</code></pre> - * @return {Ext.ux.StatusBar} this - */ - setStatus: function (o) { - o = o || {}; - - if (typeof o == 'string') { - o = { text: o }; - } - if (o.text !== undefined) { - this.setText(o.text); - } - if (o.iconCls !== undefined) { - this.setIcon(o.iconCls); - } - - if (o.clear) { - var c = o.clear, - wait = this.autoClear, - defaults = { useDefaults: true, anim: true }; - - if (typeof c == 'object') { - c = Ext.applyIf(c, defaults); - if (c.wait) { - wait = c.wait; - } - } else if (typeof c == 'number') { - wait = c; - c = defaults; - } else if (typeof c == 'boolean') { - c = defaults; - } - - c.threadId = this.activeThreadId; - this.clearStatus.defer(wait, this, [c]); - } - return this; - }, - - /** - * Clears the status {@link #text} and {@link #iconCls}. Also supports clearing via an optional fade out animation. - * @param {Object} config (optional) A config object containing any or all of the following properties. If this - * object is not specified the status will be cleared using the defaults below:<ul> - * <li><tt>anim</tt> {Boolean} : (optional) True to clear the status by fading out the status element (defaults - * to false which clears immediately).</li> - * <li><tt>useDefaults</tt> {Boolean} : (optional) True to reset the text and icon using {@link #defaultText} and - * {@link #defaultIconCls} (defaults to false which sets the text to '' and removes any existing icon class).</li> - * </ul> - * @return {Ext.ux.StatusBar} this - */ - clearStatus: function (o) { - o = o || {}; - - if (o.threadId && o.threadId !== this.activeThreadId) { - // this means the current call was made internally, but a newer - // thread has set a message since this call was deferred. Since - // we don't want to overwrite a newer message just ignore. - return this; - } - - var text = o.useDefaults ? this.defaultText : this.emptyText, - iconCls = o.useDefaults - ? this.defaultIconCls - ? this.defaultIconCls - : '' - : ''; - - if (o.anim) { - // animate the statusEl Ext.Element - this.statusEl.el.fadeOut({ - remove: false, - useDisplay: true, - scope: this, - callback: function () { - this.setStatus({ - text: text, - iconCls: iconCls, - }); - - this.statusEl.el.show(); - }, - }); - } else { - // hide/show the el to avoid jumpy text or icon - this.statusEl.hide(); - this.setStatus({ - text: text, - iconCls: iconCls, - }); - this.statusEl.show(); - } - return this; - }, - - /** - * Convenience method for setting the status text directly. For more flexible options see {@link #setStatus}. - * @param {String} text (optional) The text to set (defaults to '') - * @return {Ext.ux.StatusBar} this - */ - setText: function (text) { - this.activeThreadId++; - this.text = text || ''; - if (this.rendered) { - this.statusEl.setText(this.text); - } - return this; - }, - - /** - * Returns the current status text. - * @return {String} The status text - */ - getText: function () { - return this.text; - }, - - /** - * Convenience method for setting the status icon directly. For more flexible options see {@link #setStatus}. - * See {@link #iconCls} for complete details about customizing the icon. - * @param {String} iconCls (optional) The icon class to set (defaults to '', and any current icon class is removed) - * @return {Ext.ux.StatusBar} this - */ - setIcon: function (cls) { - this.activeThreadId++; - cls = cls || ''; - - if (this.rendered) { - if (this.currIconCls) { - this.statusEl.removeClass(this.currIconCls); - this.currIconCls = null; - } - if (cls.length > 0) { - this.statusEl.addClass(cls); - this.currIconCls = cls; - } - } else { - this.currIconCls = cls; - } - return this; - }, - - /** - * Convenience method for setting the status text and icon to special values that are pre-configured to indicate - * a "busy" state, usually for loading or processing activities. - * @param {Object/String} config (optional) A config object in the same format supported by {@link #setStatus}, or a - * string to use as the status text (in which case all other options for setStatus will be defaulted). Use the - * <tt>text</tt> and/or <tt>iconCls</tt> properties on the config to override the default {@link #busyText} - * and {@link #busyIconCls} settings. If the config argument is not specified, {@link #busyText} and - * {@link #busyIconCls} will be used in conjunction with all of the default options for {@link #setStatus}. - * @return {Ext.ux.StatusBar} this - */ - showBusy: function (o) { - if (typeof o == 'string') { - o = { text: o }; - } - o = Ext.applyIf(o || {}, { - text: this.busyText, - iconCls: this.busyIconCls, - }); - return this.setStatus(o); - }, -}); -Ext.reg('statusbar', Ext.ux.StatusBar); diff --git a/deluge/ui/web/js/extjs/ext-extensions.js b/deluge/ui/web/js/extjs/ext-extensions.js deleted file mode 100644 index e6cb62c..0000000 --- a/deluge/ui/web/js/extjs/ext-extensions.js +++ /dev/null @@ -1,84 +0,0 @@ -Ext.ns("Ext.ux.form"); -Ext.ux.form.FileUploadField=Ext.extend(Ext.form.TextField,{buttonText:"Browse...",buttonOnly:!1,buttonOffset:3,multiple:!1,readOnly:!0,autoSize:Ext.emptyFn,initComponent:function(){Ext.ux.form.FileUploadField.superclass.initComponent.call(this);this.addEvents("fileselected")},onRender:function(a,b){Ext.ux.form.FileUploadField.superclass.onRender.call(this,a,b);this.wrap=this.el.wrap({cls:"x-form-field-wrap x-form-file-wrap"});this.el.addClass("x-form-file-text");this.el.dom.removeAttribute("name");this.createFileInput(); -var c=Ext.applyIf(this.buttonCfg||{},{text:this.buttonText});this.button=new Ext.Button(Ext.apply(c,{renderTo:this.wrap,cls:"x-form-file-btn"+(c.iconCls?" x-btn-icon":"")}));this.buttonOnly&&(this.el.hide(),this.wrap.setWidth(this.button.getEl().getWidth()));this.bindListeners();this.resizeEl=this.positionEl=this.wrap},bindListeners:function(){this.fileInput.on({scope:this,mouseenter:function(){this.button.addClass(["x-btn-over","x-btn-focus"])},mouseleave:function(){this.button.removeClass(["x-btn-over", -"x-btn-focus","x-btn-click"])},mousedown:function(){this.button.addClass("x-btn-click")},mouseup:function(){this.button.removeClass(["x-btn-over","x-btn-focus","x-btn-click"])},change:function(){var a=this.fileInput.dom.files;a||(a=this.fileInput.dom.value);this.setValue(a);this.fireEvent("fileselected",this,a)}})},createFileInput:function(){this.fileInput=this.wrap.createChild({id:this.getFileInputId(),name:this.name||this.getId(),cls:"x-form-file",tag:"input",type:"file",size:1});this.fileInput.dom.multiple= -this.multiple},reset:function(){this.rendered&&(this.fileInput.remove(),this.createFileInput(),this.bindListeners());Ext.ux.form.FileUploadField.superclass.reset.call(this)},getFileInputId:function(){return this.id+"-file"},onResize:function(a,b){Ext.ux.form.FileUploadField.superclass.onResize.call(this,a,b);this.wrap.setWidth(a);this.buttonOnly||(a=this.wrap.getWidth()-this.button.getEl().getWidth()-this.buttonOffset,this.el.setWidth(a))},onDestroy:function(){Ext.ux.form.FileUploadField.superclass.onDestroy.call(this); -Ext.destroy(this.fileInput,this.button,this.wrap)},onDisable:function(){Ext.ux.form.FileUploadField.superclass.onDisable.call(this);this.doDisable(!0)},onEnable:function(){Ext.ux.form.FileUploadField.superclass.onEnable.call(this);this.doDisable(!1)},doDisable:function(a){this.fileInput.dom.disabled=a;this.button.setDisabled(a)},preFocus:Ext.emptyFn,alignErrorIcon:function(){this.errorIcon.alignTo(this.wrap,"tl-tr",[2,0])}});Ext.reg("fileuploadfield",Ext.ux.form.FileUploadField); -Ext.form.FileUploadField=Ext.ux.form.FileUploadField; -Ext.override(Ext.form.RadioGroup,{afterRender:function(){this.items.each(function(a){this.relayEvents(a,["check"])},this);this.lazyValue&&(this.setValue(this.value),delete this.value,delete this.lazyValue);Ext.form.RadioGroup.superclass.afterRender.call(this)},getName:function(){return this.items.first().getName()},getValue:function(){return this.items.first().getGroupValue()},setValue:function(a){this.items.each?this.items.each(function(b){if(b.rendered){var c=b.el.getValue()==String(a);b.el.dom.checked= -c;b.el.dom.defaultChecked=c;b.wrap[c?"addClass":"removeClass"](b.checkedCls)}}):(this.value=a,this.lazyValue=!0)}});Ext.ns("Ext.ux.form"); -Ext.ux.form.SpinnerField=Ext.extend(Ext.form.NumberField,{actionMode:"wrap",deferHeight:!0,autoSize:Ext.emptyFn,onBlur:Ext.emptyFn,adjustSize:Ext.BoxComponent.prototype.adjustSize,constructor:function(a){var b=Ext.copyTo({},a,"incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass"),b=this.spinner=new Ext.ux.Spinner(b),b=a.plugins?Ext.isArray(a.plugins)?a.plugins.push(b):[a.plugins,b]:b;Ext.ux.form.SpinnerField.superclass.constructor.call(this,Ext.apply(a,{plugins:b}))}, -getResizeEl:function(){return this.wrap},getPositionEl:function(){return this.wrap},alignErrorIcon:function(){this.wrap&&this.errorIcon.alignTo(this.wrap,"tl-tr",[2,0])},validateBlur:function(){return!0}});Ext.reg("spinnerfield",Ext.ux.form.SpinnerField);Ext.form.SpinnerField=Ext.ux.form.SpinnerField;Ext.override(Ext.ux.form.SpinnerField,{onBlur:Ext.form.Field.prototype.onBlur});Ext.ns("Ext.ux.form"); -Ext.ux.form.SpinnerGroup=Ext.extend(Ext.form.CheckboxGroup,{defaultType:"spinnerfield",anchor:"98%",groupCls:"x-form-spinner-group",colCfg:{},onRender:function(a,b){if(!this.el){var c={cls:this.groupCls,layout:"column",border:!1,renderTo:a},d=Ext.apply({defaultType:this.defaultType,layout:"form",border:!1,labelWidth:60,defaults:{hideLabel:!0,anchor:"60%"}},this.colCfg);if(this.items[0].items){Ext.apply(c,{layoutConfig:{columns:this.items.length},defaults:this.defaults,items:this.items});for(var e= -0,g=this.items.length;e<g;e++)Ext.applyIf(this.items[e],d)}else{var f,h=[];"string"==typeof this.columns&&(this.columns=this.items.length);if(!Ext.isArray(this.columns)){f=[];for(e=0;e<this.columns;e++)f.push(0.01*(100/this.columns));this.columns=f}f=this.columns.length;for(e=0;e<f;e++)g=Ext.apply({items:[]},d),g[1>=this.columns[e]?"columnWidth":"width"]=this.columns[e],this.defaults&&(g.defaults=Ext.apply(g.defaults||{},this.defaults)),h.push(g);if(this.vertical)for(var d=Math.ceil(this.items.length/ -f),k=0,e=0,g=this.items.length;e<g;e++)0<e&&0==e%d&&k++,this.items[e].fieldLabel&&(this.items[e].hideLabel=!1),h[k].items.push(this.items[e]);else{e=0;for(g=this.items.length;e<g;e++)d=e%f,this.items[e].fieldLabel&&(this.items[e].hideLabel=!1),h[d].items.push(this.items[e])}Ext.apply(c,{layoutConfig:{columns:f},items:h})}this.panel=new Ext.Panel(c);this.el=this.panel.getEl();this.forId&&this.itemCls&&(c=this.el.up(this.itemCls).child("label",!0))&&c.setAttribute("htmlFor",this.forId);c=this.panel.findBy(function(a){return a.isFormField}, -this);this.items=new Ext.util.MixedCollection;this.items.addAll(c);this.items.each(function(a){a.on("spin",this.onFieldChange,this);a.on("change",this.onFieldChange,this)},this);this.lazyValueSet&&(this.setValue(this.value),delete this.value,delete this.lazyValueSet);this.lazyRawValueSet&&(this.setRawValue(this.rawValue),delete this.rawValue,delete this.lazyRawValueSet)}Ext.ux.form.SpinnerGroup.superclass.onRender.call(this,a,b)},onFieldChange:function(a){this.fireEvent("change",this,this.getValue())}, -initValue:Ext.emptyFn,getValue:function(){var a=[this.items.getCount()];this.items.each(function(b,c){a[c]=Number(b.getValue())});return a},getRawValue:function(){var a=[this.items.getCount()];this.items.each(function(b,c){a[c]=Number(b.getRawValue())});return a},setValue:function(a){this.rendered?this.items.each(function(b,c){b.setValue(a[c])}):(this.value=a,this.lazyValueSet=!0)},setRawValue:function(a){this.rendered?this.items.each(function(b,c){b.setRawValue(a[c])}):(this.rawValue=a,this.lazyRawValueSet= -!0)}});Ext.reg("spinnergroup",Ext.ux.form.SpinnerGroup);Ext.namespace("Ext.ux.form"); -Ext.ux.form.ToggleField=Ext.extend(Ext.form.Field,{cls:"x-toggle-field",initComponent:function(){Ext.ux.form.ToggleField.superclass.initComponent.call(this);this.toggle=new Ext.form.Checkbox;this.toggle.on("check",this.onToggleCheck,this);this.input=new Ext.form.TextField({disabled:!0})},onRender:function(a,b){this.el||(this.panel=new Ext.Panel({cls:this.groupCls,layout:"table",layoutConfig:{columns:2},border:!1,renderTo:a}),this.panel.ownerCt=this,this.el=this.panel.getEl(),this.panel.add(this.toggle), -this.panel.add(this.input),this.panel.doLayout(),this.toggle.getEl().parent().setStyle("padding-right","10px"));Ext.ux.form.ToggleField.superclass.onRender.call(this,a,b)},onResize:function(a,b){this.panel.setSize(a,b);this.panel.doLayout();var c=a-this.toggle.getSize().width-25;this.input.setSize(c,b)},onToggleCheck:function(a,b){this.input.setDisabled(!b)}});Ext.reg("togglefield",Ext.ux.form.ToggleField);Ext.ns("Ext.ux.grid"); -Ext.ux.grid.BufferView=Ext.extend(Ext.grid.GridView,{rowHeight:19,borderHeight:2,scrollDelay:100,cacheSize:20,cleanDelay:500,initTemplates:function(){Ext.ux.grid.BufferView.superclass.initTemplates.call(this);var a=this.templates;a.rowHolder=new Ext.Template('<div class="x-grid3-row {alt}" style="{tstyle}"></div>');a.rowHolder.disableFormats=!0;a.rowHolder.compile();a.rowBody=new Ext.Template('<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',"<tbody><tr>{cells}</tr>", -this.enableRowBody?'<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>':"","</tbody></table>");a.rowBody.disableFormats=!0;a.rowBody.compile()},getStyleRowHeight:function(){return Ext.isBorderBox?this.rowHeight+this.borderHeight:this.rowHeight},getCalculatedRowHeight:function(){return this.rowHeight+this.borderHeight},getVisibleRowCount:function(){var a=this.getCalculatedRowHeight(), -b=this.scroller.dom.clientHeight;return 1>b?0:Math.ceil(b/a)},getVisibleRows:function(){var a=this.getVisibleRowCount(),b=this.scroller.dom.scrollTop,b=0===b?0:Math.floor(b/this.getCalculatedRowHeight())-1;return{first:Math.max(b,0),last:Math.min(b+a+2,this.ds.getCount()-1)}},doRender:function(a,b,c,d,e,g,f){for(var h=this.templates,k=h.cell,l=h.row,t=h.rowBody,p=e-1,u=this.getStyleRowHeight(),y=this.getVisibleRows(),x=[],n,m={},q={tstyle:"width:"+this.getTotalWidth()+";height:"+u+"px;"},r,w=0,A= -b.length;w<A;w++){r=b[w];var u=[],v=w+d,z=v>=y.first&&v<=y.last;if(z)for(var s=0;s<e;s++){n=a[s];m.id=n.id;m.css=0===s?"x-grid3-cell-first ":s==p?"x-grid3-cell-last ":"";m.attr=m.cellAttr="";m.value=n.renderer(r.data[n.name],m,r,v,s,c);m.style=n.style;if(void 0===m.value||""===m.value)m.value=" ";r.dirty&&"undefined"!==typeof r.modified[n.name]&&(m.css+=" x-grid3-dirty-cell");u[u.length]=k.apply(m)}n=[];g&&0===(v+1)%2&&(n[0]="x-grid3-row-alt");r.dirty&&(n[1]=" x-grid3-dirty-row");q.cols=e;this.getRowClass&& -(n[2]=this.getRowClass(r,v,q,c));q.alt=n.join(" ");q.cells=u.join("");x[x.length]=!z?h.rowHolder.apply(q):f?t.apply(q):l.apply(q)}return x.join("")},isRowRendered:function(a){return(a=this.getRow(a))&&0<a.childNodes.length},syncScroll:function(){Ext.ux.grid.BufferView.superclass.syncScroll.apply(this,arguments);this.update()},update:function(){this.scrollDelay?(this.renderTask||(this.renderTask=new Ext.util.DelayedTask(this.doUpdate,this)),this.renderTask.delay(this.scrollDelay)):this.doUpdate()}, -onRemove:function(a,b,c,d){Ext.ux.grid.BufferView.superclass.onRemove.apply(this,arguments);!0!==d&&this.update()},doUpdate:function(){if(0<this.getVisibleRowCount()){for(var a=this.grid,b=a.colModel,c=a.store,d=this.getColumnData(),e=this.getVisibleRows(),g,f=e.first;f<=e.last;f++)if(!this.isRowRendered(f)&&(g=this.getRow(f))){var h=this.doRender(d,[c.getAt(f)],c,f,b.getColumnCount(),a.stripeRows,!0);g.innerHTML=h}this.clean()}},clean:function(){this.cleanTask||(this.cleanTask=new Ext.util.DelayedTask(this.doClean, -this));this.cleanTask.delay(this.cleanDelay)},doClean:function(){if(0<this.getVisibleRowCount()){var a=this.getVisibleRows();a.first-=this.cacheSize;a.last+=this.cacheSize;var b=0,c=this.getRows();0>=a.first&&(b=a.last+1);for(var d=this.ds.getCount();b<d;b++)if((b<a.first||b>a.last)&&c[b].innerHTML)c[b].innerHTML=""}},removeTask:function(a){var b=this[a];b&&b.cancel&&(b.cancel(),this[a]=null)},destroy:function(){this.removeTask("cleanTask");this.removeTask("renderTask");Ext.ux.grid.BufferView.superclass.destroy.call(this)}, -layout:function(){Ext.ux.grid.BufferView.superclass.layout.call(this);this.update()}}); -Ext.override(Ext.layout.FormLayout,{renderItem:function(a,b,c){if(a&&!a.rendered&&(a.isFormField||a.fieldLabel)&&"hidden"!=a.inputType){var d=this.getTemplateArgs(a);"number"==typeof b&&(b=c.dom.childNodes[b]||null);a.formItem=b?this.fieldTpl.insertBefore(b,d,!0):this.fieldTpl.append(c,d,!0);a.actionMode="formItem";a.render("x-form-el-"+a.id);a.container=a.formItem;a.actionMode="container"}else Ext.layout.FormLayout.superclass.renderItem.apply(this,arguments)}}); -Ext.override(Ext.tree.MultiSelectionModel,{onNodeClick:function(a,b){if(b.ctrlKey&&this.isSelected(a))this.unselect(a);else if(b.shiftKey&&!this.isSelected(a)){var c=a.parentNode;if(this.lastSelNode.parentNode.id==c.id){var d=c.indexOf(a),e=c.indexOf(this.lastSelNode);this.select(this.lastSelNode,b,!1,!0);d>e&&(d+=e,e=d-e,d-=e);c.eachChild(function(a){var f=c.indexOf(a);d<f&&f<e&&this.select(a,b,!0,!0)},this);this.select(a,b,!0)}}else this.select(a,b,b.ctrlKey)},select:function(a,b,c,d){!0!==c&&this.clearSelections(!0); -if(this.isSelected(a))return this.lastSelNode=a;this.selNodes.push(a);this.lastSelNode=this.selMap[a.id]=a;a.ui.onSelectedChange(!0);!0!==d&&this.fireEvent("selectionchange",this,this.selNodes);return a}});Ext.ns("Ext.ux.tree"); -Ext.ux.tree.TreeGrid=Ext.extend(Ext.tree.TreePanel,{rootVisible:!1,useArrows:!0,lines:!1,borderWidth:Ext.isBorderBox?0:2,cls:"x-treegrid",columnResize:!0,enableSort:!0,reserveScrollOffset:!0,enableHdMenu:!0,columnsText:"Columns",initComponent:function(){this.root||(this.root=new Ext.tree.AsyncTreeNode({text:"Root"}));var a=this.loader;a?Ext.isObject(a)&&!a.load&&(a=new Ext.ux.tree.TreeGridLoader(a)):a=new Ext.ux.tree.TreeGridLoader({dataUrl:this.dataUrl,requestMethod:this.requestMethod,store:this.store}); -this.loader=a;Ext.ux.tree.TreeGrid.superclass.initComponent.call(this);this.initColumns();this.enableSort&&(this.treeGridSorter=new Ext.ux.tree.TreeGridSorter(this,this.enableSort));this.columnResize&&(this.colResizer=new Ext.tree.ColumnResizer(this.columnResize),this.colResizer.init(this));this.internalTpl||(this.internalTpl=new Ext.XTemplate('<div class="x-grid3-header">','<div class="x-treegrid-header-inner">','<div class="x-grid3-header-offset">','<table style="table-layout: fixed;" cellspacing="0" cellpadding="0" border="0"><colgroup><tpl for="columns"><col /></tpl></colgroup>', -'<thead><tr class="x-grid3-hd-row">','<tpl for="columns">','<td class="x-grid3-hd x-grid3-cell x-treegrid-hd" style="text-align: {align};" id="',this.id,'-xlhd-{#}">','<div class="x-grid3-hd-inner x-treegrid-hd-inner" unselectable="on">',this.enableHdMenu?'<a class="x-grid3-hd-btn" href="#"></a>':"",'{header}<img class="x-grid3-sort-icon" src="',Ext.BLANK_IMAGE_URL,'" />',"</div>","</td></tpl>","</tr></thead>","</table>","</div></div>","</div>",'<div class="x-treegrid-root-node">','<table class="x-treegrid-root-table" cellpadding="0" cellspacing="0" style="table-layout: fixed;"></table>', -"</div>"));this.colgroupTpl||(this.colgroupTpl=new Ext.XTemplate('<colgroup><tpl for="columns"><col style="width: {width}px"/></tpl></colgroup>'))},initColumns:function(){var a=this.columns,b=a.length,c=[],d,e;for(d=0;d<b;d++)e=a[d],e.isColumn||(e.xtype=e.xtype?/^tg/.test(e.xtype)?e.xtype:"tg"+e.xtype:"tgcolumn",e=Ext.create(e)),e.init(this),c.push(e),!1!==this.enableSort&&!1!==e.sortable&&(this.enableSort=e.sortable=!0);this.columns=c},onRender:function(){Ext.tree.TreePanel.superclass.onRender.apply(this, -arguments);this.el.addClass("x-treegrid");this.outerCt=this.body.createChild({cls:"x-tree-root-ct x-treegrid-ct "+(this.useArrows?"x-tree-arrows":this.lines?"x-tree-lines":"x-tree-no-lines")});this.internalTpl.overwrite(this.outerCt,{columns:this.columns});this.mainHd=Ext.get(this.outerCt.dom.firstChild);this.innerHd=Ext.get(this.mainHd.dom.firstChild);this.innerBody=Ext.get(this.outerCt.dom.lastChild);this.innerCt=Ext.get(this.innerBody.dom.firstChild);this.colgroupTpl.insertFirst(this.innerCt,{columns:this.columns}); -this.hideHeaders?this.el.child(".x-grid3-header").setDisplayed("none"):!1!==this.enableHdMenu&&(this.hmenu=new Ext.menu.Menu({id:this.id+"-hctx"}),!1!==this.enableColumnHide&&(this.colMenu=new Ext.menu.Menu({id:this.id+"-hcols-menu"}),this.colMenu.on({scope:this,beforeshow:this.beforeColMenuShow,itemclick:this.handleHdMenuClick}),this.hmenu.add({itemId:"columns",hideOnClick:!1,text:this.columnsText,menu:this.colMenu,iconCls:"x-cols-icon"})),this.hmenu.on("itemclick",this.handleHdMenuClick,this))}, -setRootNode:function(a){a.attributes.uiProvider=Ext.ux.tree.TreeGridRootNodeUI;a=Ext.ux.tree.TreeGrid.superclass.setRootNode.call(this,a);this.innerCt&&this.colgroupTpl.insertFirst(this.innerCt,{columns:this.columns});return a},clearInnerCt:function(){if(Ext.isIE)for(var a=this.innerCt.dom;a.firstChild;)a.removeChild(a.firstChild);else Ext.ux.tree.TreeGrid.superclass.clearInnerCt.call(this)},initEvents:function(){Ext.ux.tree.TreeGrid.superclass.initEvents.apply(this,arguments);this.mon(this.innerBody, -"scroll",this.syncScroll,this);this.mon(this.innerHd,"click",this.handleHdDown,this);this.mon(this.mainHd,{scope:this,mouseover:this.handleHdOver,mouseout:this.handleHdOut})},onResize:function(a,b){Ext.ux.tree.TreeGrid.superclass.onResize.apply(this,arguments);var c=this.innerBody.dom,d=this.innerHd.dom;if(c&&(Ext.isNumber(b)&&(c.style.height=this.body.getHeight(!0)-d.offsetHeight+"px"),Ext.isNumber(a))){var e=Ext.num(this.scrollOffset,Ext.getScrollBarWidth());if(this.reserveScrollOffset||10<c.offsetWidth- -c.clientWidth)this.setScrollOffset(e);else{var g=this;setTimeout(function(){g.setScrollOffset(10<c.offsetWidth-c.clientWidth?e:0)},10)}}},updateColumnWidths:function(){var a=this.columns,b=a.length,c=this.outerCt.query("colgroup"),d=c.length,e,g,f,h;for(f=0;f<b;f++){e=a[f];for(h=0;h<d;h++)g=c[h],g.childNodes[f].style.width=(e.hidden?0:e.width)+"px"}f=0;c=this.innerHd.query("td");for(len=c.length;f<len;f++)e=Ext.fly(c[f]),a[f]&&a[f].hidden?e.addClass("x-treegrid-hd-hidden"):e.removeClass("x-treegrid-hd-hidden"); -a=this.getTotalColumnWidth();Ext.fly(this.innerHd.dom.firstChild).setWidth(a+(this.scrollOffset||0));this.outerCt.select("table").setWidth(a);this.syncHeaderScroll()},getVisibleColumns:function(){var a=[],b=this.columns,c=b.length,d;for(d=0;d<c;d++)b[d].hidden||a.push(b[d]);return a},getTotalColumnWidth:function(){for(var a=0,b=0,c=this.getVisibleColumns(),d=c.length;b<d;b++)a+=c[b].width;return a},setScrollOffset:function(a){this.scrollOffset=a;this.updateColumnWidths()},handleHdDown:function(a, -b){var c=a.getTarget(".x-treegrid-hd");if(c&&Ext.fly(b).hasClass("x-grid3-hd-btn")){var d=this.hmenu.items,e=this.columns,g=this.findHeaderIndex(c),e=e[g];a.stopEvent();Ext.fly(c).addClass("x-grid3-hd-menu-open");this.hdCtxIndex=g;this.fireEvent("headerbuttonclick",d,e,c,g);this.hmenu.on("hide",function(){Ext.fly(c).removeClass("x-grid3-hd-menu-open")},this,{single:!0});this.hmenu.show(b,"tl-bl?")}else c&&(g=this.findHeaderIndex(c),this.fireEvent("headerclick",this.columns[g],c,g))},handleHdOver:function(a, -b){var c=a.getTarget(".x-treegrid-hd");if(c&&!this.headersDisabled){index=this.findHeaderIndex(c);this.activeHdRef=b;this.activeHdIndex=index;var d=Ext.get(c);this.activeHdRegion=d.getRegion();d.addClass("x-grid3-hd-over");if(this.activeHdBtn=d.child(".x-grid3-hd-btn"))this.activeHdBtn.dom.style.height=c.firstChild.offsetHeight-1+"px"}},handleHdOut:function(a,b){var c=a.getTarget(".x-treegrid-hd");if(c&&(!Ext.isIE||!a.within(c,!0)))this.activeHdRef=null,Ext.fly(c).removeClass("x-grid3-hd-over"),c.style.cursor= -""},findHeaderIndex:function(a){a=a.dom||a;for(var b=a.parentNode.childNodes,c=0,d;d=b[c];c++)if(d==a)return c;return-1},beforeColMenuShow:function(){var a=this.columns,b=a.length,c,d;this.colMenu.removeAll();for(c=1;c<b;c++)d=a[c],!1!==d.hideable&&this.colMenu.add(new Ext.menu.CheckItem({itemId:"col-"+c,text:d.header,checked:!d.hidden,hideOnClick:!1,disabled:!1===d.hideable}))},handleHdMenuClick:function(a){var b=this.hdCtxIndex,c=a.getItemId();!1!==this.fireEvent("headermenuclick",this.columns[b], -c,b)&&(b=c.substr(4),0<b&&this.columns[b]&&this.setColumnVisible(b,!a.checked));return!0},setColumnVisible:function(a,b){this.columns[a].hidden=!b;this.updateColumnWidths()},scrollToTop:function(){this.innerBody.dom.scrollTop=0;this.innerBody.dom.scrollLeft=0},syncScroll:function(){this.syncHeaderScroll();var a=this.innerBody.dom;this.fireEvent("bodyscroll",a.scrollLeft,a.scrollTop)},syncHeaderScroll:function(){var a=this.innerBody.dom;this.innerHd.dom.scrollLeft=a.scrollLeft;this.innerHd.dom.scrollLeft= -a.scrollLeft},registerNode:function(a){Ext.ux.tree.TreeGrid.superclass.registerNode.call(this,a);!a.uiProvider&&(!a.isRoot&&!a.ui.isTreeGridNodeUI)&&(a.ui=new Ext.ux.tree.TreeGridNodeUI(a))}});Ext.reg("treegrid",Ext.ux.tree.TreeGrid); -Ext.tree.ColumnResizer=Ext.extend(Ext.util.Observable,{minWidth:14,constructor:function(a){Ext.apply(this,a);Ext.tree.ColumnResizer.superclass.constructor.call(this)},init:function(a){this.tree=a;a.on("render",this.initEvents,this)},initEvents:function(a){a.mon(a.innerHd,"mousemove",this.handleHdMove,this);this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeStart.createDelegate(this),onStart:this.onStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onEnd.createDelegate(this), -tolerance:3,autoStart:300});this.tracker.initEl(a.innerHd);a.on("beforedestroy",this.tracker.destroy,this.tracker)},handleHdMove:function(a,b){var c=a.getPageX(),d=a.getTarget(".x-treegrid-hd",3,!0);if(d){var e=d.getRegion(),g=d.dom.style,f=d.dom.parentNode;if(5>=c-e.left&&d.dom!==f.firstChild){for(c=d.dom.previousSibling;c&&Ext.fly(c).hasClass("x-treegrid-hd-hidden");)c=c.previousSibling;c&&(this.activeHd=Ext.get(c),g.cursor=Ext.isWebKit?"e-resize":"col-resize")}else if(5>=e.right-c){for(c=d.dom;c&& -Ext.fly(c).hasClass("x-treegrid-hd-hidden");)c=c.previousSibling;c&&(this.activeHd=Ext.get(c),g.cursor=Ext.isWebKit?"w-resize":"col-resize")}else delete this.activeHd,g.cursor=""}},onBeforeStart:function(a){this.dragHd=this.activeHd;return!!this.dragHd},onStart:function(a){this.dragHeadersDisabled=this.tree.headersDisabled;this.tree.headersDisabled=!0;this.proxy=this.tree.body.createChild({cls:"x-treegrid-resizer"});this.proxy.setHeight(this.tree.body.getHeight());a=this.tracker.getXY()[0];this.hdX= -this.dragHd.getX();this.hdIndex=this.tree.findHeaderIndex(this.dragHd);this.proxy.setX(this.hdX);this.proxy.setWidth(a-this.hdX);this.maxWidth=this.tree.outerCt.getWidth()-this.tree.innerBody.translatePoints(this.hdX).left},onDrag:function(a){a=this.tracker.getXY()[0];this.proxy.setWidth((a-this.hdX).constrain(this.minWidth,this.maxWidth))},onEnd:function(a){a=this.proxy.getWidth();var b=this.tree,c=this.dragHeadersDisabled;this.proxy.remove();delete this.dragHd;b.columns[this.hdIndex].width=a;b.updateColumnWidths(); -setTimeout(function(){b.headersDisabled=c},100)}}); -(function(){Ext.override(Ext.list.Column,{init:function(){var a=Ext.data.Types,b=this.sortType;this.type?Ext.isString(this.type)&&(this.type=Ext.data.Types[this.type.toUpperCase()]||a.AUTO):this.type=a.AUTO;Ext.isString(b)?this.sortType=Ext.data.SortTypes[b]:Ext.isEmpty(b)&&(this.sortType=this.type.sortType)}});Ext.tree.Column=Ext.extend(Ext.list.Column,{});Ext.tree.NumberColumn=Ext.extend(Ext.list.NumberColumn,{});Ext.tree.DateColumn=Ext.extend(Ext.list.DateColumn,{});Ext.tree.BooleanColumn=Ext.extend(Ext.list.BooleanColumn, -{});Ext.reg("tgcolumn",Ext.tree.Column);Ext.reg("tgnumbercolumn",Ext.tree.NumberColumn);Ext.reg("tgdatecolumn",Ext.tree.DateColumn);Ext.reg("tgbooleancolumn",Ext.tree.BooleanColumn)})();Ext.ux.tree.TreeGridLoader=Ext.extend(Ext.tree.TreeLoader,{createNode:function(a){a.uiProvider||(a.uiProvider=Ext.ux.tree.TreeGridNodeUI);return Ext.tree.TreeLoader.prototype.createNode.call(this,a)}}); -Ext.ux.tree.TreeGridNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{isTreeGridNodeUI:!0,renderElements:function(a,b,c,d){var e=a.getOwnerTree(),g=e.columns,f=g[0],h,k,l;this.indentMarkup=a.parentNode?a.parentNode.ui.getChildIndent():"";k=['<tbody class="x-tree-node">','<tr ext:tree-node-id="',a.id,'" class="x-tree-node-el x-tree-node-leaf ',b.cls,'">','<td class="x-treegrid-col">','<span class="x-tree-node-indent">',this.indentMarkup,"</span>",'<img src="',this.emptyIcon,'" class="x-tree-ec-icon x-tree-elbow" />', -'<img src="',b.icon||this.emptyIcon,'" class="x-tree-node-icon',b.icon?" x-tree-node-inline-icon":"",b.iconCls?" "+b.iconCls:"",'" unselectable="on" />','<a hidefocus="on" class="x-tree-node-anchor" href="',b.href?b.href:"#",'" tabIndex="1" ',b.hrefTarget?' target="'+b.hrefTarget+'"':"",">",'<span unselectable="on">',f.tpl?f.tpl.apply(b):b[f.dataIndex]||f.text,"</span></a>","</td>"];h=1;for(l=g.length;h<l;h++)f=g[h],k.push('<td class="x-treegrid-col ',f.cls?f.cls:"",'">','<div unselectable="on" class="x-treegrid-text"', -f.align?' style="text-align: '+f.align+';"':"",">",f.tpl?f.tpl.apply(b):b[f.dataIndex],"</div>","</td>");k.push('</tr><tr class="x-tree-node-ct"><td colspan="',g.length,'">','<table class="x-treegrid-node-ct-table" cellpadding="0" cellspacing="0" style="table-layout: fixed; display: none; width: ',e.innerCt.getWidth(),'px;"><colgroup>');h=0;for(l=g.length;h<l;h++)k.push('<col style="width: ',g[h].hidden?0:g[h].width,'px;" />');k.push("</colgroup></table></td></tr></tbody>");!0!==d&&a.nextSibling&& -a.nextSibling.ui.getEl()?this.wrap=Ext.DomHelper.insertHtml("beforeBegin",a.nextSibling.ui.getEl(),k.join("")):this.wrap=Ext.DomHelper.insertHtml("beforeEnd",c,k.join(""));this.elNode=this.wrap.childNodes[0];this.ctNode=this.wrap.childNodes[1].firstChild.firstChild;a=this.elNode.firstChild.childNodes;this.indentNode=a[0];this.ecNode=a[1];this.iconNode=a[2];this.anchor=a[3];this.textNode=a[3].firstChild},animExpand:function(a){this.ctNode.style.display="";Ext.ux.tree.TreeGridNodeUI.superclass.animExpand.call(this, -a)}});Ext.ux.tree.TreeGridRootNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{isTreeGridNodeUI:!0,render:function(){this.rendered||(this.wrap=this.ctNode=this.node.ownerTree.innerCt.dom,this.node.expanded=!0);if(Ext.isWebKit){var a=this.ctNode;a.style.tableLayout=null;(function(){a.style.tableLayout="fixed"}).defer(1)}},destroy:function(){this.elNode&&Ext.dd.Registry.unregister(this.elNode.id);delete this.node},collapse:Ext.emptyFn,expand:Ext.emptyFn}); -Ext.override(Ext.ux.tree.TreeGridNodeUI,{updateColumns:function(){if(this.rendered){var a=this.node.attributes,b=this.node.getOwnerTree().columns,c=b[0];this.anchor.firstChild.innerHTML=c.tpl?c.tpl.apply(a):a[c.dataIndex]||c.text;i=1;for(len=b.length;i<len;i++)c=b[i],this.elNode.childNodes[i].firstChild.innerHTML=c.tpl?c.tpl.apply(a):a[c.dataIndex]||c.text}}}); -Ext.tree.RenderColumn=Ext.extend(Ext.tree.Column,{constructor:function(a){a.tpl=a.tpl||new Ext.XTemplate("{"+a.dataIndex+":this.format}");a.tpl.format=a.renderer;a.tpl.col=this;Ext.tree.RenderColumn.superclass.constructor.call(this,a)}});Ext.reg("tgrendercolumn",Ext.tree.RenderColumn);Ext.ns("Ext.ux.tree"); -Ext.ux.tree.TreeGridSorter=Ext.extend(Ext.tree.TreeSorter,{sortClasses:["sort-asc","sort-desc"],sortAscText:"Sort Ascending",sortDescText:"Sort Descending",constructor:function(a,b){Ext.isObject(b)||(b={property:a.columns[0].dataIndex||"text",folderSort:!0});Ext.ux.tree.TreeGridSorter.superclass.constructor.apply(this,arguments);this.tree=a;a.on("headerclick",this.onHeaderClick,this);a.ddAppendOnly=!0;var c=this;this.defaultSortFn=function(a,b){var g=c.dir&&"desc"==c.dir.toLowerCase(),f=c.property|| -"text",h=c.sortType,k=!0===c.caseSensitive,l=c.leafAttr||"leaf",t=a.attributes,p=b.attributes;if(c.folderSort){if(t[l]&&!p[l])return 1;if(!t[l]&&p[l])return-1}l=t[f];f=p[f];p=h?h(l):k?l:l.toUpperCase();v2=h?h(f):k?f:f.toUpperCase();return p<v2?g?1:-1:p>v2?g?-1:1:0};a.on("afterrender",this.onAfterTreeRender,this,{single:!0});a.on("headermenuclick",this.onHeaderMenuClick,this)},onAfterTreeRender:function(){this.tree.hmenu&&this.tree.hmenu.insert(0,{itemId:"asc",text:this.sortAscText,cls:"xg-hmenu-sort-asc"}, -{itemId:"desc",text:this.sortDescText,cls:"xg-hmenu-sort-desc"});this.updateSortIcon(0,"asc")},onHeaderMenuClick:function(a,b,c){if("asc"===b||"desc"===b)return this.onHeaderClick(a,null,c),!1},onHeaderClick:function(a,b,c){if(a&&!this.tree.headersDisabled){var d=this;d.property=a.dataIndex;d.dir=a.dir="desc"===a.dir?"asc":"desc";d.sortType=a.sortType;d.caseSensitive===Ext.isBoolean(a.caseSensitive)?a.caseSensitive:this.caseSensitive;d.sortFn=a.sortFn||this.defaultSortFn;this.tree.root.cascade(function(a){a.isLeaf()|| -d.updateSort(d.tree,a)});this.updateSortIcon(c,a.dir)}},updateSortIcon:function(a,b){var c=this.sortClasses;this.tree.innerHd.select("td").removeClass(c).item(a).addClass(c["desc"==b?1:0])}}); -Ext.ux.JSLoader=function(a){Ext.ux.JSLoader.scripts[++Ext.ux.JSLoader.index]={url:a.url,success:!0,jsLoadObj:null,options:a,onLoad:a.onLoad||Ext.emptyFn,onError:a.onError||Ext.ux.JSLoader.stdError,scope:a.scope||this};Ext.Ajax.request({url:a.url,scriptIndex:Ext.ux.JSLoader.index,success:function(a,c){var d=Ext.ux.JSLoader.scripts[c.scriptIndex];try{eval(a.responseText)}catch(e){d.success=!1,d.onError(d.options,e)}d.success&&d.onLoad.call(d.scope,d.options)},failure:function(a,c){var d=Ext.ux.JSLoader.scripts[c.scriptIndex]; -d.success=!1;d.onError(d.options,a.status)}})};Ext.ux.JSLoader.index=0;Ext.ux.JSLoader.scripts=[];Ext.ux.JSLoader.stdError=function(a,b){window.alert("Error loading script:\n\n"+a.url+"\n\nstatus: "+b)}; -Ext.ux.Spinner=Ext.extend(Ext.util.Observable,{incrementValue:1,alternateIncrementValue:5,triggerClass:"x-form-spinner-trigger",splitterClass:"x-form-spinner-splitter",alternateKey:Ext.EventObject.shiftKey,defaultValue:0,accelerate:!1,constructor:function(a){Ext.ux.Spinner.superclass.constructor.call(this,a);Ext.apply(this,a);this.mimicing=!1},init:function(a){this.field=a;a.afterMethod("onRender",this.doRender,this);a.afterMethod("onEnable",this.doEnable,this);a.afterMethod("onDisable",this.doDisable, -this);a.afterMethod("afterRender",this.doAfterRender,this);a.afterMethod("onResize",this.doResize,this);a.afterMethod("onFocus",this.doFocus,this);a.beforeMethod("onDestroy",this.doDestroy,this)},doRender:function(a,b){var c=this.el=this.field.getEl(),d=this.field;d.wrap?this.wrap=d.wrap.addClass("x-form-field-wrap"):d.wrap=this.wrap=c.wrap({cls:"x-form-field-wrap"});this.trigger=this.wrap.createChild({tag:"img",src:Ext.BLANK_IMAGE_URL,cls:"x-form-trigger "+this.triggerClass});d.width||this.wrap.setWidth(c.getWidth()+ -this.trigger.getWidth());this.splitter=this.wrap.createChild({tag:"div",cls:this.splitterClass,style:"width:13px; height:2px;"});this.splitter.setRight(Ext.isIE?1:2).setTop(10).show();this.proxy=this.trigger.createProxy("",this.splitter,!0);this.proxy.addClass("x-form-spinner-proxy");this.proxy.setStyle("left","0px");this.proxy.setSize(14,1);this.proxy.hide();this.dd=new Ext.dd.DDProxy(this.splitter.dom.id,"SpinnerDrag",{dragElId:this.proxy.id});this.initTrigger();this.initSpinner()},doAfterRender:function(){var a; -if(Ext.isIE&&this.el.getY()!=(a=this.trigger.getY()))this.el.position(),this.el.setY(a)},doEnable:function(){this.wrap&&(this.disabled=!1,this.wrap.removeClass(this.field.disabledClass))},doDisable:function(){this.wrap&&(this.disabled=!0,this.wrap.addClass(this.field.disabledClass),this.el.removeClass(this.field.disabledClass))},doResize:function(a,b){"number"==typeof a&&this.el.setWidth(a-this.trigger.getWidth());this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth())},doFocus:function(){this.mimicing|| -(this.wrap.addClass("x-trigger-wrap-focus"),this.mimicing=!0,Ext.get(Ext.isIE?document.body:document).on("mousedown",this.mimicBlur,this,{delay:10}),this.el.on("keydown",this.checkTab,this))},checkTab:function(a){a.getKey()==a.TAB&&this.triggerBlur()},mimicBlur:function(a){!this.wrap.contains(a.target)&&this.field.validateBlur(a)&&this.triggerBlur()},triggerBlur:function(){this.mimicing=!1;Ext.get(Ext.isIE?document.body:document).un("mousedown",this.mimicBlur,this);this.el.un("keydown",this.checkTab, -this);this.field.beforeBlur();this.wrap.removeClass("x-trigger-wrap-focus");this.field.onBlur.call(this.field)},initTrigger:function(){this.trigger.addClassOnOver("x-form-trigger-over");this.trigger.addClassOnClick("x-form-trigger-click")},initSpinner:function(){this.field.addEvents({spin:!0,spinup:!0,spindown:!0});this.keyNav=new Ext.KeyNav(this.el,{up:function(a){a.preventDefault();this.onSpinUp()},down:function(a){a.preventDefault();this.onSpinDown()},pageUp:function(a){a.preventDefault();this.onSpinUpAlternate()}, -pageDown:function(a){a.preventDefault();this.onSpinDownAlternate()},scope:this});this.repeater=new Ext.util.ClickRepeater(this.trigger,{accelerate:this.accelerate});this.field.mon(this.repeater,"click",this.onTriggerClick,this,{preventDefault:!0});this.field.mon(this.trigger,{mouseover:this.onMouseOver,mouseout:this.onMouseOut,mousemove:this.onMouseMove,mousedown:this.onMouseDown,mouseup:this.onMouseUp,scope:this,preventDefault:!0});this.field.mon(this.wrap,"mousewheel",this.handleMouseWheel,this); -this.dd.setXConstraint(0,0,10);this.dd.setYConstraint(1500,1500,10);this.dd.endDrag=this.endDrag.createDelegate(this);this.dd.startDrag=this.startDrag.createDelegate(this);this.dd.onDrag=this.onDrag.createDelegate(this)},onMouseOver:function(){if(!this.disabled){var a=this.getMiddle();this.tmpHoverClass=Ext.EventObject.getPageY()<a?"x-form-spinner-overup":"x-form-spinner-overdown";this.trigger.addClass(this.tmpHoverClass)}},onMouseOut:function(){this.trigger.removeClass(this.tmpHoverClass)},onMouseMove:function(){if(!this.disabled){var a= -this.getMiddle();Ext.EventObject.getPageY()>a&&"x-form-spinner-overup"==this.tmpHoverClass||Ext.EventObject.getPageY()}},onMouseDown:function(){if(!this.disabled){var a=this.getMiddle();this.tmpClickClass=Ext.EventObject.getPageY()<a?"x-form-spinner-clickup":"x-form-spinner-clickdown";this.trigger.addClass(this.tmpClickClass)}},onMouseUp:function(){this.trigger.removeClass(this.tmpClickClass)},onTriggerClick:function(){if(!this.disabled&&!this.el.dom.readOnly){var a=this.getMiddle();this["onSpin"+ -(Ext.EventObject.getPageY()<a?"Up":"Down")]()}},getMiddle:function(){var a=this.trigger.getTop(),b=this.trigger.getHeight();return a+b/2},isSpinnable:function(){return this.disabled||this.el.dom.readOnly?(Ext.EventObject.preventDefault(),!1):!0},handleMouseWheel:function(a){if(!1!=this.wrap.hasClass("x-trigger-wrap-focus")){var b=a.getWheelDelta();0<b?(this.onSpinUp(),a.stopEvent()):0>b&&(this.onSpinDown(),a.stopEvent())}},startDrag:function(){this.proxy.show();this._previousY=Ext.fly(this.dd.getDragEl()).getTop()}, -endDrag:function(){this.proxy.hide()},onDrag:function(){if(!this.disabled){var a=Ext.fly(this.dd.getDragEl()).getTop(),b="";this._previousY>a&&(b="Up");this._previousY<a&&(b="Down");if(""!=b)this["onSpin"+b]();this._previousY=a}},onSpinUp:function(){if(!1!=this.isSpinnable())if(!0==Ext.EventObject.shiftKey)this.onSpinUpAlternate();else this.spin(!1,!1),this.field.fireEvent("spin",this),this.field.fireEvent("spinup",this)},onSpinDown:function(){if(!1!=this.isSpinnable())if(!0==Ext.EventObject.shiftKey)this.onSpinDownAlternate(); -else this.spin(!0,!1),this.field.fireEvent("spin",this),this.field.fireEvent("spindown",this)},onSpinUpAlternate:function(){!1!=this.isSpinnable()&&(this.spin(!1,!0),this.field.fireEvent("spin",this),this.field.fireEvent("spinup",this))},onSpinDownAlternate:function(){!1!=this.isSpinnable()&&(this.spin(!0,!0),this.field.fireEvent("spin",this),this.field.fireEvent("spindown",this))},spin:function(a,b){var c=parseFloat(this.field.getValue()),d=!0==b?this.alternateIncrementValue:this.incrementValue; -!0==a?c-=d:c+=d;c=isNaN(c)?this.defaultValue:c;c=this.fixBoundries(c);this.field.setRawValue(c)},fixBoundries:function(a){void 0!=this.field.minValue&&a<this.field.minValue&&(a=this.field.minValue);void 0!=this.field.maxValue&&a>this.field.maxValue&&(a=this.field.maxValue);return this.fixPrecision(a)},fixPrecision:function(a){var b=isNaN(a);return!this.field.allowDecimals||-1==this.field.decimalPrecision||b||!a?b?"":a:parseFloat(parseFloat(a).toFixed(this.field.decimalPrecision))},doDestroy:function(){this.trigger&& -this.trigger.remove();this.wrap&&(this.wrap.remove(),delete this.field.wrap);this.splitter&&this.splitter.remove();this.dd&&(this.dd.unreg(),this.dd=null);this.proxy&&this.proxy.remove();this.repeater&&this.repeater.purgeListeners();this.mimicing&&Ext.get(Ext.isIE?document.body:document).un("mousedown",this.mimicBlur,this)}});Ext.form.Spinner=Ext.ux.Spinner; -Ext.ux.StatusBar=Ext.extend(Ext.Toolbar,{cls:"x-statusbar",busyIconCls:"x-status-busy",busyText:"Loading...",autoClear:5E3,emptyText:" ",activeThreadId:0,initComponent:function(){"right"==this.statusAlign&&(this.cls+=" x-status-right");Ext.ux.StatusBar.superclass.initComponent.call(this)},afterRender:function(){Ext.ux.StatusBar.superclass.afterRender.call(this);var a="right"==this.statusAlign;this.currIconCls=this.iconCls||this.defaultIconCls;this.statusEl=new Ext.Toolbar.TextItem({cls:"x-status-text "+ -(this.currIconCls||""),text:this.text||this.defaultText||""});a?(this.add("->"),this.add(this.statusEl)):(this.insert(0,this.statusEl),this.insert(1,"->"));this.doLayout()},setStatus:function(a){a=a||{};"string"==typeof a&&(a={text:a});void 0!==a.text&&this.setText(a.text);void 0!==a.iconCls&&this.setIcon(a.iconCls);if(a.clear){a=a.clear;var b=this.autoClear,c={useDefaults:!0,anim:!0};"object"==typeof a?(a=Ext.applyIf(a,c),a.wait&&(b=a.wait)):"number"==typeof a?(b=a,a=c):"boolean"==typeof a&&(a=c); -a.threadId=this.activeThreadId;this.clearStatus.defer(b,this,[a])}return this},clearStatus:function(a){a=a||{};if(a.threadId&&a.threadId!==this.activeThreadId)return this;var b=a.useDefaults?this.defaultText:this.emptyText,c=a.useDefaults?this.defaultIconCls?this.defaultIconCls:"":"";a.anim?this.statusEl.el.fadeOut({remove:!1,useDisplay:!0,scope:this,callback:function(){this.setStatus({text:b,iconCls:c});this.statusEl.el.show()}}):(this.statusEl.hide(),this.setStatus({text:b,iconCls:c}),this.statusEl.show()); -return this},setText:function(a){this.activeThreadId++;this.text=a||"";this.rendered&&this.statusEl.setText(this.text);return this},getText:function(){return this.text},setIcon:function(a){this.activeThreadId++;a=a||"";this.rendered?(this.currIconCls&&(this.statusEl.removeClass(this.currIconCls),this.currIconCls=null),0<a.length&&(this.statusEl.addClass(a),this.currIconCls=a)):this.currIconCls=a;return this},showBusy:function(a){"string"==typeof a&&(a={text:a});a=Ext.applyIf(a||{},{text:this.busyText, -iconCls:this.busyIconCls});return this.setStatus(a)}});Ext.reg("statusbar",Ext.ux.StatusBar); diff --git a/deluge/ui/web/js/gettext.js b/deluge/ui/web/js/gettext.js deleted file mode 100644 index 559577a..0000000 --- a/deluge/ui/web/js/gettext.js +++ /dev/null @@ -1,326 +0,0 @@ -GetText={maps:{},add:function(string,translation){this.maps[string]=translation},get:function(string){if (this.maps[string]){string=this.maps[string]} return string}};function _(string){return GetText.get(string)}GetText.add('10 KiB/s','${escape(_("10 KiB/s"))}') -GetText.add('30 KiB/s','${escape(_("30 KiB/s"))}') -GetText.add('300 KiB/s','${escape(_("300 KiB/s"))}') -GetText.add('5 KiB/s','${escape(_("5 KiB/s"))}') -GetText.add('80 KiB/s','${escape(_("80 KiB/s"))}') -GetText.add('<b>IP</b> {0}','${escape(_("<b>IP</b> {0}"))}') -GetText.add('About Deluge','${escape(_("About Deluge"))}') -GetText.add('Active','${escape(_("Active"))}') -GetText.add('Active Torrents','${escape(_("Active Torrents"))}') -GetText.add('Add','${escape(_("Add"))}') -GetText.add('Add Connection','${escape(_("Add Connection"))}') -GetText.add('Add In Paused State','${escape(_("Add In Paused State"))}') -GetText.add('Add Torrents','${escape(_("Add Torrents"))}') -GetText.add('Add Tracker','${escape(_("Add Tracker"))}') -GetText.add('Add from Url','${escape(_("Add from Url"))}') -GetText.add('Add torrents in Paused state','${escape(_("Add torrents in Paused state"))}') -GetText.add('Added','${escape(_("Added"))}') -GetText.add('Address','${escape(_("Address"))}') -GetText.add('All','${escape(_("All"))}') -GetText.add('Allocating','${escape(_("Allocating"))}') -GetText.add('Allow Remote Connections','${escape(_("Allow Remote Connections"))}') -GetText.add('Allow the use of multiple filters at once','${escape(_("Allow the use of multiple filters at once"))}') -GetText.add('Announce OK','${escape(_("Announce OK"))}') -GetText.add('Announce Sent','${escape(_("Announce Sent"))}') -GetText.add('Apply','${escape(_("Apply"))}') -GetText.add('Author Email:','${escape(_("Author Email:"))}') -GetText.add('Author:','${escape(_("Author:"))}') -GetText.add('Auto Managed','${escape(_("Auto Managed"))}') -GetText.add('Avail','${escape(_("Avail"))}') -GetText.add('Back','${escape(_("Back"))}') -GetText.add('Bandwidth','${escape(_("Bandwidth"))}') -GetText.add('Be alerted about new releases','${escape(_("Be alerted about new releases"))}') -GetText.add('Bottom','${escape(_("Bottom"))}') -GetText.add('Browse','${escape(_("Browse"))}') -GetText.add('Browse...','${escape(_("Browse..."))}') -GetText.add('Cache','${escape(_("Cache"))}') -GetText.add('Cache Expiry (seconds):','${escape(_("Cache Expiry (seconds):"))}') -GetText.add('Cache Size (16 KiB Blocks):','${escape(_("Cache Size (16 KiB Blocks):"))}') -GetText.add('Cancel','${escape(_("Cancel"))}') -GetText.add('Certificate:','${escape(_("Certificate:"))}') -GetText.add('Change Default Password','${escape(_("Change Default Password"))}') -GetText.add('Change Successful','${escape(_("Change Successful"))}') -GetText.add('Checking','${escape(_("Checking"))}') -GetText.add('Client','${escape(_("Client"))}') -GetText.add('Client:','${escape(_("Client:"))}') -GetText.add('Close','${escape(_("Close"))}') -GetText.add('Comment:','${escape(_("Comment:"))}') -GetText.add('Complete Seen','${escape(_("Complete Seen"))}') -GetText.add('Completed','${escape(_("Completed"))}') -GetText.add('Confirm:','${escape(_("Confirm:"))}') -GetText.add('Connect','${escape(_("Connect"))}') -GetText.add('Connected','${escape(_("Connected"))}') -GetText.add('Connection Limit','${escape(_("Connection Limit"))}') -GetText.add('Connection Manager','${escape(_("Connection Manager"))}') -GetText.add('Connection restored','${escape(_("Connection restored"))}') -GetText.add('Connections','${escape(_("Connections"))}') -GetText.add('Cookies','${escape(_("Cookies"))}') -GetText.add('Copy','${escape(_("Copy"))}') -GetText.add('Copy Magnet URI','${escape(_("Copy Magnet URI"))}') -GetText.add('Copy of .torrent files to:','${escape(_("Copy of .torrent files to:"))}') -GetText.add('Copyright 2007-2018 Deluge Team','${escape(_("Copyright 2007-2018 Deluge Team"))}') -GetText.add('Create','${escape(_("Create"))}') -GetText.add('Created By:','${escape(_("Created By:"))}') -GetText.add('D/L Speed Limit','${escape(_("D/L Speed Limit"))}') -GetText.add('DHT','${escape(_("DHT"))}') -GetText.add('DHT Nodes','${escape(_("DHT Nodes"))}') -GetText.add('Daemon','${escape(_("Daemon"))}') -GetText.add('Daemon port:','${escape(_("Daemon port:"))}') -GetText.add('Deluge','${escape(_("Deluge"))}') -GetText.add('Details','${escape(_("Details"))}') -GetText.add('Details:','${escape(_("Details:"))}') -GetText.add('Disabled','${escape(_("Disabled"))}') -GetText.add('Disconnect','${escape(_("Disconnect"))}') -GetText.add('Down','${escape(_("Down"))}') -GetText.add('Down Limit','${escape(_("Down Limit"))}') -GetText.add('Down Speed','${escape(_("Down Speed"))}') -GetText.add('Download','${escape(_("Download"))}') -GetText.add('Download Folder','${escape(_("Download Folder"))}') -GetText.add('Download Folder:','${escape(_("Download Folder:"))}') -GetText.add('Download Speed','${escape(_("Download Speed"))}') -GetText.add('Download to:','${escape(_("Download to:"))}') -GetText.add('Downloaded','${escape(_("Downloaded"))}') -GetText.add('Downloading','${escape(_("Downloading"))}') -GetText.add('Downloading:','${escape(_("Downloading:"))}') -GetText.add('Downloads','${escape(_("Downloads"))}') -GetText.add('ETA','${escape(_("ETA"))}') -GetText.add('Edit','${escape(_("Edit"))}') -GetText.add('Edit Connection','${escape(_("Edit Connection"))}') -GetText.add('Edit Tracker','${escape(_("Edit Tracker"))}') -GetText.add('Edit Trackers','${escape(_("Edit Trackers"))}') -GetText.add('Either','${escape(_("Either"))}') -GetText.add('Enabled','${escape(_("Enabled"))}') -GetText.add('Encryption','${escape(_("Encryption"))}') -GetText.add('Error','${escape(_("Error"))}') -GetText.add('Expand All','${escape(_("Expand All"))}') -GetText.add('External IP Address','${escape(_("External IP Address"))}') -GetText.add('Failed to download torrent','${escape(_("Failed to download torrent"))}') -GetText.add('Failed to upload torrent','${escape(_("Failed to upload torrent"))}') -GetText.add('File','${escape(_("File"))}') -GetText.add('File Browser','${escape(_("File Browser"))}') -GetText.add('Filename','${escape(_("Filename"))}') -GetText.add('Files','${escape(_("Files"))}') -GetText.add('Filters','${escape(_("Filters"))}') -GetText.add('Find More','${escape(_("Find More"))}') -GetText.add('Folders','${escape(_("Folders"))}') -GetText.add('Force Proxy','${escape(_("Force Proxy"))}') -GetText.add('Force Recheck','${escape(_("Force Recheck"))}') -GetText.add('Force Use of Proxy','${escape(_("Force Use of Proxy"))}') -GetText.add('Forced','${escape(_("Forced"))}') -GetText.add('Forward','${escape(_("Forward"))}') -GetText.add('Freespace in download folder','${escape(_("Freespace in download folder"))}') -GetText.add('From:','${escape(_("From:"))}') -GetText.add('Full Stream','${escape(_("Full Stream"))}') -GetText.add('General','${escape(_("General"))}') -GetText.add('GeoIP Database','${escape(_("GeoIP Database"))}') -GetText.add('Global Bandwidth Usage','${escape(_("Global Bandwidth Usage"))}') -GetText.add('HTTP','${escape(_("HTTP"))}') -GetText.add('HTTP Auth','${escape(_("HTTP Auth"))}') -GetText.add('Handshake','${escape(_("Handshake"))}') -GetText.add('Hash:','${escape(_("Hash:"))}') -GetText.add('Help','${escape(_("Help"))}') -GetText.add('Hide Client Identity','${escape(_("Hide Client Identity"))}') -GetText.add('High','${escape(_("High"))}') -GetText.add('Home','${escape(_("Home"))}') -GetText.add('Homepage:','${escape(_("Homepage:"))}') -GetText.add('Host','${escape(_("Host"))}') -GetText.add('Host:','${escape(_("Host:"))}') -GetText.add('I2P','${escape(_("I2P"))}') -GetText.add('Ignore limits on local network','${escape(_("Ignore limits on local network"))}') -GetText.add('Ignore slow torrents','${escape(_("Ignore slow torrents"))}') -GetText.add('Incoming Address','${escape(_("Incoming Address"))}') -GetText.add('Incoming Port','${escape(_("Incoming Port"))}') -GetText.add('Incoming:','${escape(_("Incoming:"))}') -GetText.add('Infohash','${escape(_("Infohash"))}') -GetText.add('Install','${escape(_("Install"))}') -GetText.add('Install Plugin','${escape(_("Install Plugin"))}') -GetText.add('Interface','${escape(_("Interface"))}') -GetText.add('Invalid Password','${escape(_("Invalid Password"))}') -GetText.add('KiB/s','${escape(_("KiB/s"))}') -GetText.add('LSD','${escape(_("LSD"))}') -GetText.add('Labels','${escape(_("Labels"))}') -GetText.add('Language','${escape(_("Language"))}') -GetText.add('Last Transfer','${escape(_("Last Transfer"))}') -GetText.add('Level:','${escape(_("Level:"))}') -GetText.add('Loading','${escape(_("Loading"))}') -GetText.add('Login','${escape(_("Login"))}') -GetText.add('Login Failed','${escape(_("Login Failed"))}') -GetText.add('Logout','${escape(_("Logout"))}') -GetText.add('Lost Connection','${escape(_("Lost Connection"))}') -GetText.add('Lost connection to webserver','${escape(_("Lost connection to webserver"))}') -GetText.add('Low','${escape(_("Low"))}') -GetText.add('Max Connections','${escape(_("Max Connections"))}') -GetText.add('Max Connections:','${escape(_("Max Connections:"))}') -GetText.add('Max Down Speed','${escape(_("Max Down Speed"))}') -GetText.add('Max Download Speed:','${escape(_("Max Download Speed:"))}') -GetText.add('Max Up Speed','${escape(_("Max Up Speed"))}') -GetText.add('Max Upload Slots','${escape(_("Max Upload Slots"))}') -GetText.add('Max Upload Slots:','${escape(_("Max Upload Slots:"))}') -GetText.add('Max Upload Speed:','${escape(_("Max Upload Speed:"))}') -GetText.add('Maximum Connection Attempts per Second:','${escape(_("Maximum Connection Attempts per Second:"))}') -GetText.add('Maximum Connections:','${escape(_("Maximum Connections:"))}') -GetText.add('Maximum Download Speed (KiB/s):','${escape(_("Maximum Download Speed (KiB/s):"))}') -GetText.add('Maximum Half-Open Connections:','${escape(_("Maximum Half-Open Connections:"))}') -GetText.add('Maximum Upload Slots','${escape(_("Maximum Upload Slots"))}') -GetText.add('Maximum Upload Slots:','${escape(_("Maximum Upload Slots:"))}') -GetText.add('Maximum Upload Speed (KiB/s):','${escape(_("Maximum Upload Speed (KiB/s):"))}') -GetText.add('Mixed','${escape(_("Mixed"))}') -GetText.add('Move','${escape(_("Move"))}') -GetText.add('Move Completed Folder','${escape(_("Move Completed Folder"))}') -GetText.add('Move Completed:','${escape(_("Move Completed:"))}') -GetText.add('Move Download Folder','${escape(_("Move Download Folder"))}') -GetText.add('Move completed to:','${escape(_("Move completed to:"))}') -GetText.add('NAT-PMP','${escape(_("NAT-PMP"))}') -GetText.add('Name','${escape(_("Name"))}') -GetText.add('Name:','${escape(_("Name:"))}') -GetText.add('Network','${escape(_("Network"))}') -GetText.add('Network Extras','${escape(_("Network Extras"))}') -GetText.add('Never','${escape(_("Never"))}') -GetText.add('New Torrents','${escape(_("New Torrents"))}') -GetText.add('New:','${escape(_("New:"))}') -GetText.add('None','${escape(_("None"))}') -GetText.add('Normal','${escape(_("Normal"))}') -GetText.add('Not Connected','${escape(_("Not Connected"))}') -GetText.add('Not a valid torrent','${escape(_("Not a valid torrent"))}') -GetText.add('OK','${escape(_("OK"))}') -GetText.add('Off','${escape(_("Off"))}') -GetText.add('Offline','${escape(_("Offline"))}') -GetText.add('Old:','${escape(_("Old:"))}') -GetText.add('On','${escape(_("On"))}') -GetText.add('Online','${escape(_("Online"))}') -GetText.add('Options','${escape(_("Options"))}') -GetText.add('Other','${escape(_("Other"))}') -GetText.add('Outgoing Interface','${escape(_("Outgoing Interface"))}') -GetText.add('Outgoing Ports','${escape(_("Outgoing Ports"))}') -GetText.add('Outgoing:','${escape(_("Outgoing:"))}') -GetText.add('Owner','${escape(_("Owner"))}') -GetText.add('Password','${escape(_("Password"))}') -GetText.add('Password:','${escape(_("Password:"))}') -GetText.add('Path:','${escape(_("Path:"))}') -GetText.add('Pause','${escape(_("Pause"))}') -GetText.add('Pause torrent','${escape(_("Pause torrent"))}') -GetText.add('Paused','${escape(_("Paused"))}') -GetText.add('Peer Exchange','${escape(_("Peer Exchange"))}') -GetText.add('Peer TOS Byte:','${escape(_("Peer TOS Byte:"))}') -GetText.add('Peers','${escape(_("Peers"))}') -GetText.add('Per Torrent Bandwidth Usage','${escape(_("Per Torrent Bandwidth Usage"))}') -GetText.add('Periodically check the website for new releases','${escape(_("Periodically check the website for new releases"))}') -GetText.add('Plugin','${escape(_("Plugin"))}') -GetText.add('Plugin Egg','${escape(_("Plugin Egg"))}') -GetText.add('Plugins','${escape(_("Plugins"))}') -GetText.add('Port','${escape(_("Port"))}') -GetText.add('Port:','${escape(_("Port:"))}') -GetText.add('Pre-allocate disk space','${escape(_("Pre-allocate disk space"))}') -GetText.add('Preallocate Disk Space','${escape(_("Preallocate Disk Space"))}') -GetText.add('Prefer seeding torrents','${escape(_("Prefer seeding torrents"))}') -GetText.add('Preferences','${escape(_("Preferences"))}') -GetText.add('Prioritize First/Last','${escape(_("Prioritize First/Last"))}') -GetText.add('Prioritize First/Last Pieces','${escape(_("Prioritize First/Last Pieces"))}') -GetText.add('Prioritize first and last pieces of torrent','${escape(_("Prioritize first and last pieces of torrent"))}') -GetText.add('Priority','${escape(_("Priority"))}') -GetText.add('Private','${escape(_("Private"))}') -GetText.add('Private Key:','${escape(_("Private Key:"))}') -GetText.add('Progress','${escape(_("Progress"))}') -GetText.add('Protocol Traffic Download/Upload','${escape(_("Protocol Traffic Download/Upload"))}') -GetText.add('Proxy','${escape(_("Proxy"))}') -GetText.add('Proxy Hostnames','${escape(_("Proxy Hostnames"))}') -GetText.add('Proxy Peers','${escape(_("Proxy Peers"))}') -GetText.add('Proxy Trackers','${escape(_("Proxy Trackers"))}') -GetText.add('Public','${escape(_("Public"))}') -GetText.add('Queue','${escape(_("Queue"))}') -GetText.add('Queue to top','${escape(_("Queue to top"))}') -GetText.add('Queued','${escape(_("Queued"))}') -GetText.add('Rate limit IP overhead','${escape(_("Rate limit IP overhead"))}') -GetText.add('Ratio','${escape(_("Ratio"))}') -GetText.add('Refresh','${escape(_("Refresh"))}') -GetText.add('Remaining','${escape(_("Remaining"))}') -GetText.add('Remove','${escape(_("Remove"))}') -GetText.add('Remove Torrent','${escape(_("Remove Torrent"))}') -GetText.add('Remove With Data','${escape(_("Remove With Data"))}') -GetText.add('Remove at ratio','${escape(_("Remove at ratio"))}') -GetText.add('Remove torrent','${escape(_("Remove torrent"))}') -GetText.add('Resume','${escape(_("Resume"))}') -GetText.add('Save','${escape(_("Save"))}') -GetText.add('Seeding','${escape(_("Seeding"))}') -GetText.add('Seeding Rotation','${escape(_("Seeding Rotation"))}') -GetText.add('Seeding:','${escape(_("Seeding:"))}') -GetText.add('Seeds','${escape(_("Seeds"))}') -GetText.add('Seeds:Peers','${escape(_("Seeds:Peers"))}') -GetText.add('Select an egg','${escape(_("Select an egg"))}') -GetText.add('Sequential Download','${escape(_("Sequential Download"))}') -GetText.add('Sequential download','${escape(_("Sequential download"))}') -GetText.add('Server','${escape(_("Server"))}') -GetText.add('Server:','${escape(_("Server:"))}') -GetText.add('Session Timeout:','${escape(_("Session Timeout:"))}') -GetText.add('Set Maximum Connections','${escape(_("Set Maximum Connections"))}') -GetText.add('Set Maximum Download Speed','${escape(_("Set Maximum Download Speed"))}') -GetText.add('Set Maximum Upload Speed','${escape(_("Set Maximum Upload Speed"))}') -GetText.add('Settings','${escape(_("Settings"))}') -GetText.add('Share Ratio Reached','${escape(_("Share Ratio Reached"))}') -GetText.add('Share Ratio:','${escape(_("Share Ratio:"))}') -GetText.add('Shared','${escape(_("Shared"))}') -GetText.add('Show filters with zero torrents','${escape(_("Show filters with zero torrents"))}') -GetText.add('Show session speed in titlebar','${escape(_("Show session speed in titlebar"))}') -GetText.add('Size','${escape(_("Size"))}') -GetText.add('Skip','${escape(_("Skip"))}') -GetText.add('Skip File Hash Check','${escape(_("Skip File Hash Check"))}') -GetText.add('Socks4','${escape(_("Socks4"))}') -GetText.add('Socks5','${escape(_("Socks5"))}') -GetText.add('Socks5 Auth','${escape(_("Socks5 Auth"))}') -GetText.add('Start Daemon','${escape(_("Start Daemon"))}') -GetText.add('State','${escape(_("State"))}') -GetText.add('States','${escape(_("States"))}') -GetText.add('Status','${escape(_("Status"))}') -GetText.add('Status:','${escape(_("Status:"))}') -GetText.add('Stop Daemon','${escape(_("Stop Daemon"))}') -GetText.add('Stop seed at ratio:','${escape(_("Stop seed at ratio:"))}') -GetText.add('Super Seed','${escape(_("Super Seed"))}') -GetText.add('Super Seeding','${escape(_("Super Seeding"))}') -GetText.add('System Default','${escape(_("System Default"))}') -GetText.add('System Information','${escape(_("System Information"))}') -GetText.add('The connection to the webserver has been lost!','${escape(_("The connection to the webserver has been lost!"))}') -GetText.add('Tier','${escape(_("Tier"))}') -GetText.add('Time (m):','${escape(_("Time (m):"))}') -GetText.add('Time Ratio:','${escape(_("Time Ratio:"))}') -GetText.add('To:','${escape(_("To:"))}') -GetText.add('Top','${escape(_("Top"))}') -GetText.add('Total Files:','${escape(_("Total Files:"))}') -GetText.add('Total Size:','${escape(_("Total Size:"))}') -GetText.add('Total:','${escape(_("Total:"))}') -GetText.add('Tracker','${escape(_("Tracker"))}') -GetText.add('Tracker Host','${escape(_("Tracker Host"))}') -GetText.add('Tracker:','${escape(_("Tracker:"))}') -GetText.add('Trackers','${escape(_("Trackers"))}') -GetText.add('Trackers:','${escape(_("Trackers:"))}') -GetText.add('Type Of Service','${escape(_("Type Of Service"))}') -GetText.add('Type:','${escape(_("Type:"))}') -GetText.add('U/L Speed Limit','${escape(_("U/L Speed Limit"))}') -GetText.add('UPnP','${escape(_("UPnP"))}') -GetText.add('Unable to add host: {0}','${escape(_("Unable to add host: {0}"))}') -GetText.add('Unable to edit host','${escape(_("Unable to edit host"))}') -GetText.add('Unlimited','${escape(_("Unlimited"))}') -GetText.add('Up','${escape(_("Up"))}') -GetText.add('Up Limit','${escape(_("Up Limit"))}') -GetText.add('Up Speed','${escape(_("Up Speed"))}') -GetText.add('Update Tracker','${escape(_("Update Tracker"))}') -GetText.add('Updates','${escape(_("Updates"))}') -GetText.add('Upload Slot Limit','${escape(_("Upload Slot Limit"))}') -GetText.add('Upload Speed','${escape(_("Upload Speed"))}') -GetText.add('Uploaded','${escape(_("Uploaded"))}') -GetText.add('Uploading your plugin...','${escape(_("Uploading your plugin..."))}') -GetText.add('Uploading your torrent...','${escape(_("Uploading your torrent..."))}') -GetText.add('Url','${escape(_("Url"))}') -GetText.add('Use Random Port','${escape(_("Use Random Port"))}') -GetText.add('Use Random Ports','${escape(_("Use Random Ports"))}') -GetText.add('Username:','${escape(_("Username:"))}') -GetText.add('Version','${escape(_("Version"))}') -GetText.add('Version:','${escape(_("Version:"))}') -GetText.add('Warning','${escape(_("Warning"))}') -GetText.add('WebUI Language Changed','${escape(_("WebUI Language Changed"))}') -GetText.add('WebUI Password','${escape(_("WebUI Password"))}') -GetText.add('Yes, please send anonymous statistics','${escape(_("Yes, please send anonymous statistics"))}') -GetText.add('You entered an incorrect password','${escape(_("You entered an incorrect password"))}') -GetText.add('Your old password was incorrect!','${escape(_("Your old password was incorrect!"))}') -GetText.add('Your password was successfully changed!','${escape(_("Your password was successfully changed!"))}') -GetText.add('libtorrent:','${escape(_("libtorrent:"))}') -GetText.add('n/a','${escape(_("n/a"))}') |