diff --git a/deluge/ui/web/js/Deluge.Add.js b/deluge/ui/web/js/Deluge.Add.js index 99309e98f..e9ffb9205 100644 --- a/deluge/ui/web/js/Deluge.Add.js +++ b/deluge/ui/web/js/Deluge.Add.js @@ -76,7 +76,7 @@ Ext.deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, { folderSort: true }); - this.optionsManager = new Deluge.OptionsManager({ + this.optionsManager = new Deluge.MultiOptionsManager({ defaults: { 'add_paused': false, 'compact_allocation': false, diff --git a/deluge/ui/web/js/Deluge.Details.Options.js b/deluge/ui/web/js/Deluge.Details.Options.js index 1d0974d8a..b62ab2293 100644 --- a/deluge/ui/web/js/Deluge.Details.Options.js +++ b/deluge/ui/web/js/Deluge.Details.Options.js @@ -56,7 +56,7 @@ Ext.deluge.details.OptionsTab = Ext.extend(Ext.form.FormPanel, { Ext.deluge.details.OptionsTab.superclass.initComponent.call(this); this.fieldsets = {}, this.fields = {}; - this.optionsManager = new Deluge.OptionsManager({ + this.optionsManager = new Deluge.MultiOptionsManager({ defaults: { 'max_download_speed': -1, 'max_upload_speed': -1, diff --git a/deluge/ui/web/js/Deluge.MultiOptionsManager.js b/deluge/ui/web/js/Deluge.MultiOptionsManager.js new file mode 100644 index 000000000..550411d16 --- /dev/null +++ b/deluge/ui/web/js/Deluge.MultiOptionsManager.js @@ -0,0 +1,248 @@ +/* +Script: + Deluge.MultiOptionsManager.js + +Copyright: + (C) Damien Churchill 2009 + 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. +*/ + +/** + * @description A class that can be used to manage options throughout the ui. + * @namespace Deluge + * @class Deluge.MultiOptionsManager + */ +Deluge.MultiOptionsManager = Ext.extend(Deluge.OptionsManager, { + + constructor: function(config) { + config = config || {}; + this.options = {}; + this.binds = {}; + this.changed = {}; + this.defaults = (config && config['defaults']) || {}; + + this.addEvents({ + 'add': true, + 'changed': true, + 'reset': true + }); + this.on('changed', this.onChange, this); + + Deluge.MultiOptionsManager.superclass.constructor.call(this); + }, + + /** + * Add a set of default options and values to the options manager + * @param {String} id + * @param {Object} options The default options. + */ + addOptions: function(options) { + this.options[id] = options; + }, + + /** + * Binds a form field to the specified option. + * @param {String} option + * @param {Ext.form.Field} field + */ + bind: function(option, field) { + this.binds[option] = field; + this.binds[field] = option; + + switch (field.getXType()) { + case 'checkbox': + case 'radiogroup': + field.on('check', this.onFieldChange, this); + break; + case 'uxspinner': + field.on('spin', this.onFieldChange, this); + field.on('keypress', this.onFieldChange, this); + break; + default: + break; + } + }, + + /** + * Changes bound fields to use the specified id. + * @param {String} id + */ + changeId: function(id) { + this.currentId = id; + for (var option in this.defaults) { + if (!this.binds[option]) continue; + this.binds[option].setValue(this.get(id, option)); + } + }, + + /** + * Get the value for an option + * @param {String} id + * @param {String|Array} [option] A single option or an array of options to return. + * @returns {Object} the options value. + */ + get: function(id, option) { + if (!option) { + var values = {}; + for (var key in this.defaults) { + values[key] = this.get(id, key); + } + return values; + } else { + return (this.hasChanged(id, option)) ? this.changed[id][option] : this.getDefault(id, option); + } + }, + + /** + * Returns the changed values. + * @param {String} id + * @returns {Object} the changed options + */ + getChanged: function(id) { + return (this.changed[id]) ? this.changed[id] : {}; + }, + + /** + * Get the default value for an option. + * @param {String} id + * @param {String|Array} [option] A single option or an array of options to return. + * @returns {Object} the value of the option + */ + getDefault: function(id, option) { + return (this.hasOption(id, option)) ? this.options[id][option] : this.defaults[option]; + }, + + /** + * Check to see if the option has been changed. + * @param {String} id + * @param {String} option + * @returns {Boolean} true if the option has been changed, else false. + */ + hasChanged: function(id, option) { + return (this.changed[id] && !Ext.isEmpty(this.changed[id][option])); + }, + + /** + * Check to see if an id has had an option set to something other than the + * default value. + * @param {String} id + * @param {String} option + * @returns {Boolean} true if the id has an option, else false. + */ + hasOption: function(id, option) { + return (this.options[id] && !Ext.isEmpty(this.options[id][option])); + }, + + /** + * Reset the options back to the default values for the specified id. + * @param {String} id + */ + reset: function(id) { + if (!this.changed[id]) return; + delete this.changed[id]; + }, + + /** + * 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 + */ + set: function(id, option, value) { + if (typeof value === undefined) { + for (var key in option) { + this.set(id, key, option[key]); + } + } else { + if (!this.options[id]) this.options[id] = {}; + this.options[id][option] = value; + } + }, + + /** + * 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(id, option, value) { + if (typeof value === undefined) { + for (var key in option) { + this.update(id, key, option[key]); + } + } else { + if (!this.changed[id]) this.changed[id] = {}; + + var oldValue = this.get(id, option); + if (oldValue == value) return; + + var defaultValue = this.getDefault(id, option); + if (defaultValue == value) { + if (this.hasChanged(id, option)) delete this.changed[id][option]; + this.fireEvent('changed', id, option, value, oldValue); + return; + } + + if (Ext.type(defaultValue) != Ext.type(value)) { + switch (Ext.type(defaultValue)) { + case 'string': + value = String(value); + break; + case 'number': + value = Number(value); + break; + case 'boolean': + value = Boolean(value); + break; + } + } + + this.changed[id][option] = value; + this.fireEvent('changed', id, option, value, oldValue); + } + }, + + /* Event Handlers */ + + /** + * Stops a form fields value from being blocked by the change functions + * @param {Ext.form.Field} field + * @private + */ + onFieldChange: function(field) { + var option = this.binds[field]; + this.update(this.currentId, option, field.getValue()); + }, + + onChange: function(id, option, newValue, oldValue) { + // If we don't have a bind there's nothing to do. + if (Ext.isEmpty(this.binds[option])) return; + + // Set the form field to the new value. + this.binds[option].setValue(newValue); + } +}); \ No newline at end of file diff --git a/deluge/ui/web/js/Deluge.OptionsManager.js b/deluge/ui/web/js/Deluge.OptionsManager.js index 5ad08ea3f..34a94f9fd 100644 --- a/deluge/ui/web/js/Deluge.OptionsManager.js +++ b/deluge/ui/web/js/Deluge.OptionsManager.js @@ -31,6 +31,8 @@ Copyright: statement from all source files in the program, then also delete it here. */ +Ext.namespace('Deluge'); + /** * @description A class that can be used to manage options throughout the ui. * @namespace Deluge @@ -42,9 +44,7 @@ Deluge.OptionsManager = Ext.extend(Ext.util.Observable, { config = config || {}; this.binds = {}; this.changed = {}; - this.defaults = (config && config['defaults']) || {}; - this.options = {}; - this.currentId = null; + this.options = (config && config['options']) || {}; this.addEvents({ 'add': true, @@ -61,8 +61,8 @@ Deluge.OptionsManager = Ext.extend(Ext.util.Observable, { * @param {String} id * @param {Object} options The default options. */ - addOptions: function(id, options) { - this.options[id] = options; + addOptions: function(options) { + this.options = Ext.applyIf(this.options, options); }, /** @@ -89,52 +89,42 @@ Deluge.OptionsManager = Ext.extend(Ext.util.Observable, { }, /** - * Changes bound fields to use the specified id. - * @param {String} id - */ - changeId: function(id) { - this.currentId = id; - for (var option in this.defaults) { - if (!this.binds[option]) continue; - this.binds[option].setValue(this.get(id, option)); - } - }, - - /** - * Get the value for an option - * @param {String} id - * @param {String|Array} [option] A single option or an array of options to return. + * 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(id, option) { - if (!option) { - var values = {}; - for (var key in this.defaults) { - values[key] = this.get(id, key); - } - return values; - } else { - return (this.hasChanged(id, option)) ? this.changed[id][option] : this.getDefault(id, option); - } + get: function() { + var options = {}; + Ext.each(arguments, function(option) { + if (!this.has(option)) return; + options[option] = (this.isDirty(option)) ? this.changed[option] : this.options[option]; + }); + return options; }, /** - * Returns the changed values. - * @param {String} id - * @returns {Object} the changed options - */ - getChanged: function(id) { - return (this.changed[id]) ? this.changed[id] : {}; - }, - - /** - * Get the default value for an option. - * @param {String} id + * 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(id, option) { - return (this.hasOption(id, option)) ? this.options[id][option] : this.defaults[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]); }, /** @@ -148,63 +138,49 @@ Deluge.OptionsManager = Ext.extend(Ext.util.Observable, { }, /** - * Check to see if an id has had an option set to something other than the - * default value. - * @param {String} id + * Check to see if an option exists in the options manager * @param {String} option - * @returns {Boolean} true if the id has an option, else false. + * @returns {Boolean} true if the option exists, else false. */ - hasOption: function(id, option) { - return (this.options[id] && !Ext.isEmpty(this.options[id][option])); + has: function(option) { + return (this.defaults[option]); }, /** - * Reset the options back to the default values for the specified id. + * Reset the options back to the default values. * @param {String} id */ - reset: function(id) { - if (!this.changed[id]) return; - delete this.changed[id]; + reset: function() { + this.changed = {}; }, /** * 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 */ - set: function(id, option, value) { - if (typeof value === undefined) { - for (var key in option) { - this.set(id, key, option[key]); - } - } else { - if (!this.options[id]) this.options[id] = {}; - this.options[id][option] = value; - } + set: function(option, value) { + this.options[option] = value; }, /** * 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(id, option, value) { + update: function(option, value) { if (typeof value === undefined) { for (var key in option) { - this.update(id, key, option[key]); + this.update(key, option[key]); } } else { - if (!this.changed[id]) this.changed[id] = {}; - - var oldValue = this.get(id, option); + var oldValue = this.get(option); if (oldValue == value) return; - var defaultValue = this.getDefault(id, option); + var defaultValue = this.getDefault(option); if (defaultValue == value) { - if (this.hasChanged(id, option)) delete this.changed[id][option]; - this.fireEvent('changed', id, option, value, oldValue); + if (this.isDirty(option)) delete this.changed[option]; + this.fireEvent('changed', option, value, oldValue); return; } @@ -221,9 +197,9 @@ Deluge.OptionsManager = Ext.extend(Ext.util.Observable, { break; } } - - this.changed[id][option] = value; - this.fireEvent('changed', id, option, value, oldValue); + + this.changed[option] = value; + this.fireEvent('changed', option, value, oldValue); } }, @@ -236,14 +212,14 @@ Deluge.OptionsManager = Ext.extend(Ext.util.Observable, { */ onFieldChange: function(field) { var option = this.binds[field]; - this.update(this.currentId, option, field.getValue()); + this.update(option, field.getValue()); }, - onChange: function(id, option, newValue, oldValue) { + onChange: function(option, newValue, oldValue) { // If we don't have a bind there's nothing to do. if (Ext.isEmpty(this.binds[option])) return; // Set the form field to the new value. this.binds[option].setValue(newValue); } -}); +}); \ No newline at end of file diff --git a/deluge/ui/web/js/Deluge.Preferences.Downloads.js b/deluge/ui/web/js/Deluge.Preferences.Downloads.js index 3be766e08..7661bc522 100644 --- a/deluge/ui/web/js/Deluge.Preferences.Downloads.js +++ b/deluge/ui/web/js/Deluge.Preferences.Downloads.js @@ -15,6 +15,7 @@ this.fieldsets = {} this.fields = {}; + var optMan = Deluge.Preferences.getOptionsManager(); this.fieldsets['folders'] = this.add({ xtype: 'fieldset', border: false, @@ -51,8 +52,8 @@ name: 'compact_allocation', labelSeparator: '', items: [ - {boxLabel: _('Compact'), value: 'true'}, - {boxLabel: _('Full'), value: 'false',style: 'margin-right: 10px;'} + {boxLabel: _('Compact') + ' ', value: 'true'}, + {boxLabel: _('Full'), value: 'false'} ] }); diff --git a/deluge/ui/web/js/Deluge.Preferences.js b/deluge/ui/web/js/Deluge.Preferences.js index e61c3b45e..878930d7a 100644 --- a/deluge/ui/web/js/Deluge.Preferences.js +++ b/deluge/ui/web/js/Deluge.Preferences.js @@ -94,6 +94,8 @@ Copyright: Ext.deluge.PreferencesWindow.superclass.initComponent.call(this); this.categoriesGrid = this.items.get(0); this.configPanel = this.items.get(1); + this.optionsManager = new Deluge.OptionsManager(); + this.pages = {}; this.on('show', this.onShow, this); }, @@ -111,6 +113,14 @@ Copyright: this.pages[name].hide(); }, + /** + * Return the options manager for the preferences window. + * @returns {Deluge.OptionsManager} the options manager + */ + getOptionsManager: function() { + return this.optionsManager; + }, + onPageSelect: function(selModel, rowIndex, r) { if (this.currentPage) { this.currentPage.hide(); diff --git a/deluge/ui/web/server.py b/deluge/ui/web/server.py index 609b40c32..f8b7bd247 100644 --- a/deluge/ui/web/server.py +++ b/deluge/ui/web/server.py @@ -278,6 +278,7 @@ class TopLevel(resource.Resource): "/js/Deluge.Menus.js", "/js/Deluge.Events.js", "/js/Deluge.OptionsManager.js", + "/js/Deluge.MultiOptionsManager.js", "/js/Deluge.Add.js", "/js/Deluge.Add.File.js", "/js/Deluge.Add.Url.js",