mirror of
https://git.deluge-torrent.org/deluge
synced 2025-04-21 03:54:50 +00:00
webui-refactor:use deluge.component for components/prepare for plugins
This commit is contained in:
parent
1a5ebf73ee
commit
f1cd5071da
22 changed files with 377 additions and 518 deletions
|
@ -40,9 +40,9 @@ from lib.webpy022.http import seeother
|
|||
import sys
|
||||
import os
|
||||
import utils
|
||||
from deluge import component
|
||||
|
||||
groups = []
|
||||
blocks = forms.utils.datastructures.SortedDict()
|
||||
config_page_manager = component.get("ConfigPageManager")
|
||||
|
||||
class WebCfgForm(forms.Form):
|
||||
"config base for webui"
|
||||
|
@ -76,9 +76,9 @@ class config_page:
|
|||
"""
|
||||
def get_form_class(self,name):
|
||||
try:
|
||||
return blocks[name]
|
||||
return config_page_manager.blocks[name]
|
||||
except KeyError:
|
||||
raise Exception('no config page named:"%s"')
|
||||
raise Exception('no config page named:"%s"' % name)
|
||||
|
||||
@deco.deluge_page
|
||||
def GET(self, name):
|
||||
|
@ -109,18 +109,4 @@ class config_page:
|
|||
error= _('Correct the errors above and try again'))
|
||||
|
||||
def render(self, f , name , message = '' , error=''):
|
||||
return render.config(groups, blocks, f, name , message , error)
|
||||
|
||||
def register_block(group, name, form):
|
||||
if not group in groups:
|
||||
groups.append(group)
|
||||
form.group = group
|
||||
blocks[name] = form
|
||||
|
||||
def unregister_block(name):
|
||||
del blocks[name]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return render.config(config_page_manager.groups, config_page_manager.blocks, f, name , message , error)
|
58
deluge/ui/webui/config_page_manager.py
Normal file
58
deluge/ui/webui/config_page_manager.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) Martijn Voncken 2008 <mvoncken@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 2, 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.
|
||||
|
||||
|
||||
from utils import logcall
|
||||
from render import template
|
||||
from deluge import component
|
||||
import lib.newforms_plus as forms
|
||||
|
||||
class ConfigPageManager(component.Component):
|
||||
def __init__(self):
|
||||
component.Component.__init__(self, "ConfigPageManager")
|
||||
self.groups = []
|
||||
self.blocks = forms.utils.datastructures.SortedDict()
|
||||
|
||||
def register(self, group, name, form):
|
||||
if not group in self.groups:
|
||||
self.groups.append(group)
|
||||
form.group = group
|
||||
self.blocks[name] = form
|
||||
|
||||
def unregister(self, name):
|
||||
del self.blocks[name]
|
||||
|
||||
__config_page_manager = ConfigPageManager()
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -31,13 +31,16 @@
|
|||
# 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_plus as forms
|
||||
import config
|
||||
import utils
|
||||
from webserver_common import ws, proxy , log
|
||||
import lib.newforms_plus as forms
|
||||
import config_forms
|
||||
from deluge import component
|
||||
|
||||
config_page = component.get("ConfigPageManager")
|
||||
|
||||
|
||||
class NetworkPorts(config.CfgForm ):
|
||||
class NetworkPorts(config_forms.CfgForm ):
|
||||
title = _("Ports")
|
||||
info = _("Restart daemon after changing these values.")
|
||||
_port_from = forms.IntegerField(_("From"))
|
||||
|
@ -45,7 +48,7 @@ class NetworkPorts(config.CfgForm ):
|
|||
random_port = forms.CheckBox(_("Random"))
|
||||
|
||||
def initial_data(self):
|
||||
data = config.CfgForm.initial_data(self)
|
||||
data = config_forms.CfgForm.initial_data(self)
|
||||
data['_port_from'] , data['_port_to'] = data['listen_ports']
|
||||
return data
|
||||
|
||||
|
@ -53,15 +56,15 @@ class NetworkPorts(config.CfgForm ):
|
|||
data['listen_ports'] = [data['_port_from'] , data['_port_to'] ]
|
||||
del(data['_port_from'])
|
||||
del(data['_port_to'])
|
||||
config.CfgForm.save(self, data)
|
||||
config_forms.config.CfgForm.save(self, data)
|
||||
|
||||
def validate(self, data):
|
||||
if (data['_port_to'] < data['_port_from']):
|
||||
raise ValidationError('"Port from" must be greater than "Port to"')
|
||||
|
||||
config.register_block('network','ports', NetworkPorts)
|
||||
config_page.register('network','ports', NetworkPorts)
|
||||
|
||||
class NetworkExtra(config.CfgForm ):
|
||||
class NetworkExtra(config_forms.CfgForm ):
|
||||
title = _("Extra's")
|
||||
dht = forms.CheckBox(_("Mainline DHT"))
|
||||
upnp = forms.CheckBox(_("UpNP"))
|
||||
|
@ -69,9 +72,9 @@ class NetworkExtra(config.CfgForm ):
|
|||
utpex = forms.CheckBox(_("Peer-Exchange"))
|
||||
lsd = forms.CheckBox(_("LSD"))
|
||||
|
||||
config.register_block('network','extra', NetworkExtra)
|
||||
config_page.register('network','extra', NetworkExtra)
|
||||
|
||||
class NetworkEnc(config.CfgForm ):
|
||||
class NetworkEnc(config_forms.CfgForm ):
|
||||
title = _("Encryption")
|
||||
|
||||
_enc_choices = list(enumerate([_("Forced"),_("Enabled"),_("Disabled")]))
|
||||
|
@ -82,10 +85,10 @@ class NetworkEnc(config.CfgForm ):
|
|||
enc_level = forms.IntChoiceField(_("Level"), _level_choices)
|
||||
enc_prefer_rc4 = forms.CheckBox("Prefer to encrypt entire stream")
|
||||
|
||||
config.register_block('network','encryption', NetworkEnc)
|
||||
config_page.register('network','encryption', NetworkEnc)
|
||||
|
||||
|
||||
class BandwithGlobal(config.CfgForm):
|
||||
class BandwithGlobal(config_forms.CfgForm):
|
||||
title = _("Global")
|
||||
info = _("-1 = Unlimited")
|
||||
max_connections_global = forms.DelugeInt(_("Maximum Connections"))
|
||||
|
@ -93,18 +96,18 @@ class BandwithGlobal(config.CfgForm):
|
|||
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)
|
||||
config_page.register('bandwidth','global', BandwithGlobal)
|
||||
|
||||
class BandwithTorrent(config.CfgForm):
|
||||
class BandwithTorrent(config_forms.CfgForm):
|
||||
title = _("Per Torrent")
|
||||
info = _("-1 = Unlimited")
|
||||
max_connections_per_torrent = forms.DelugeInt(_("Maximum Connections"))
|
||||
max_upload_slots_per_torrent = forms.DelugeInt(_("Maximum Upload Slots"))
|
||||
|
||||
config.register_block('bandwidth','torrent', BandwithTorrent)
|
||||
config_page.register('bandwidth','torrent', BandwithTorrent)
|
||||
|
||||
|
||||
class Download(config.CfgForm):
|
||||
class Download(config_forms.CfgForm):
|
||||
title = _("Download")
|
||||
download_location = forms.ServerFolder(_("Store all downoads in"))
|
||||
torrentfiles_location = forms.ServerFolder(_("Save .torrent files to"))
|
||||
|
@ -113,15 +116,15 @@ class Download(config.CfgForm):
|
|||
prioritize_first_last_pieces = forms.CheckBox(
|
||||
_('Prioritize first and last pieces'))
|
||||
|
||||
config.register_block('deluge','download', Download)
|
||||
config_page.register('deluge','download', Download)
|
||||
|
||||
class Daemon(config.CfgForm):
|
||||
class Daemon(config_forms.CfgForm):
|
||||
title = _("Daemon")
|
||||
info = _("Restart daemon and webui after changing these settings")
|
||||
daemon_port = forms.IntegerField(_("Port"))
|
||||
allow_remote = forms.CheckBox(_("Allow Remote Connections"))
|
||||
|
||||
config.register_block('deluge','daemon', Daemon)
|
||||
config_page.register('deluge','daemon', Daemon)
|
||||
|
||||
class Plugins(forms.Form):
|
||||
title = _("Enabled Plugins")
|
||||
|
@ -139,9 +142,9 @@ class Plugins(forms.Form):
|
|||
def save(self, value):
|
||||
raise forms.ValidationError("SAVE:TODO")
|
||||
|
||||
config.register_block('deluge','plugins', Plugins)
|
||||
|
||||
config_page.register('deluge','plugins', Plugins)
|
||||
|
||||
"""
|
||||
class Queue(forms.Form):
|
||||
title = _("Queue")
|
||||
info = _("queue-cfg not finished")
|
||||
|
@ -159,4 +162,5 @@ class Queue(forms.Form):
|
|||
def save(self, value):
|
||||
raise forms.ValidationError("SAVE:TODO")
|
||||
|
||||
config.register_block('plugins','queue', Queue)
|
||||
config_page.register('plugins','queue', Queue)
|
||||
"""
|
|
@ -31,13 +31,17 @@
|
|||
# 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_plus as forms
|
||||
import config
|
||||
|
||||
import utils
|
||||
from webserver_common import ws
|
||||
from webserver_common import ws, log
|
||||
import lib.newforms_plus as forms
|
||||
import config_forms
|
||||
from deluge import component
|
||||
|
||||
config_page = component.get("ConfigPageManager")
|
||||
plugins = component.get("WebPluginManager")
|
||||
|
||||
class Template(config.WebCfgForm):
|
||||
class Template(config_forms.WebCfgForm):
|
||||
title = _("Template")
|
||||
|
||||
_templates = [(t,t) for t in ws.get_templates()]
|
||||
|
@ -52,20 +56,16 @@ class Template(config.WebCfgForm):
|
|||
from render import render
|
||||
render.apply_cfg()
|
||||
|
||||
|
||||
class Server(config.WebCfgForm):
|
||||
class Server(config_forms.WebCfgForm):
|
||||
title = _("Server")
|
||||
port = forms.IntegerField(label = _("Port"),min_value=80)
|
||||
use_https = forms.CheckBox(_("Use https"))
|
||||
|
||||
try:
|
||||
import OpenSSL
|
||||
except ImportError:
|
||||
info = _("pyopenssl not installed, install this for https.")
|
||||
|
||||
port = forms.IntegerField(label = _("Port"),min_value=80)
|
||||
|
||||
use_https = forms.CheckBox(_("Use https"))
|
||||
|
||||
|
||||
def post_save(self):
|
||||
pass
|
||||
#raise forms.ValidationError(
|
||||
|
@ -93,6 +93,21 @@ class Password(forms.Form):
|
|||
utils.end_session()
|
||||
#raise forms.ValidationError(_("Password changed,please login again"))
|
||||
|
||||
config.register_block('webui','template', Template)
|
||||
config.register_block('webui','server',Server)
|
||||
config.register_block('webui','password',Password)
|
||||
class WebUiPlugins(forms.Form):
|
||||
title = _("WebUi Plugins")
|
||||
|
||||
_choices = [(p,p) for p in plugins.get_available_plugins()]
|
||||
enabled_plugins = forms.MultipleChoice(_(""), _choices)
|
||||
|
||||
def initial_data(self):
|
||||
return {'enabled_plugins':plugins.get_enabled_plugins()}
|
||||
|
||||
def save(self, data):
|
||||
log.debug()
|
||||
for plugin_name in data['enabled_plugins']:
|
||||
plugins.enable_plugin(plugin_name)
|
||||
|
||||
config_page.register('webui','template', Template)
|
||||
config_page.register('webui','server',Server)
|
||||
config_page.register('webui','password',Password)
|
||||
config_page.register('webui','webuiplugins',WebUiPlugins)
|
||||
|
|
|
@ -1,283 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Dbus Ipc for experimental web interface
|
||||
#
|
||||
# dbus_interface.py
|
||||
#
|
||||
# Copyright (C) Martijn Voncken 2007 <mvoncken@gmail.com>
|
||||
# Contains copy and pasted code from other parts of deluge,see deluge AUTHORS
|
||||
#
|
||||
# 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 2, 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.
|
||||
|
||||
import os
|
||||
import gtk
|
||||
import dbus
|
||||
import deluge.common as common
|
||||
from lib.pythonize import pythonize
|
||||
import base64
|
||||
import random
|
||||
random.seed()
|
||||
|
||||
dbus_interface="org.deluge_torrent.dbusplugin"
|
||||
dbus_service="/org/deluge_torrent/DelugeDbusPlugin"
|
||||
|
||||
dbus_manager = None
|
||||
def get_dbus_manager(*args):
|
||||
#another way to make a singleton.
|
||||
global dbus_manager
|
||||
if not dbus_manager:
|
||||
dbus_manager = DbusManager(*args)
|
||||
return dbus_manager
|
||||
|
||||
class DbusManager(dbus.service.Object):
|
||||
def __init__(self, core, interface,config,config_file):
|
||||
self.core = core
|
||||
self.interface = interface
|
||||
self.config = config
|
||||
self.config_file = config_file
|
||||
self.bus = dbus.SessionBus()
|
||||
bus_name = dbus.service.BusName(dbus_interface,bus=self.bus)
|
||||
dbus.service.Object.__init__(self, bus_name,dbus_service)
|
||||
|
||||
#
|
||||
#todo : add: get_interface_version in=i,get_config_value in=s out=s
|
||||
#
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="",out_signature="as")
|
||||
def get_session_state(self):
|
||||
"""Returns a list of torrent_ids in the session.
|
||||
same as 0.6, but returns type "as" instead of a pickle
|
||||
"""
|
||||
torrent_list = [str(key) for key in self.core.unique_IDs]
|
||||
return torrent_list
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="sas",out_signature="a{sv}")
|
||||
def get_torrent_status(self, torrent_id, keys):
|
||||
"""return torrent metadata of a single torrent as a dict
|
||||
0.6 returns a pickle, this returns a dbus-type.
|
||||
+added some more values to the dict
|
||||
"""
|
||||
|
||||
torrent_id = int(torrent_id)
|
||||
# Convert the array of strings to a python list of strings
|
||||
nkeys = [str(key) for key in keys]
|
||||
|
||||
state = self.core.get_torrent_state(torrent_id)
|
||||
torrent = self.core.unique_IDs[torrent_id]
|
||||
|
||||
status = {
|
||||
"name": state["name"],
|
||||
"total_size": state["total_size"],
|
||||
"num_pieces": state["num_pieces"],
|
||||
"state": state['state'],
|
||||
"user_paused": self.core.is_user_paused(torrent_id),
|
||||
"paused":state['is_paused'],
|
||||
"progress": int(state["progress"] * 100),
|
||||
"next_announce": state["next_announce"],
|
||||
"total_payload_download":state["total_payload_download"],
|
||||
"total_payload_upload": state["total_payload_upload"],
|
||||
"download_payload_rate": state["download_rate"],
|
||||
"upload_payload_rate": state["upload_rate"],
|
||||
"num_peers": state["num_peers"],
|
||||
"num_seeds": state["num_seeds"],
|
||||
"total_wanted": state["total_wanted"],
|
||||
"eta": common.estimate_eta(state),
|
||||
"ratio": self.interface.manager.calc_ratio(torrent_id,state),
|
||||
#non 0.6 values follow here:
|
||||
"tracker_status": state.get("tracker_status","?"),
|
||||
"uploaded_memory": torrent.uploaded_memory,
|
||||
}
|
||||
#more non 0.6 values
|
||||
for key in ["total_seeds", "total_peers","is_seed", "total_done",
|
||||
"total_download", "total_upload"
|
||||
#, "download_rate","upload_rate"
|
||||
, "num_files", "piece_length", "distributed_copies"
|
||||
,"next_announce","tracker","queue_pos"]:
|
||||
status[key] = state[key]
|
||||
|
||||
#print 'all_keys:',sorted(status.keys())
|
||||
|
||||
status_subset = {}
|
||||
for key in keys:
|
||||
if key in status:
|
||||
status_subset[key] = status[key]
|
||||
else:
|
||||
print 'mbus error,no key named:', key
|
||||
return status_subset
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="as",out_signature="")
|
||||
def pause_torrent(self, torrents):
|
||||
"""same as 0.6 interface"""
|
||||
for torrent_id in torrents:
|
||||
torrent_id = int(torrent_id)
|
||||
self.core.set_user_pause(torrent_id, True)
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="as", out_signature="")
|
||||
def resume_torrent(self, torrents):
|
||||
"""same as 0.6 interface"""
|
||||
for torrent_id in torrents:
|
||||
torrent_id = int(torrent_id)
|
||||
self.core.set_user_pause(torrent_id, False)
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="as", out_signature="")
|
||||
def force_reannounce(self, torrents):
|
||||
"""same as 0.6 interface"""
|
||||
for torrent_id in torrents:
|
||||
torrent_id = int(torrent_id)
|
||||
self.core.update_tracker(torrent_id)
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="asbb", out_signature="")
|
||||
def remove_torrent(self, torrent_ids, data_also, torrent_also):
|
||||
"""remove a torrent,and optionally data and torrent
|
||||
additions compared to 0.6 interface: (data_also, torrent_also)
|
||||
"""
|
||||
for torrent_id in torrent_ids:
|
||||
torrent_id = int(torrent_id)
|
||||
self.core.remove_torrent(torrent_id, bool(data_also)
|
||||
,bool( torrent_also))
|
||||
|
||||
#this should not be needed:
|
||||
gtk.gdk.threads_enter()
|
||||
try:
|
||||
self.interface.torrent_model_remove(torrent_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="s", out_signature="b")
|
||||
def add_torrent_url(self, url):
|
||||
filename = fetch_url(url)
|
||||
self._add_torrent(filename)
|
||||
return True
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="s", out_signature="b")
|
||||
def queue_up(self, torrent_id):
|
||||
self.core.queue_up(int(torrent_id))
|
||||
return True
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="s", out_signature="b")
|
||||
def queue_down(self, torrent_id):
|
||||
self.core.queue_down(int(torrent_id))
|
||||
return True
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="ss", out_signature="b")
|
||||
def add_torrent_filecontent(self, name, filecontent_b64):
|
||||
"""not available in deluge 0.6 interface"""
|
||||
#name = fillename without directory
|
||||
name = name.replace('\\','/')
|
||||
name = 'deluge_' + str(random.random()) + '_' + name.split('/')[-1]
|
||||
filename = os.path.join(self.core.config.get("default_download_path"), name)
|
||||
|
||||
filecontent = base64.b64decode(filecontent_b64)
|
||||
f = open(filename,"wb") #no with statement, that's py 2.5+
|
||||
f.write(filecontent)
|
||||
f.close()
|
||||
print 'write:',filename
|
||||
self._add_torrent(filename)
|
||||
return True
|
||||
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="", out_signature="a{sv}")
|
||||
def get_config(self):
|
||||
return self.core.config.mapping
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="s", out_signature="v")
|
||||
def get_config_value(self,key):
|
||||
return self.core.config.mapping[pythonize(key)] #ugly!
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="a{sv}", out_signature="")
|
||||
def set_config(self, config):
|
||||
"""Set the config with values from dictionary"""
|
||||
config = deluge.common.pythonize(config)
|
||||
# Load all the values into the configuration
|
||||
for key in self.core.config.keys():
|
||||
self.core.config[key] = config[key]
|
||||
self.core.apply_prefs()
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="", out_signature="v")
|
||||
def get_download_rate(self):
|
||||
return self.core.get_state()['download_rate']
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="", out_signature="v")
|
||||
def get_upload_rate(self):
|
||||
return self.core.get_state()['upload_rate']
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus_interface,
|
||||
in_signature="", out_signature="v")
|
||||
def get_num_connections(self):
|
||||
core_state = self.core.get_state()
|
||||
return core_state['num_connections']
|
||||
|
||||
#internal
|
||||
def _add_torrent(self, filename):
|
||||
filename = unicode(filename)
|
||||
target = self.core.config.get("default_download_path")
|
||||
|
||||
torrent_id = self.core.add_torrent(filename, target,
|
||||
self.interface.config.get("use_compact_storage"))
|
||||
|
||||
#update gtk-ui This should not be needed!!
|
||||
gtk.gdk.threads_enter()
|
||||
try:
|
||||
self.interface.torrent_model_append(torrent_id)
|
||||
except:
|
||||
pass
|
||||
#finally is 2.5 only!
|
||||
gtk.gdk.threads_leave()
|
||||
|
||||
return True
|
||||
|
||||
def fetch_url(url):
|
||||
import urllib
|
||||
|
||||
try:
|
||||
filename, headers = urllib.urlretrieve(url)
|
||||
except IOError:
|
||||
raise Exception( "Network error while trying to fetch torrent from %s"
|
||||
% url)
|
||||
else:
|
||||
if (filename.endswith(".torrent") or
|
||||
headers["content-type"]=="application/x-bittorrent"):
|
||||
return filename
|
||||
else:
|
||||
raise Exception("URL doesn't appear to be a valid torrent file:%s"
|
||||
% url)
|
||||
|
||||
return None
|
|
@ -29,16 +29,28 @@
|
|||
# this exception statement from your version. If you delete this exception
|
||||
# statement from all source files in the program, then also delete it here.
|
||||
|
||||
#initialize components:
|
||||
import menu_manager #registers as "MenuManager"
|
||||
import config_page_manager #registers as "ConfigPageManager"
|
||||
import plugin_manager #registers as "WebPluginManager"
|
||||
import page_manager #registers as "PageManager"
|
||||
|
||||
from webserver_common import ws
|
||||
#self registering pages etc.
|
||||
import pages
|
||||
import config_tabs_webui #auto registers in ConfigUiManager
|
||||
import config_tabs_deluge #auto registers in ConfigUiManager
|
||||
import register_menu
|
||||
|
||||
from webserver_common import ws #todo: remove ws.
|
||||
|
||||
from lib.webpy022.request import webpyfunc
|
||||
from lib.webpy022 import webapi
|
||||
from lib.gtk_cherrypy_wsgiserver import CherryPyWSGIServer
|
||||
import lib.webpy022 as web
|
||||
import os
|
||||
|
||||
def create_webserver(urls, methods, middleware):
|
||||
from webserver_common import ws
|
||||
from lib.webpy022.request import webpyfunc
|
||||
from lib.webpy022 import webapi
|
||||
from lib.gtk_cherrypy_wsgiserver import CherryPyWSGIServer
|
||||
import os
|
||||
|
||||
func = webapi.wsgifunc(webpyfunc(urls, methods, False), *middleware)
|
||||
server_address=("0.0.0.0", int(ws.config.get('port')))
|
||||
|
||||
|
@ -51,13 +63,14 @@ def create_webserver(urls, methods, middleware):
|
|||
return server
|
||||
|
||||
def WebServer(debug = False):
|
||||
import lib.webpy022 as web
|
||||
from deluge import component
|
||||
if debug:
|
||||
middleware = [web.reloader]
|
||||
else:
|
||||
middleware = []
|
||||
|
||||
import pages
|
||||
return create_webserver(pages.urls, pages.page_classes, middleware)
|
||||
pagemanager = component.get("PageManager")
|
||||
return create_webserver(pagemanager.urls, pagemanager.page_classes, middleware)
|
||||
|
||||
def run(debug = False):
|
||||
server = WebServer(debug)
|
||||
|
|
|
@ -37,52 +37,56 @@ future : required for plugin-api.
|
|||
"""
|
||||
from utils import logcall
|
||||
from render import template
|
||||
from deluge import component
|
||||
|
||||
admin_pages = [] #[(title, url),..]
|
||||
detail_tabs = [] #[(title, url),..]
|
||||
toolbar_items = [] #((id,title ,flag ,method ,url ,image ),.. )
|
||||
|
||||
#a storage+sorteddict == evildict.
|
||||
|
||||
#toolbar:
|
||||
|
||||
class TB:
|
||||
class TOOLBAR_FLAGS:
|
||||
generic = 0
|
||||
torrent = 1
|
||||
torrent_list = 2
|
||||
|
||||
def register_toolbar_item(id, title, image, flag, method, url, important):
|
||||
toolbar_items.append((id, title, image, flag, method, url, important))
|
||||
#todo: remove lower hack.
|
||||
class MenuManager(component.Component):
|
||||
TOOLBAR_FLAGS = TOOLBAR_FLAGS
|
||||
def __init__(self):
|
||||
component.Component.__init__(self, "MenuManager")
|
||||
self.admin_pages = [] #[(title, url),..]
|
||||
self.detail_tabs = [] #[(title, url),..]
|
||||
self.toolbar_items = [] #((id,title ,flag ,method ,url ,image ),.. )
|
||||
|
||||
def unregister_toolbar_item(item_id):
|
||||
for (i, toolbar) in enumerate(admin_pages):
|
||||
if toolbar[0] == item_id:
|
||||
del toolbar_items[i]
|
||||
|
||||
#admin:
|
||||
#register vars in template.
|
||||
template.Template.globals["admin_pages"] = self.admin_pages
|
||||
template.Template.globals["detail_tabs"] = self.detail_tabs
|
||||
template.Template.globals["toolbar_items"] = self.toolbar_items
|
||||
|
||||
def register_admin_page(id, title, url):
|
||||
admin_pages.append((id, title, url))
|
||||
|
||||
def unregister_admin_page(page_id):
|
||||
for (i, (id, title, url)) in list(enumerate(admin_pages)):
|
||||
if id == page_id:
|
||||
del admin_pages[i]
|
||||
return
|
||||
def register_toolbar_item(self, id, title, image, flag, method, url, important):
|
||||
self.toolbar_items.append((id, title, image, flag, method, url, important))
|
||||
#todo: remove lower hack.
|
||||
|
||||
#detail:
|
||||
def unregister_toolbar_item(self, item_id):
|
||||
for (i, toolbar) in enumerate(admin_pages):
|
||||
if toolbar[0] == item_id:
|
||||
del self.toolbar_items[i]
|
||||
|
||||
def register_detail_tab(id, title, page):
|
||||
detail_tabs.append((id, title, page))
|
||||
#admin:
|
||||
def register_admin_page(self, id, title, url):
|
||||
self.admin_pages.append((id, title, url))
|
||||
|
||||
def unregister_detail_tab(tab_id):
|
||||
for (i, (id, title, tab)) in list(enumerate(detail_tabs)):
|
||||
if id == tab_id:
|
||||
del detail_tabs[i]
|
||||
return
|
||||
def unregister_admin_page(page_id):
|
||||
for (i, (id, title, url)) in list(enumerate(admin_pages)):
|
||||
if id == page_id:
|
||||
del self.admin_pages[i]
|
||||
return
|
||||
|
||||
#detail:
|
||||
def register_detail_tab(self, id, title, page):
|
||||
self.detail_tabs.append((id, title, page))
|
||||
|
||||
def unregister_detail_tab(self, tab_id):
|
||||
for (i, (id, title, tab)) in list(enumerate(detail_tabs)):
|
||||
if id == tab_id:
|
||||
del self.detail_tabs[i]
|
||||
return
|
||||
|
||||
__menu_manager = MenuManager()
|
||||
|
||||
#register vars in template.
|
||||
template.Template.globals["admin_pages"] = admin_pages
|
||||
template.Template.globals["detail_tabs"] = detail_tabs
|
||||
template.Template.globals["toolbar_items"] = toolbar_items
|
||||
|
|
69
deluge/ui/webui/page_manager.py
Normal file
69
deluge/ui/webui/page_manager.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Copyright (C) Martijn Voncken 2007 <mvoncken@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 2, 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.
|
||||
#
|
||||
|
||||
from deluge import component
|
||||
|
||||
class PageManager(component.Component):
|
||||
"""
|
||||
web,py 0.2 mapping hack..
|
||||
see deluge_webserver.py
|
||||
"""
|
||||
def __init__(self):
|
||||
component.Component.__init__(self, "PageManager")
|
||||
self.page_classes = {}
|
||||
self.urls = []
|
||||
|
||||
def register_pages(self, url_list, class_list):
|
||||
self.urls += url_list
|
||||
self.page_classes.update(class_list)
|
||||
|
||||
def register_page(self, url, klass):
|
||||
self.urls.append(url)
|
||||
self.urls.append(klass.__name__)
|
||||
self.page_classes[klass.__name__] = klass
|
||||
|
||||
def unregister_page(self, url):
|
||||
raise NotImplemenetedError()
|
||||
#self.page_classes[klass.__name__] = None
|
||||
|
||||
__page_manager = PageManager()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -30,12 +30,16 @@
|
|||
# this exception statement from your version. If you delete this exception
|
||||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
|
||||
|
||||
#todo: remove useless imports.
|
||||
|
||||
from webserver_common import ws, proxy, log
|
||||
from utils import *
|
||||
import utils #todo remove the line above.
|
||||
from render import render, error_page
|
||||
import page_decorators as deco
|
||||
from config import config_page
|
||||
from config_forms import config_page
|
||||
from torrent_options import torrent_options
|
||||
from torrent_move import torrent_move
|
||||
|
||||
|
@ -48,55 +52,16 @@ web.webapi.internalerror = deluge_debugerror
|
|||
import lib.webpy022 as web
|
||||
from lib.webpy022.http import seeother, url
|
||||
from lib.static_handler import static_handler
|
||||
|
||||
from torrent_add import torrent_add
|
||||
|
||||
from operator import attrgetter
|
||||
import os
|
||||
from deluge import component
|
||||
|
||||
page_manager = component.get("PageManager")
|
||||
|
||||
#from json_api import json_api #secuity leak, todo:fix
|
||||
|
||||
#self registering pages:
|
||||
import config_tabs_webui #auto registers
|
||||
import config_tabs_deluge #auto registers
|
||||
from torrent_add import torrent_add #todo: self-register.
|
||||
|
||||
#plugin like api's
|
||||
import menu_manager
|
||||
from menu_manager import TB
|
||||
|
||||
#plugin-like api's : register
|
||||
|
||||
menu_manager.register_admin_page("config", _("Config"), "/config/")
|
||||
menu_manager.register_admin_page("connect", _("Connect"), "/connect")
|
||||
menu_manager.register_admin_page("about", _("About"), "/about")
|
||||
menu_manager.register_admin_page("logout", _("Logout"), "/logout")
|
||||
|
||||
menu_manager.register_detail_tab("details", _("Details"), "tab_meta")
|
||||
menu_manager.register_detail_tab("files", _("Files"), "tab_files")
|
||||
menu_manager.register_detail_tab("options", _("Options"), "tab_options")
|
||||
menu_manager.register_detail_tab("trackers", _("Trackers"), "tab_trackers")
|
||||
|
||||
menu_manager.register_toolbar_item("add", _("Add"), "list-add.png" , TB.generic,
|
||||
"GET","/torrent/add/", True)
|
||||
menu_manager.register_toolbar_item("delete",_("Delete"), "list-remove.png" ,TB.torrent_list,
|
||||
"GET","/torrent/delete/" , True)
|
||||
menu_manager.register_toolbar_item("stop",_("Stop"), "pause.png" ,TB.torrent_list,
|
||||
"POST","/torrent/stop/", True)
|
||||
menu_manager.register_toolbar_item("start",_("Start"), "start.png" ,TB.torrent_list,
|
||||
"POST","/torrent/start/", True)
|
||||
menu_manager.register_toolbar_item("queue_up",_("Up"), "queue-up.png" ,TB.torrent_list,
|
||||
"POST","/torrent/queue/up/", True)
|
||||
menu_manager.register_toolbar_item("queue_down",_("Down"), "queue-down.png" ,TB.torrent_list,
|
||||
"POST","/torrent/queue/down/", True)
|
||||
menu_manager.register_toolbar_item("details",_("Details"), "details.png" ,TB.torrent,
|
||||
"GET","/torrent/info/", True)
|
||||
menu_manager.register_toolbar_item("move",_("Move"), "move.png" ,TB.torrent_list,
|
||||
"POST","/torrent/move/", True)
|
||||
|
||||
menu_manager.register_toolbar_item("reannounce",_("Reannounce"), "view-refresh.png" ,TB.torrent_list,
|
||||
"POST","'/torrent/reannounce/", False)
|
||||
menu_manager.register_toolbar_item("recheck",_("Recheck"), "view-refresh.png" ,TB.torrent_list,
|
||||
"POST","'/torrent/recheck/", False)
|
||||
|
||||
#routing:
|
||||
urls = [
|
||||
|
@ -142,7 +107,6 @@ urls = [
|
|||
#/routing
|
||||
|
||||
|
||||
|
||||
#pages:
|
||||
class login:
|
||||
@deco.deluge_page_noauth
|
||||
|
@ -495,15 +459,4 @@ class pixmaps:
|
|||
|
||||
#/pages
|
||||
|
||||
#for plugins:
|
||||
page_classes = dict(globals())
|
||||
|
||||
def register_page(url, klass):
|
||||
urls.append(url)
|
||||
urls.append(klass.__name__)
|
||||
page_classes[klass.__name__] = klass
|
||||
|
||||
def unregister_page(url):
|
||||
raise NotImplemenetedError()
|
||||
#page_classes[klass.__name__] = None
|
||||
|
||||
page_manager.register_pages(urls,globals())
|
||||
|
|
|
@ -31,29 +31,16 @@
|
|||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
|
||||
import deluge.component as component
|
||||
import deluge.pluginmanagerbase
|
||||
from deluge import component, pluginmanagerbase
|
||||
from deluge.configmanager import ConfigManager
|
||||
from deluge.log import LOG as log
|
||||
|
||||
import lib.webpy022 as web
|
||||
import lib.newforms_plus as forms
|
||||
from render import render
|
||||
from utils import logcall
|
||||
import page_decorators as deco
|
||||
|
||||
import pages
|
||||
import config
|
||||
|
||||
from menu_manager import TB
|
||||
import menu_manager
|
||||
|
||||
class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
|
||||
class PluginManager(pluginmanagerbase.PluginManagerBase,
|
||||
component.Component):
|
||||
def __init__(self):
|
||||
component.Component.__init__(self, "PluginManager")
|
||||
self.config = ConfigManager("gtkui.conf")
|
||||
deluge.pluginmanagerbase.PluginManagerBase.__init__(
|
||||
component.Component.__init__(self, "WebPluginManager")
|
||||
self.config = ConfigManager("webui.conf")
|
||||
pluginmanagerbase.PluginManagerBase.__init__(
|
||||
self, "webui.conf", "deluge.plugin.webui")
|
||||
|
||||
def start(self):
|
||||
|
@ -73,22 +60,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
|
|||
self.enable_plugins()
|
||||
|
||||
|
||||
register_template_path = staticmethod(render.register_template_path)
|
||||
unregister_template_path = staticmethod(render.unregister_template_path)
|
||||
|
||||
register_admin_page = staticmethod(menu_manager.register_admin_page)
|
||||
unregister_admin_page = staticmethod(menu_manager.unregister_admin_page)
|
||||
|
||||
register_toolbar_item = staticmethod(menu_manager.register_toolbar_item)
|
||||
unregister_toolbar_item = staticmethod(menu_manager.register_toolbar_item)
|
||||
|
||||
register_page = staticmethod(pages.register_page)
|
||||
unregister_page = staticmethod(pages.unregister_page)
|
||||
|
||||
register_config_form = staticmethod(config.register_block)
|
||||
unregister_config_form = staticmethod(config.unregister_block)
|
||||
__plugin_manager = PluginManager()
|
||||
|
||||
|
||||
__all__ = ['PluginManager','web','forms','render','logcall','deco','TB']
|
||||
|
||||
|
58
deluge/ui/webui/register_menu.py
Normal file
58
deluge/ui/webui/register_menu.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
#
|
||||
# Copyright (C) Martijn Voncken 2008 <mvoncken@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 2, 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.
|
||||
#
|
||||
|
||||
from deluge import component
|
||||
|
||||
menu = component.get("MenuManager")
|
||||
TB = menu.TOOLBAR_FLAGS
|
||||
|
||||
menu.register_admin_page("config", _("Config"), "/config/")
|
||||
menu.register_admin_page("connect", _("Connect"), "/connect")
|
||||
menu.register_admin_page("about", _("About"), "/about")
|
||||
menu.register_admin_page("logout", _("Logout"), "/logout")
|
||||
|
||||
menu.register_detail_tab("details", _("Details"), "tab_meta")
|
||||
menu.register_detail_tab("files", _("Files"), "tab_files")
|
||||
menu.register_detail_tab("options", _("Options"), "tab_options")
|
||||
menu.register_detail_tab("trackers", _("Trackers"), "tab_trackers")
|
||||
|
||||
menu.register_toolbar_item("add", _("Add"), "list-add.png" , TB.generic, "GET","/torrent/add/", True)
|
||||
menu.register_toolbar_item("delete",_("Delete"), "list-remove.png" ,TB.torrent_list, "GET","/torrent/delete/" , True)
|
||||
menu.register_toolbar_item("stop",_("Stop"), "pause.png" ,TB.torrent_list, "POST","/torrent/stop/", True)
|
||||
menu.register_toolbar_item("start",_("Start"), "start.png" ,TB.torrent_list, "POST","/torrent/start/", True)
|
||||
menu.register_toolbar_item("queue_up",_("Up"), "queue-up.png" ,TB.torrent_list, "POST","/torrent/queue/up/", True)
|
||||
menu.register_toolbar_item("queue_down",_("Down"), "queue-down.png" ,TB.torrent_list, "POST","/torrent/queue/down/", True)
|
||||
menu.register_toolbar_item("details",_("Details"), "details.png" ,TB.torrent, "GET","/torrent/info/", True)
|
||||
menu.register_toolbar_item("move",_("Move"), "move.png" ,TB.torrent_list,"POST","/torrent/move/", True)
|
||||
menu.register_toolbar_item("reannounce",_("Reannounce"), "view-refresh.png" ,TB.torrent_list, "POST","'/torrent/reannounce/", False)
|
||||
menu.register_toolbar_item("recheck",_("Recheck"), "view-refresh.png" ,TB.torrent_list, "POST","'/torrent/recheck/", False)
|
|
@ -54,6 +54,8 @@ class subclassed_render(object):
|
|||
#load template-meta-data
|
||||
cfg_template = ws.config.get('template')
|
||||
template_path = os.path.join(ws.webui_path, 'templates/%s/' % cfg_template)
|
||||
if not os.path.exists(template_path):
|
||||
template_path = os.path.join(ws.webui_path, 'templates/deluge/')
|
||||
self.meta = Storage(eval(open(os.path.join(template_path,'meta.cfg')).read()))
|
||||
|
||||
#load renerders
|
||||
|
@ -186,5 +188,4 @@ template.Template.globals.update({
|
|||
})
|
||||
#/template-defs
|
||||
|
||||
|
||||
__all__ = ['render']
|
||||
|
|
|
@ -84,7 +84,7 @@ $for torrent in torrent_list:
|
|||
</td>
|
||||
<td>$ftime(torrent.eta)</td>
|
||||
<td>$("%.3f" % torrent.distributed_copies)</td>
|
||||
<td>$("%.3f" % torrent.ratio)</td\>
|
||||
<td>$("%.3f" % torrent.ratio)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -19,7 +19,7 @@ $for group in groups:
|
|||
<!--form block-->
|
||||
<div class="panel" id="config_panel">
|
||||
<h2>$form.group / $form.title</h2>
|
||||
<div id="info">$form.info</div>
|
||||
<div class="info">$form.info</div>
|
||||
<form method="POST">
|
||||
<table id="config_table">
|
||||
$:form.as_table()
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
$def with (connect_list, connected)
|
||||
|
||||
$:render.header(_("Connect to Daemon"), 'connect')
|
||||
$:render.header(_("Connect to Daemon"), 'Connect')
|
||||
|
||||
$:render.admin_toolbar('connect')
|
||||
|
||||
<div class="panel" align="left">
|
||||
<h2>$_("Connect")</h2>
|
||||
$if connected:
|
||||
<table><tr>
|
||||
<td>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
$def with (error)
|
||||
$:render.header(_('Login'))
|
||||
<div class="panel">
|
||||
<h2>$_("Deluge Login")</h2>
|
||||
|
||||
$if error > 0:
|
||||
<div class="error">$_("Password is invalid,try again")</div>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
$def with (add_form, options_form, error)
|
||||
$:render.header(_("Add Torrent"))
|
||||
<div class="panel">
|
||||
<h2>$_("Add Torrent")</h2>
|
||||
<form method="POST" action="/torrent/add" ENCTYPE="multipart/form-data">
|
||||
<input type="hidden" name="redir" value="$get('redir')">
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
$def with (torrent_list, organize_filters)
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Deluge:$_('Torrent list')</title>
|
||||
|
@ -34,6 +36,7 @@ $if organize_filters:
|
|||
$:render.part_organize(organize_filters)
|
||||
|
||||
|
||||
|
||||
<table id="torrent_list_block" width="70%">
|
||||
<tr><td>
|
||||
<div id="toolbar">
|
||||
|
@ -44,12 +47,11 @@ $if organize_filters:
|
|||
|
||||
</td></tr><tr><td height=100%>
|
||||
|
||||
<!-- torrent info here?-->
|
||||
|
||||
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
<div class="panel" id="info_panel_div" style="width:740px;">
|
||||
<iframe
|
||||
style="border-style:hidden;width:740px;height:200px;"
|
||||
|
@ -57,10 +59,13 @@ $if organize_filters:
|
|||
</iframe>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
<script language='javascript'>
|
||||
/*on_click_action = open_details;*/
|
||||
on_click_action = on_click_row_js;
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
$def with (error)
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Deluge:$_('Login')</title>
|
||||
<link rel="icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
||||
<link rel="shortcut icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
||||
<link rel="stylesheet" type="text/css" href="/template_style.css" />
|
||||
<script language="javascript" src="/static/deluge.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page">
|
||||
|
||||
<div class="panel">
|
||||
$if error > 0:
|
||||
<div class="error">$_("Password is invalid,try again")</div>
|
||||
|
||||
<form method="POST" id="loginform" action='/login'>
|
||||
<input type="hidden" name="redir" value="$get('redir')">
|
||||
<div id="loginpanel">
|
||||
<div class="form_row">
|
||||
<span class="form_label">$_('Password')</span>
|
||||
<input type="password" name="pwd" id="pwd" class="form_input">
|
||||
</div>
|
||||
<div class="form_row">
|
||||
<span class="form_label"></span>
|
||||
<input type="submit" name="submit"
|
||||
id="submit" value="Submit" class="form_input">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
$:render.footer()
|
|
@ -39,11 +39,13 @@ $for tracker, num in filters.tracker:
|
|||
|
||||
|
||||
<div class="title">$_('Keyword')</div>
|
||||
$if get('keyword'):
|
||||
<div style="background-color:#F00">
|
||||
<input type="text" name="keyword" value="$get('keyword')" style="width:100px"
|
||||
title="$_('Filter on a keyword')"
|
||||
/>
|
||||
$if get('keyword'):
|
||||
selected
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -32,6 +32,22 @@ img{
|
|||
}
|
||||
|
||||
/*controls:*/
|
||||
div.error {
|
||||
background-color:#FFFFFF;
|
||||
color:#AA0000;
|
||||
font-weight:bold;
|
||||
-moz-border-radius:10px;
|
||||
width:200px;
|
||||
margin-bottom:20px;
|
||||
padding:10px;
|
||||
|
||||
}
|
||||
div.info {
|
||||
background-color:#FFFFFF;
|
||||
color: #0000AA;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
a.tab_button_active {
|
||||
color: #0000AA;
|
||||
text-decoration:none;
|
||||
|
@ -47,7 +63,7 @@ div.panel {
|
|||
border-style:solid;
|
||||
border-width:2px;
|
||||
border-color:#C3D9FF;
|
||||
background-color:#E0ECFF;
|
||||
background-color:#FAFAFA; /*offf-topic-hint:allo allo*/
|
||||
-moz-border-radius:5px;
|
||||
width:700px;
|
||||
margin-left:20px;
|
||||
|
@ -55,6 +71,17 @@ div.panel {
|
|||
|
||||
}
|
||||
|
||||
h2 {
|
||||
background-color:#E0ECFF;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
background-color:#E0ECFF;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
|
||||
/*page from top to bottom:*/
|
||||
|
||||
/*top part :*/
|
||||
|
@ -216,9 +243,6 @@ div.progress_bar{
|
|||
text-align:right;
|
||||
}
|
||||
|
||||
#config_panel table {
|
||||
background-color:none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -141,6 +141,11 @@ class Ws:
|
|||
def init_process(self):
|
||||
self.config = pickle.load(open(self.config_file))
|
||||
|
||||
if self.config.get('enabled_plugins') == None:
|
||||
self.config['enabled_plugins'] = []
|
||||
self.save_config()
|
||||
|
||||
|
||||
def init_06(self, uri = 'http://localhost:58846'):
|
||||
proxy.set_core_uri(uri)
|
||||
|
||||
|
@ -153,8 +158,11 @@ class Ws:
|
|||
pickle.dump(CONFIG_DEFAULTS,f)
|
||||
f.close()
|
||||
|
||||
|
||||
self.init_process()
|
||||
self.env = '0.6'
|
||||
from render import render
|
||||
render.apply_cfg()
|
||||
|
||||
#utils for config:
|
||||
def get_templates(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue