diff --git a/deluge/ui/webui/webui_plugin/config.py b/deluge/ui/webui/webui_plugin/config.py index d8b6f5ae1..b590e9b25 100644 --- a/deluge/ui/webui/webui_plugin/config.py +++ b/deluge/ui/webui/webui_plugin/config.py @@ -31,7 +31,7 @@ # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. -import lib.newforms as forms +import lib.newforms_plus as forms import page_decorators as deco import lib.webpy022 as web from webserver_common import ws @@ -43,37 +43,7 @@ import os groups = [] blocks = forms.utils.datastructures.SortedDict() -class Form(forms.Form): - info = "" - title = "No Title" - def __init__(self,data = None): - if data == None: - data = self.initial_data() - forms.Form.__init__(self,data) - - def initial_data(self): - "override in subclass" - return None - - def start_save(self): - "called by config_page" - data = web.Storage(self.clean_data) - self.validate(data) - self.save(data) - self.post_save() - - def save(self, vars): - "override in subclass" - raise NotImplementedError() - - def post_save(self): - pass - - def validate(self, data): - pass - - -class WebCfgForm(Form): +class WebCfgForm(forms.Form): "config base for webui" def initial_data(self): return ws.config @@ -82,7 +52,7 @@ class WebCfgForm(Form): ws.config.update(data) ws.save_config() -class CookieCfgForm(Form): +class CookieCfgForm(forms.Form): "config base for webui" def initial_data(self): return ws.config @@ -92,85 +62,13 @@ class CookieCfgForm(Form): ws.save_config() -class CfgForm(Form): +class CfgForm(forms.Form): "config base for deluge-cfg" def initial_data(self): return ws.proxy.get_config() def save(self, data): ws.proxy.set_config(dict(data)) - -#convenience Input Fields. -class _IntInput(forms.TextInput): - """ - because deluge-floats are edited as ints. - """ - def render(self, name, value, attrs=None): - try: - value = int(float(value)) - if value == -1: - value = _("Unlimited") - except: - pass - return forms.TextInput.render(self, name, value, attrs) - -class CheckBox(forms.BooleanField): - "Non Required ChoiceField" - def __init__(self,label, **kwargs): - forms.BooleanField.__init__(self,label=label,required=False,**kwargs) - -class IntCombo(forms.ChoiceField): - """ - choices are the display-values - returns int for the chosen display-value. - """ - def __init__(self, label, choices, **kwargs): - forms.ChoiceField.__init__(self, label=label, - choices=enumerate(choices), **kwargs) - - def clean(self, value): - return int(forms.ChoiceField.clean(self, value)) - -class DelugeInt(forms.IntegerField): - def __init__(self, label , **kwargs): - forms.IntegerField.__init__(self, label=label, min_value=-1, - max_value=sys.maxint, widget=_IntInput, **kwargs) - - def clean(self, value): - if str(value).lower() == _('Unlimited').lower(): - value = -1 - return int(forms.IntegerField.clean(self, value)) - -class DelugeFloat(DelugeInt): - def clean(self, value): - return int(DelugeInt.clean(self, value)) - -class MultipleChoice(forms.MultipleChoiceField): - #temp/test - def __init__(self, label, choices, **kwargs): - forms.MultipleChoiceField.__init__(self, label=label, choices=choices, - widget=forms.CheckboxSelectMultiple, required=False) - -class ServerFolder(forms.CharField): - def __init__(self, label, **kwargs): - forms.CharField.__init__(self, label=label,**kwargs) - - def clean(self, value): - value = value.rstrip('/').rstrip('\\') - self.validate(value) - return forms.CharField.clean(self, value) - - def validate(self, value): - if (value and not os.path.isdir(value)): - raise forms.ValidationError(_("This folder does not exist.")) - -class Password(forms.CharField): - def __init__(self, label, **kwargs): - forms.CharField.__init__(self, label=label, widget=forms.PasswordInput, - **kwargs) - -#/fields - class config_page: """ web.py config page diff --git a/deluge/ui/webui/webui_plugin/config_tabs_deluge.py b/deluge/ui/webui/webui_plugin/config_tabs_deluge.py index e8489e79b..092732db8 100644 --- a/deluge/ui/webui/webui_plugin/config_tabs_deluge.py +++ b/deluge/ui/webui/webui_plugin/config_tabs_deluge.py @@ -31,7 +31,7 @@ # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. -import lib.newforms as forms +import lib.newforms_plus as forms import config import utils from webserver_common import ws @@ -42,7 +42,7 @@ class NetworkPorts(config.CfgForm ): info = _("Restart daemon after changing these values.") _port_from = forms.IntegerField(_("From")) _port_to = forms.IntegerField(_("To")) - random_port = config.CheckBox(_("Random")) + random_port = forms.CheckBox(_("Random")) def initial_data(self): data = config.CfgForm.initial_data(self) @@ -63,24 +63,24 @@ config.register_block('network','ports', NetworkPorts) class NetworkExtra(config.CfgForm ): title = _("Extra's") - dht = config.CheckBox(_("Mainline DHT")) - upnp = config.CheckBox(_("UpNP")) - natpmp = config.CheckBox(_("NAT-PMP")) - utpex = config.CheckBox(_("Peer-Exchange")) - lsd = config.CheckBox(_("LSD")) + dht = forms.CheckBox(_("Mainline DHT")) + upnp = forms.CheckBox(_("UpNP")) + natpmp = forms.CheckBox(_("NAT-PMP")) + utpex = forms.CheckBox(_("Peer-Exchange")) + lsd = forms.CheckBox(_("LSD")) config.register_block('network','extra', NetworkExtra) class NetworkEnc(config.CfgForm ): title = _("Encryption") - _enc_choices = [_("Forced"),_("Enabled"),_("Disabled")] - _level_choices = [_("Handshake"), _("Full") , _("Either")] + _enc_choices = list(enumerate([_("Forced"),_("Enabled"),_("Disabled")])) + _level_choices = list(enumerate([_("Handshake"), _("Full") , _("Either")])) - enc_in_policy = config.IntCombo(_("Inbound"), _enc_choices) - enc_out_policy = config.IntCombo(_("Outbound"), _enc_choices) - enc_level = config.IntCombo(_("Level"), _level_choices) - enc_prefer_rc4 = config.CheckBox("Prefer to encrypt entire stream") + enc_in_policy = forms.IntChoiceField(_("Inbound"), _enc_choices) + enc_out_policy = forms.IntChoiceField(_("Outbound"), _enc_choices) + enc_level = forms.IntChoiceField(_("Level"), _level_choices) + enc_prefer_rc4 = forms.CheckBox("Prefer to encrypt entire stream") config.register_block('network','encryption', NetworkEnc) @@ -88,44 +88,45 @@ config.register_block('network','encryption', NetworkEnc) class BandwithGlobal(config.CfgForm): title = _("Global") info = _("-1 = Unlimited") - max_connections_global = config.DelugeInt(_("Maximum Connections")) - max_download_speed = config.DelugeFloat(_("Maximum Download Speed (Kib/s)")) - max_upload_speed = config.DelugeFloat(_("Maximum Upload Speed (Kib/s)")) - max_upload_slots_global = config.DelugeInt(_("Maximum Upload Slots")) + max_connections_global = forms.DelugeInt(_("Maximum Connections")) + max_download_speed = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)")) + max_upload_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)")) + max_upload_slots_global = forms.DelugeInt(_("Maximum Upload Slots")) config.register_block('bandwidth','global', BandwithGlobal) class BandwithTorrent(config.CfgForm): title = _("Per Torrent") info = _("-1 = Unlimited") - max_connections_per_torrent = config.DelugeInt(_("Maximum Connections")) - max_upload_slots_per_torrent = config.DelugeInt(_("Maximum Upload Slots")) + max_connections_per_torrent = forms.DelugeInt(_("Maximum Connections")) + max_upload_slots_per_torrent = forms.DelugeInt(_("Maximum Upload Slots")) config.register_block('bandwidth','torrent', BandwithTorrent) class Download(config.CfgForm): title = _("Download") - download_location = config.ServerFolder(_("Store all downoads in")) - torrentfiles_location = config.ServerFolder(_("Save .torrent files to")) - autoadd_location = config.ServerFolder(_("Auto Add folder"), required=False) - compact_allocation = config.CheckBox(_('Use Compact Allocation')) - prioritize_first_last_pieces = config.CheckBox( + download_location = forms.ServerFolder(_("Store all downoads in")) + torrentfiles_location = forms.ServerFolder(_("Save .torrent files to")) + autoadd_location = forms.ServerFolder(_("Auto Add folder"), required=False) + compact_allocation = forms.CheckBox(_('Use Compact Allocation')) + prioritize_first_last_pieces = forms.CheckBox( _('Prioritize first and last pieces')) config.register_block('deluge','download', Download) class Daemon(config.CfgForm): title = _("Daemon") + info = _("Restart daemon and webui after changing these settings") daemon_port = forms.IntegerField(_("Port")) - allow_remote = config.CheckBox(_("Allow Remote Connections")) + allow_remote = forms.CheckBox(_("Allow Remote Connections")) config.register_block('deluge','daemon', Daemon) -class Plugins(config.Form): +class Plugins(forms.Form): title = _("Enabled Plugins") _choices = [(p,p) for p in ws.proxy.get_available_plugins()] - enabled_plugins = config.MultipleChoice(_(""), _choices) + enabled_plugins = forms.MultipleChoice(_(""), _choices) def initial_data(self): return {'enabled_plugins':ws.proxy.get_enabled_plugins()} @@ -136,19 +137,19 @@ class Plugins(config.Form): config.register_block('deluge','plugins', Plugins) -class Queue(config.Form): +class Queue(forms.Form): title = _("Queue") info = _("queue-cfg not finished") - queue_top = config.CheckBox(_("Queue new torrents to top")) - total_active = config.DelugeInt(_("Total active torrents")) - total_seeding = config.DelugeInt(_("Total active seeding")) - total_downloading = config.DelugeInt(_("Total active downloading")) + queue_top = forms.CheckBox(_("Queue new torrents to top")) + total_active = forms.DelugeInt(_("Total active torrents")) + total_seeding = forms.DelugeInt(_("Total active seeding")) + total_downloading = forms.DelugeInt(_("Total active downloading")) - queue_bottom = config.CheckBox(_("Queue completed torrents to bottom")) - stop_on_ratio = config.CheckBox(_("Stop seeding when ratio reaches")) - stop_ratio = config.DelugeInt(_("TODO:float-edit-box")) - remove_after_stop = config.CheckBox(_("Remve torrent when ratio reached")) + queue_bottom = forms.CheckBox(_("Queue completed torrents to bottom")) + stop_on_ratio = forms.CheckBox(_("Stop seeding when ratio reaches")) + stop_ratio = forms.DelugeInt(_("TODO:float-edit-box")) + remove_after_stop = forms.CheckBox(_("Remve torrent when ratio reached")) def save(self, value): raise forms.ValidationError("SAVE:TODO") diff --git a/deluge/ui/webui/webui_plugin/config_tabs_webui.py b/deluge/ui/webui/webui_plugin/config_tabs_webui.py index 5937ca699..f61aa8fa1 100644 --- a/deluge/ui/webui/webui_plugin/config_tabs_webui.py +++ b/deluge/ui/webui/webui_plugin/config_tabs_webui.py @@ -31,7 +31,7 @@ # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. -import lib.newforms as forms +import lib.newforms_plus as forms import config import utils from webserver_common import ws @@ -41,11 +41,12 @@ class Template(config.WebCfgForm): title = _("Template") _templates = [(t,t) for t in ws.get_templates()] - _button_choices = [_('Text and image'), _('Image Only'), _('Text Only')] + _button_choices = enumerate([_('Text and image'), _('Image Only') + , _('Text Only')]) template = forms.ChoiceField( label=_("Template"), choices = _templates) - button_style = config.IntCombo(_("Button style"),_button_choices) - cache_templates = config.CheckBox(_("Cache templates")) + button_style = forms.IntChoiceField(_("Button style"),_button_choices) + cache_templates = forms.CheckBox(_("Cache templates")) def post_save(self): from render import render @@ -62,7 +63,7 @@ class Server(config.WebCfgForm): port = forms.IntegerField(label = _("Port"),min_value=80) - use_https = config.CheckBox(_("Use https")) + use_https = forms.CheckBox(_("Use https")) def post_save(self): @@ -70,12 +71,12 @@ class Server(config.WebCfgForm): #raise forms.ValidationError( # _("Manually restart server to apply these changes.")) -class Password(config.Form): +class Password(forms.Form): title = _("Password") - old_pwd = config.Password(_("Current Password")) - new1 = config.Password(_("New Password")) - new2 = config.Password(_("New Password (Confirm)")) + old_pwd = forms.Password(_("Current Password")) + new1 = forms.Password(_("New Password")) + new2 = forms.Password(_("New Password (Confirm)")) def save(self,data): ws.update_pwd(data.new1) diff --git a/deluge/ui/webui/webui_plugin/lib/newforms/forms.py b/deluge/ui/webui/webui_plugin/lib/newforms/forms.py index 97f0efcb6..df4af3b54 100644 --- a/deluge/ui/webui/webui_plugin/lib/newforms/forms.py +++ b/deluge/ui/webui/webui_plugin/lib/newforms/forms.py @@ -9,7 +9,7 @@ from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput from util import flatatt, StrAndUnicode, ErrorDict, ErrorList, ValidationError import copy -__all__ = ('BaseForm', 'Form') +#__all__ = ('BaseForm', 'Form') NON_FIELD_ERRORS = '__all__' diff --git a/deluge/ui/webui/webui_plugin/lib/newforms_plus.py b/deluge/ui/webui/webui_plugin/lib/newforms_plus.py new file mode 100644 index 000000000..e11c56b4d --- /dev/null +++ b/deluge/ui/webui/webui_plugin/lib/newforms_plus.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) Martijn Voncken 2008 +# Django Lisence, see ./newforms/LICENCE +# + +from newforms import * +import newforms +from newforms.forms import BoundField + +import sys, os + + +import webpy022 as web #todo:remove this dependency. + +#Form +class FilteredForm(newforms.Form): + """ + used to enable more complex layouts. + the filter argument contains the names of the fields to render. + """ + def _html_output_filtered(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row, filter): + """ + Helper function for outputting HTML. Used by as_table(), as_ul(), as_p(). + newforms_plus: 99% c&p from newforms, added filter. + """ + top_errors = self.non_field_errors() # Errors that should be displayed above all fields. + output, hidden_fields = [], [] + for name, field in self.fields.items(): + #FilteredForm + if (filter != None) and (not name in filter): + continue + #/FilteredForm + bf = BoundField(self, field, name) + bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable. + if bf.is_hidden: + if bf_errors: + top_errors.extend(['(Hidden field %s) %s' % (name, e) for e in bf_errors]) + hidden_fields.append(unicode(bf)) + else: + if errors_on_separate_row and bf_errors: + output.append(error_row % bf_errors) + label = bf.label and bf.label_tag(escape(bf.label + ':')) or '' + if field.help_text: + help_text = help_text_html % field.help_text + else: + help_text = u'' + output.append(normal_row % {'errors': bf_errors, 'label': label, 'field': unicode(bf), 'help_text': help_text}) + if top_errors: + output.insert(0, error_row % top_errors) + if hidden_fields: # Insert any hidden fields in the last row. + str_hidden = u''.join(hidden_fields) + if output: + last_row = output[-1] + # Chop off the trailing row_ender (e.g. '') and insert the hidden fields. + output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender + else: # If there aren't any rows in the output, just append the hidden fields. + output.append(str_hidden) + return u'\n'.join(output) + + def as_table(self , filter = None): + "Returns this form rendered as HTML s -- excluding the
." + return self._html_output_filtered(u'%(label)s%(errors)s%(field)s%(help_text)s', u'%s', '', u'
%s', False, filter) + + def as_ul(self, filter = None): + "Returns this form rendered as HTML
  • s -- excluding the ." + return self._html_output_filtered(u'
  • %(errors)s%(label)s %(field)s%(help_text)s
  • ', u'
  • %s
  • ', '', u' %s', False , filter) + + def as_p(self , filter = None): + "Returns this form rendered as HTML

    s." + return self._html_output_filtered(u'

    %(label)s %(field)s%(help_text)s

    ', u'

    %s

    ', '

    ', u' %s', True, filter) + +class Form(newforms.Form): + info = "" + title = "No Title" + def __init__(self,data = None): + if data == None: + data = self.initial_data() + newforms.Form.__init__(self,data) + + def initial_data(self): + "override in subclass" + return None + + def start_save(self): + "called by config_page" + data = web.Storage(self.clean_data) + self.validate(data) + self.save(data) + self.post_save() + + def save(self, vars): + "override in subclass" + raise NotImplementedError() + + def post_save(self): + pass + + def validate(self, data): + pass + + +#convenience Input Fields. +class CheckBox(newforms.BooleanField): + "Non Required BooleanField,why the f is it required by default?" + def __init__(self,label, **kwargs): + newforms.BooleanField.__init__(self,label=label,required=False,**kwargs) + +class IntChoiceField(newforms.ChoiceField): + """same as ChoiceField, but returns an int + hint : Use IntChoiceField(choices=enumerate("list","of","strings"])) + for index-based values on a list of strings. + """ + def __init__(self, label, choices, **kwargs): + newforms.ChoiceField.__init__(self, label=label, choices=choices,**kwargs) + + def clean(self, value): + return int(newforms.ChoiceField.clean(self, value)) + +class MultipleChoice(newforms.MultipleChoiceField): + #temp/test/debug!! + "Non Required MultipleChoiceField,why the f is it required by default?" + def __init__(self, label, choices, **kwargs): + newforms.MultipleChoiceField.__init__(self, label=label, choices=choices, + widget=newforms.CheckboxSelectMultiple, required=False) + +class ServerFolder(newforms.CharField): + def __init__(self, label, **kwargs): + newforms.CharField.__init__(self, label=label,**kwargs) + + def clean(self, value): + value = value.rstrip('/').rstrip('\\') + self.validate(value) + return newforms.CharField.clean(self, value) + + def validate(self, value): + if (value and not os.path.isdir(value)): + raise newforms.ValidationError(_("This folder does not exist.")) + +class Password(newforms.CharField): + def __init__(self, label, **kwargs): + newforms.CharField.__init__(self, label=label, widget=newforms.PasswordInput, + **kwargs) + +#Deluge specific: +class _DelugeIntInput(newforms.TextInput): + """ + because deluge-floats are edited as ints. + """ + def render(self, name, value, attrs=None): + try: + value = int(float(value)) + if value == -1: + value = _("Unlimited") + except: + pass + return newforms.TextInput.render(self, name, value, attrs) + +class DelugeInt(newforms.IntegerField): + def __init__(self, label , **kwargs): + newforms.IntegerField.__init__(self, label=label, min_value=-1, + max_value=sys.maxint, widget=_DelugeIntInput, **kwargs) + + def clean(self, value): + if str(value).lower() == _('Unlimited').lower(): + value = -1 + return int(newforms.IntegerField.clean(self, value)) + +class DelugeFloat(DelugeInt): + def clean(self, value): + return int(DelugeInt.clean(self, value)) + +#/fields + + + + + diff --git a/deluge/ui/webui/webui_plugin/templates/advanced/index.html b/deluge/ui/webui/webui_plugin/templates/advanced/index.html index a77d31073..e5684560e 100644 --- a/deluge/ui/webui/webui_plugin/templates/advanced/index.html +++ b/deluge/ui/webui/webui_plugin/templates/advanced/index.html @@ -55,7 +55,7 @@ $for t in torrent_list:
    - +
    $:(sort_head('calc_state_str', 'S'))