mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-02 22:48:40 +00:00
refactor forms
This commit is contained in:
parent
d32ffa7ace
commit
9df4492083
6 changed files with 231 additions and 153 deletions
|
@ -31,7 +31,7 @@
|
||||||
# this exception statement from your version. If you delete this exception
|
# this exception statement from your version. If you delete this exception
|
||||||
# statement from all source files in the program, then also delete it here.
|
# 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 page_decorators as deco
|
||||||
import lib.webpy022 as web
|
import lib.webpy022 as web
|
||||||
from webserver_common import ws
|
from webserver_common import ws
|
||||||
|
@ -43,37 +43,7 @@ import os
|
||||||
groups = []
|
groups = []
|
||||||
blocks = forms.utils.datastructures.SortedDict()
|
blocks = forms.utils.datastructures.SortedDict()
|
||||||
|
|
||||||
class Form(forms.Form):
|
class WebCfgForm(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):
|
|
||||||
"config base for webui"
|
"config base for webui"
|
||||||
def initial_data(self):
|
def initial_data(self):
|
||||||
return ws.config
|
return ws.config
|
||||||
|
@ -82,7 +52,7 @@ class WebCfgForm(Form):
|
||||||
ws.config.update(data)
|
ws.config.update(data)
|
||||||
ws.save_config()
|
ws.save_config()
|
||||||
|
|
||||||
class CookieCfgForm(Form):
|
class CookieCfgForm(forms.Form):
|
||||||
"config base for webui"
|
"config base for webui"
|
||||||
def initial_data(self):
|
def initial_data(self):
|
||||||
return ws.config
|
return ws.config
|
||||||
|
@ -92,85 +62,13 @@ class CookieCfgForm(Form):
|
||||||
ws.save_config()
|
ws.save_config()
|
||||||
|
|
||||||
|
|
||||||
class CfgForm(Form):
|
class CfgForm(forms.Form):
|
||||||
"config base for deluge-cfg"
|
"config base for deluge-cfg"
|
||||||
def initial_data(self):
|
def initial_data(self):
|
||||||
return ws.proxy.get_config()
|
return ws.proxy.get_config()
|
||||||
def save(self, data):
|
def save(self, data):
|
||||||
ws.proxy.set_config(dict(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:
|
class config_page:
|
||||||
"""
|
"""
|
||||||
web.py config page
|
web.py config page
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
# this exception statement from your version. If you delete this exception
|
# this exception statement from your version. If you delete this exception
|
||||||
# statement from all source files in the program, then also delete it here.
|
# 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 config
|
||||||
import utils
|
import utils
|
||||||
from webserver_common import ws
|
from webserver_common import ws
|
||||||
|
@ -42,7 +42,7 @@ class NetworkPorts(config.CfgForm ):
|
||||||
info = _("Restart daemon after changing these values.")
|
info = _("Restart daemon after changing these values.")
|
||||||
_port_from = forms.IntegerField(_("From"))
|
_port_from = forms.IntegerField(_("From"))
|
||||||
_port_to = forms.IntegerField(_("To"))
|
_port_to = forms.IntegerField(_("To"))
|
||||||
random_port = config.CheckBox(_("Random"))
|
random_port = forms.CheckBox(_("Random"))
|
||||||
|
|
||||||
def initial_data(self):
|
def initial_data(self):
|
||||||
data = config.CfgForm.initial_data(self)
|
data = config.CfgForm.initial_data(self)
|
||||||
|
@ -63,24 +63,24 @@ config.register_block('network','ports', NetworkPorts)
|
||||||
|
|
||||||
class NetworkExtra(config.CfgForm ):
|
class NetworkExtra(config.CfgForm ):
|
||||||
title = _("Extra's")
|
title = _("Extra's")
|
||||||
dht = config.CheckBox(_("Mainline DHT"))
|
dht = forms.CheckBox(_("Mainline DHT"))
|
||||||
upnp = config.CheckBox(_("UpNP"))
|
upnp = forms.CheckBox(_("UpNP"))
|
||||||
natpmp = config.CheckBox(_("NAT-PMP"))
|
natpmp = forms.CheckBox(_("NAT-PMP"))
|
||||||
utpex = config.CheckBox(_("Peer-Exchange"))
|
utpex = forms.CheckBox(_("Peer-Exchange"))
|
||||||
lsd = config.CheckBox(_("LSD"))
|
lsd = forms.CheckBox(_("LSD"))
|
||||||
|
|
||||||
config.register_block('network','extra', NetworkExtra)
|
config.register_block('network','extra', NetworkExtra)
|
||||||
|
|
||||||
class NetworkEnc(config.CfgForm ):
|
class NetworkEnc(config.CfgForm ):
|
||||||
title = _("Encryption")
|
title = _("Encryption")
|
||||||
|
|
||||||
_enc_choices = [_("Forced"),_("Enabled"),_("Disabled")]
|
_enc_choices = list(enumerate([_("Forced"),_("Enabled"),_("Disabled")]))
|
||||||
_level_choices = [_("Handshake"), _("Full") , _("Either")]
|
_level_choices = list(enumerate([_("Handshake"), _("Full") , _("Either")]))
|
||||||
|
|
||||||
enc_in_policy = config.IntCombo(_("Inbound"), _enc_choices)
|
enc_in_policy = forms.IntChoiceField(_("Inbound"), _enc_choices)
|
||||||
enc_out_policy = config.IntCombo(_("Outbound"), _enc_choices)
|
enc_out_policy = forms.IntChoiceField(_("Outbound"), _enc_choices)
|
||||||
enc_level = config.IntCombo(_("Level"), _level_choices)
|
enc_level = forms.IntChoiceField(_("Level"), _level_choices)
|
||||||
enc_prefer_rc4 = config.CheckBox("Prefer to encrypt entire stream")
|
enc_prefer_rc4 = forms.CheckBox("Prefer to encrypt entire stream")
|
||||||
|
|
||||||
config.register_block('network','encryption', NetworkEnc)
|
config.register_block('network','encryption', NetworkEnc)
|
||||||
|
|
||||||
|
@ -88,44 +88,45 @@ config.register_block('network','encryption', NetworkEnc)
|
||||||
class BandwithGlobal(config.CfgForm):
|
class BandwithGlobal(config.CfgForm):
|
||||||
title = _("Global")
|
title = _("Global")
|
||||||
info = _("-1 = Unlimited")
|
info = _("-1 = Unlimited")
|
||||||
max_connections_global = config.DelugeInt(_("Maximum Connections"))
|
max_connections_global = forms.DelugeInt(_("Maximum Connections"))
|
||||||
max_download_speed = config.DelugeFloat(_("Maximum Download Speed (Kib/s)"))
|
max_download_speed = forms.DelugeFloat(_("Maximum Download Speed (Kib/s)"))
|
||||||
max_upload_speed = config.DelugeFloat(_("Maximum Upload Speed (Kib/s)"))
|
max_upload_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)"))
|
||||||
max_upload_slots_global = config.DelugeInt(_("Maximum Upload Slots"))
|
max_upload_slots_global = forms.DelugeInt(_("Maximum Upload Slots"))
|
||||||
|
|
||||||
config.register_block('bandwidth','global', BandwithGlobal)
|
config.register_block('bandwidth','global', BandwithGlobal)
|
||||||
|
|
||||||
class BandwithTorrent(config.CfgForm):
|
class BandwithTorrent(config.CfgForm):
|
||||||
title = _("Per Torrent")
|
title = _("Per Torrent")
|
||||||
info = _("-1 = Unlimited")
|
info = _("-1 = Unlimited")
|
||||||
max_connections_per_torrent = config.DelugeInt(_("Maximum Connections"))
|
max_connections_per_torrent = forms.DelugeInt(_("Maximum Connections"))
|
||||||
max_upload_slots_per_torrent = config.DelugeInt(_("Maximum Upload Slots"))
|
max_upload_slots_per_torrent = forms.DelugeInt(_("Maximum Upload Slots"))
|
||||||
|
|
||||||
config.register_block('bandwidth','torrent', BandwithTorrent)
|
config.register_block('bandwidth','torrent', BandwithTorrent)
|
||||||
|
|
||||||
|
|
||||||
class Download(config.CfgForm):
|
class Download(config.CfgForm):
|
||||||
title = _("Download")
|
title = _("Download")
|
||||||
download_location = config.ServerFolder(_("Store all downoads in"))
|
download_location = forms.ServerFolder(_("Store all downoads in"))
|
||||||
torrentfiles_location = config.ServerFolder(_("Save .torrent files to"))
|
torrentfiles_location = forms.ServerFolder(_("Save .torrent files to"))
|
||||||
autoadd_location = config.ServerFolder(_("Auto Add folder"), required=False)
|
autoadd_location = forms.ServerFolder(_("Auto Add folder"), required=False)
|
||||||
compact_allocation = config.CheckBox(_('Use Compact Allocation'))
|
compact_allocation = forms.CheckBox(_('Use Compact Allocation'))
|
||||||
prioritize_first_last_pieces = config.CheckBox(
|
prioritize_first_last_pieces = forms.CheckBox(
|
||||||
_('Prioritize first and last pieces'))
|
_('Prioritize first and last pieces'))
|
||||||
|
|
||||||
config.register_block('deluge','download', Download)
|
config.register_block('deluge','download', Download)
|
||||||
|
|
||||||
class Daemon(config.CfgForm):
|
class Daemon(config.CfgForm):
|
||||||
title = _("Daemon")
|
title = _("Daemon")
|
||||||
|
info = _("Restart daemon and webui after changing these settings")
|
||||||
daemon_port = forms.IntegerField(_("Port"))
|
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)
|
config.register_block('deluge','daemon', Daemon)
|
||||||
|
|
||||||
class Plugins(config.Form):
|
class Plugins(forms.Form):
|
||||||
title = _("Enabled Plugins")
|
title = _("Enabled Plugins")
|
||||||
_choices = [(p,p) for p in ws.proxy.get_available_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):
|
def initial_data(self):
|
||||||
return {'enabled_plugins':ws.proxy.get_enabled_plugins()}
|
return {'enabled_plugins':ws.proxy.get_enabled_plugins()}
|
||||||
|
@ -136,19 +137,19 @@ class Plugins(config.Form):
|
||||||
config.register_block('deluge','plugins', Plugins)
|
config.register_block('deluge','plugins', Plugins)
|
||||||
|
|
||||||
|
|
||||||
class Queue(config.Form):
|
class Queue(forms.Form):
|
||||||
title = _("Queue")
|
title = _("Queue")
|
||||||
info = _("queue-cfg not finished")
|
info = _("queue-cfg not finished")
|
||||||
|
|
||||||
queue_top = config.CheckBox(_("Queue new torrents to top"))
|
queue_top = forms.CheckBox(_("Queue new torrents to top"))
|
||||||
total_active = config.DelugeInt(_("Total active torrents"))
|
total_active = forms.DelugeInt(_("Total active torrents"))
|
||||||
total_seeding = config.DelugeInt(_("Total active seeding"))
|
total_seeding = forms.DelugeInt(_("Total active seeding"))
|
||||||
total_downloading = config.DelugeInt(_("Total active downloading"))
|
total_downloading = forms.DelugeInt(_("Total active downloading"))
|
||||||
|
|
||||||
queue_bottom = config.CheckBox(_("Queue completed torrents to bottom"))
|
queue_bottom = forms.CheckBox(_("Queue completed torrents to bottom"))
|
||||||
stop_on_ratio = config.CheckBox(_("Stop seeding when ratio reaches"))
|
stop_on_ratio = forms.CheckBox(_("Stop seeding when ratio reaches"))
|
||||||
stop_ratio = config.DelugeInt(_("TODO:float-edit-box"))
|
stop_ratio = forms.DelugeInt(_("TODO:float-edit-box"))
|
||||||
remove_after_stop = config.CheckBox(_("Remve torrent when ratio reached"))
|
remove_after_stop = forms.CheckBox(_("Remve torrent when ratio reached"))
|
||||||
|
|
||||||
def save(self, value):
|
def save(self, value):
|
||||||
raise forms.ValidationError("SAVE:TODO")
|
raise forms.ValidationError("SAVE:TODO")
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
# this exception statement from your version. If you delete this exception
|
# this exception statement from your version. If you delete this exception
|
||||||
# statement from all source files in the program, then also delete it here.
|
# 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 config
|
||||||
import utils
|
import utils
|
||||||
from webserver_common import ws
|
from webserver_common import ws
|
||||||
|
@ -41,11 +41,12 @@ class Template(config.WebCfgForm):
|
||||||
title = _("Template")
|
title = _("Template")
|
||||||
|
|
||||||
_templates = [(t,t) for t in ws.get_templates()]
|
_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)
|
template = forms.ChoiceField( label=_("Template"), choices = _templates)
|
||||||
button_style = config.IntCombo(_("Button style"),_button_choices)
|
button_style = forms.IntChoiceField(_("Button style"),_button_choices)
|
||||||
cache_templates = config.CheckBox(_("Cache templates"))
|
cache_templates = forms.CheckBox(_("Cache templates"))
|
||||||
|
|
||||||
def post_save(self):
|
def post_save(self):
|
||||||
from render import render
|
from render import render
|
||||||
|
@ -62,7 +63,7 @@ class Server(config.WebCfgForm):
|
||||||
|
|
||||||
port = forms.IntegerField(label = _("Port"),min_value=80)
|
port = forms.IntegerField(label = _("Port"),min_value=80)
|
||||||
|
|
||||||
use_https = config.CheckBox(_("Use https"))
|
use_https = forms.CheckBox(_("Use https"))
|
||||||
|
|
||||||
|
|
||||||
def post_save(self):
|
def post_save(self):
|
||||||
|
@ -70,12 +71,12 @@ class Server(config.WebCfgForm):
|
||||||
#raise forms.ValidationError(
|
#raise forms.ValidationError(
|
||||||
# _("Manually restart server to apply these changes."))
|
# _("Manually restart server to apply these changes."))
|
||||||
|
|
||||||
class Password(config.Form):
|
class Password(forms.Form):
|
||||||
title = _("Password")
|
title = _("Password")
|
||||||
|
|
||||||
old_pwd = config.Password(_("Current Password"))
|
old_pwd = forms.Password(_("Current Password"))
|
||||||
new1 = config.Password(_("New Password"))
|
new1 = forms.Password(_("New Password"))
|
||||||
new2 = config.Password(_("New Password (Confirm)"))
|
new2 = forms.Password(_("New Password (Confirm)"))
|
||||||
|
|
||||||
def save(self,data):
|
def save(self,data):
|
||||||
ws.update_pwd(data.new1)
|
ws.update_pwd(data.new1)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput
|
||||||
from util import flatatt, StrAndUnicode, ErrorDict, ErrorList, ValidationError
|
from util import flatatt, StrAndUnicode, ErrorDict, ErrorList, ValidationError
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
__all__ = ('BaseForm', 'Form')
|
#__all__ = ('BaseForm', 'Form')
|
||||||
|
|
||||||
NON_FIELD_ERRORS = '__all__'
|
NON_FIELD_ERRORS = '__all__'
|
||||||
|
|
||||||
|
|
178
deluge/ui/webui/webui_plugin/lib/newforms_plus.py
Normal file
178
deluge/ui/webui/webui_plugin/lib/newforms_plus.py
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) Martijn Voncken 2008 <mvoncken@gmail.com>
|
||||||
|
# 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. '</td></tr>') 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 <tr>s -- excluding the <table></table>."
|
||||||
|
return self._html_output_filtered(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False, filter)
|
||||||
|
|
||||||
|
def as_ul(self, filter = None):
|
||||||
|
"Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
|
||||||
|
return self._html_output_filtered(u'<li>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False , filter)
|
||||||
|
|
||||||
|
def as_p(self , filter = None):
|
||||||
|
"Returns this form rendered as HTML <p>s."
|
||||||
|
return self._html_output_filtered(u'<p>%(label)s %(field)s%(help_text)s</p>', u'<p>%s</p>', '</p>', 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ $for t in torrent_list:
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tableContainer" class="tableContainer">
|
<div id="tableContainer" class="tableContainer">
|
||||||
<table class="torrent_list" border=0 cellspacing=0 cellpadding=2 id="torrent_list">
|
<table class="torrent_list" border=0 cellspacing=0 cellpadding=2 id="torrent_list" >
|
||||||
<thead class="fixedHeader">
|
<thead class="fixedHeader">
|
||||||
<tr>
|
<tr>
|
||||||
$:(sort_head('calc_state_str', 'S'))
|
$:(sort_head('calc_state_str', 'S'))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue