mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-02 22:48:40 +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 sys
|
||||||
import os
|
import os
|
||||||
import utils
|
import utils
|
||||||
|
from deluge import component
|
||||||
|
|
||||||
groups = []
|
config_page_manager = component.get("ConfigPageManager")
|
||||||
blocks = forms.utils.datastructures.SortedDict()
|
|
||||||
|
|
||||||
class WebCfgForm(forms.Form):
|
class WebCfgForm(forms.Form):
|
||||||
"config base for webui"
|
"config base for webui"
|
||||||
|
@ -76,9 +76,9 @@ class config_page:
|
||||||
"""
|
"""
|
||||||
def get_form_class(self,name):
|
def get_form_class(self,name):
|
||||||
try:
|
try:
|
||||||
return blocks[name]
|
return config_page_manager.blocks[name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise Exception('no config page named:"%s"')
|
raise Exception('no config page named:"%s"' % name)
|
||||||
|
|
||||||
@deco.deluge_page
|
@deco.deluge_page
|
||||||
def GET(self, name):
|
def GET(self, name):
|
||||||
|
@ -109,18 +109,4 @@ class config_page:
|
||||||
error= _('Correct the errors above and try again'))
|
error= _('Correct the errors above and try again'))
|
||||||
|
|
||||||
def render(self, f , name , message = '' , error=''):
|
def render(self, f , name , message = '' , error=''):
|
||||||
return render.config(groups, blocks, f, name , message , error)
|
return render.config(config_page_manager.groups, config_page_manager.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]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
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
|
# 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_plus as forms
|
|
||||||
import config
|
|
||||||
import utils
|
import utils
|
||||||
from webserver_common import ws, proxy , log
|
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")
|
title = _("Ports")
|
||||||
info = _("Restart daemon after changing these values.")
|
info = _("Restart daemon after changing these values.")
|
||||||
_port_from = forms.IntegerField(_("From"))
|
_port_from = forms.IntegerField(_("From"))
|
||||||
|
@ -45,7 +48,7 @@ class NetworkPorts(config.CfgForm ):
|
||||||
random_port = forms.CheckBox(_("Random"))
|
random_port = forms.CheckBox(_("Random"))
|
||||||
|
|
||||||
def initial_data(self):
|
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']
|
data['_port_from'] , data['_port_to'] = data['listen_ports']
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -53,15 +56,15 @@ class NetworkPorts(config.CfgForm ):
|
||||||
data['listen_ports'] = [data['_port_from'] , data['_port_to'] ]
|
data['listen_ports'] = [data['_port_from'] , data['_port_to'] ]
|
||||||
del(data['_port_from'])
|
del(data['_port_from'])
|
||||||
del(data['_port_to'])
|
del(data['_port_to'])
|
||||||
config.CfgForm.save(self, data)
|
config_forms.config.CfgForm.save(self, data)
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
if (data['_port_to'] < data['_port_from']):
|
if (data['_port_to'] < data['_port_from']):
|
||||||
raise ValidationError('"Port from" must be greater than "Port to"')
|
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")
|
title = _("Extra's")
|
||||||
dht = forms.CheckBox(_("Mainline DHT"))
|
dht = forms.CheckBox(_("Mainline DHT"))
|
||||||
upnp = forms.CheckBox(_("UpNP"))
|
upnp = forms.CheckBox(_("UpNP"))
|
||||||
|
@ -69,9 +72,9 @@ class NetworkExtra(config.CfgForm ):
|
||||||
utpex = forms.CheckBox(_("Peer-Exchange"))
|
utpex = forms.CheckBox(_("Peer-Exchange"))
|
||||||
lsd = forms.CheckBox(_("LSD"))
|
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")
|
title = _("Encryption")
|
||||||
|
|
||||||
_enc_choices = list(enumerate([_("Forced"),_("Enabled"),_("Disabled")]))
|
_enc_choices = list(enumerate([_("Forced"),_("Enabled"),_("Disabled")]))
|
||||||
|
@ -82,10 +85,10 @@ class NetworkEnc(config.CfgForm ):
|
||||||
enc_level = forms.IntChoiceField(_("Level"), _level_choices)
|
enc_level = forms.IntChoiceField(_("Level"), _level_choices)
|
||||||
enc_prefer_rc4 = forms.CheckBox("Prefer to encrypt entire stream")
|
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")
|
title = _("Global")
|
||||||
info = _("-1 = Unlimited")
|
info = _("-1 = Unlimited")
|
||||||
max_connections_global = forms.DelugeInt(_("Maximum Connections"))
|
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_speed = forms.DelugeFloat(_("Maximum Upload Speed (Kib/s)"))
|
||||||
max_upload_slots_global = forms.DelugeInt(_("Maximum Upload Slots"))
|
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")
|
title = _("Per Torrent")
|
||||||
info = _("-1 = Unlimited")
|
info = _("-1 = Unlimited")
|
||||||
max_connections_per_torrent = forms.DelugeInt(_("Maximum Connections"))
|
max_connections_per_torrent = forms.DelugeInt(_("Maximum Connections"))
|
||||||
max_upload_slots_per_torrent = forms.DelugeInt(_("Maximum Upload Slots"))
|
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")
|
title = _("Download")
|
||||||
download_location = forms.ServerFolder(_("Store all downoads in"))
|
download_location = forms.ServerFolder(_("Store all downoads in"))
|
||||||
torrentfiles_location = forms.ServerFolder(_("Save .torrent files to"))
|
torrentfiles_location = forms.ServerFolder(_("Save .torrent files to"))
|
||||||
|
@ -113,15 +116,15 @@ class Download(config.CfgForm):
|
||||||
prioritize_first_last_pieces = forms.CheckBox(
|
prioritize_first_last_pieces = forms.CheckBox(
|
||||||
_('Prioritize first and last pieces'))
|
_('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")
|
title = _("Daemon")
|
||||||
info = _("Restart daemon and webui after changing these settings")
|
info = _("Restart daemon and webui after changing these settings")
|
||||||
daemon_port = forms.IntegerField(_("Port"))
|
daemon_port = forms.IntegerField(_("Port"))
|
||||||
allow_remote = forms.CheckBox(_("Allow Remote Connections"))
|
allow_remote = forms.CheckBox(_("Allow Remote Connections"))
|
||||||
|
|
||||||
config.register_block('deluge','daemon', Daemon)
|
config_page.register('deluge','daemon', Daemon)
|
||||||
|
|
||||||
class Plugins(forms.Form):
|
class Plugins(forms.Form):
|
||||||
title = _("Enabled Plugins")
|
title = _("Enabled Plugins")
|
||||||
|
@ -139,9 +142,9 @@ class Plugins(forms.Form):
|
||||||
def save(self, value):
|
def save(self, value):
|
||||||
raise forms.ValidationError("SAVE:TODO")
|
raise forms.ValidationError("SAVE:TODO")
|
||||||
|
|
||||||
config.register_block('deluge','plugins', Plugins)
|
config_page.register('deluge','plugins', Plugins)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
class Queue(forms.Form):
|
class Queue(forms.Form):
|
||||||
title = _("Queue")
|
title = _("Queue")
|
||||||
info = _("queue-cfg not finished")
|
info = _("queue-cfg not finished")
|
||||||
|
@ -159,4 +162,5 @@ class Queue(forms.Form):
|
||||||
def save(self, value):
|
def save(self, value):
|
||||||
raise forms.ValidationError("SAVE:TODO")
|
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
|
# 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_plus as forms
|
|
||||||
import config
|
|
||||||
import utils
|
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")
|
title = _("Template")
|
||||||
|
|
||||||
_templates = [(t,t) for t in ws.get_templates()]
|
_templates = [(t,t) for t in ws.get_templates()]
|
||||||
|
@ -52,20 +56,16 @@ class Template(config.WebCfgForm):
|
||||||
from render import render
|
from render import render
|
||||||
render.apply_cfg()
|
render.apply_cfg()
|
||||||
|
|
||||||
|
class Server(config_forms.WebCfgForm):
|
||||||
class Server(config.WebCfgForm):
|
|
||||||
title = _("Server")
|
title = _("Server")
|
||||||
|
port = forms.IntegerField(label = _("Port"),min_value=80)
|
||||||
|
use_https = forms.CheckBox(_("Use https"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import OpenSSL
|
import OpenSSL
|
||||||
except ImportError:
|
except ImportError:
|
||||||
info = _("pyopenssl not installed, install this for https.")
|
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):
|
def post_save(self):
|
||||||
pass
|
pass
|
||||||
#raise forms.ValidationError(
|
#raise forms.ValidationError(
|
||||||
|
@ -93,6 +93,21 @@ class Password(forms.Form):
|
||||||
utils.end_session()
|
utils.end_session()
|
||||||
#raise forms.ValidationError(_("Password changed,please login again"))
|
#raise forms.ValidationError(_("Password changed,please login again"))
|
||||||
|
|
||||||
config.register_block('webui','template', Template)
|
class WebUiPlugins(forms.Form):
|
||||||
config.register_block('webui','server',Server)
|
title = _("WebUi Plugins")
|
||||||
config.register_block('webui','password',Password)
|
|
||||||
|
_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
|
# 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.
|
||||||
|
|
||||||
|
#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):
|
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)
|
func = webapi.wsgifunc(webpyfunc(urls, methods, False), *middleware)
|
||||||
server_address=("0.0.0.0", int(ws.config.get('port')))
|
server_address=("0.0.0.0", int(ws.config.get('port')))
|
||||||
|
|
||||||
|
@ -51,13 +63,14 @@ def create_webserver(urls, methods, middleware):
|
||||||
return server
|
return server
|
||||||
|
|
||||||
def WebServer(debug = False):
|
def WebServer(debug = False):
|
||||||
|
import lib.webpy022 as web
|
||||||
|
from deluge import component
|
||||||
if debug:
|
if debug:
|
||||||
middleware = [web.reloader]
|
middleware = [web.reloader]
|
||||||
else:
|
else:
|
||||||
middleware = []
|
middleware = []
|
||||||
|
pagemanager = component.get("PageManager")
|
||||||
import pages
|
return create_webserver(pagemanager.urls, pagemanager.page_classes, middleware)
|
||||||
return create_webserver(pages.urls, pages.page_classes, middleware)
|
|
||||||
|
|
||||||
def run(debug = False):
|
def run(debug = False):
|
||||||
server = WebServer(debug)
|
server = WebServer(debug)
|
||||||
|
|
|
@ -37,52 +37,56 @@ future : required for plugin-api.
|
||||||
"""
|
"""
|
||||||
from utils import logcall
|
from utils import logcall
|
||||||
from render import template
|
from render import template
|
||||||
|
from deluge import component
|
||||||
|
|
||||||
admin_pages = [] #[(title, url),..]
|
class TOOLBAR_FLAGS:
|
||||||
detail_tabs = [] #[(title, url),..]
|
|
||||||
toolbar_items = [] #((id,title ,flag ,method ,url ,image ),.. )
|
|
||||||
|
|
||||||
#a storage+sorteddict == evildict.
|
|
||||||
|
|
||||||
#toolbar:
|
|
||||||
|
|
||||||
class TB:
|
|
||||||
generic = 0
|
generic = 0
|
||||||
torrent = 1
|
torrent = 1
|
||||||
torrent_list = 2
|
torrent_list = 2
|
||||||
|
|
||||||
def register_toolbar_item(id, title, image, flag, method, url, important):
|
class MenuManager(component.Component):
|
||||||
toolbar_items.append((id, title, image, flag, method, url, important))
|
TOOLBAR_FLAGS = TOOLBAR_FLAGS
|
||||||
#todo: remove lower hack.
|
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):
|
def register_toolbar_item(self, id, title, image, flag, method, url, important):
|
||||||
for (i, (id, title, url)) in list(enumerate(admin_pages)):
|
self.toolbar_items.append((id, title, image, flag, method, url, important))
|
||||||
if id == page_id:
|
#todo: remove lower hack.
|
||||||
del admin_pages[i]
|
|
||||||
return
|
|
||||||
|
|
||||||
#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):
|
#admin:
|
||||||
detail_tabs.append((id, title, page))
|
def register_admin_page(self, id, title, url):
|
||||||
|
self.admin_pages.append((id, title, url))
|
||||||
|
|
||||||
def unregister_detail_tab(tab_id):
|
def unregister_admin_page(page_id):
|
||||||
for (i, (id, title, tab)) in list(enumerate(detail_tabs)):
|
for (i, (id, title, url)) in list(enumerate(admin_pages)):
|
||||||
if id == tab_id:
|
if id == page_id:
|
||||||
del detail_tabs[i]
|
del self.admin_pages[i]
|
||||||
return
|
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
|
# 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.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
#todo: remove useless imports.
|
||||||
|
|
||||||
from webserver_common import ws, proxy, log
|
from webserver_common import ws, proxy, log
|
||||||
from utils import *
|
from utils import *
|
||||||
import utils #todo remove the line above.
|
import utils #todo remove the line above.
|
||||||
from render import render, error_page
|
from render import render, error_page
|
||||||
import page_decorators as deco
|
import page_decorators as deco
|
||||||
from config import config_page
|
from config_forms import config_page
|
||||||
from torrent_options import torrent_options
|
from torrent_options import torrent_options
|
||||||
from torrent_move import torrent_move
|
from torrent_move import torrent_move
|
||||||
|
|
||||||
|
@ -48,55 +52,16 @@ web.webapi.internalerror = deluge_debugerror
|
||||||
import lib.webpy022 as web
|
import lib.webpy022 as web
|
||||||
from lib.webpy022.http import seeother, url
|
from lib.webpy022.http import seeother, url
|
||||||
from lib.static_handler import static_handler
|
from lib.static_handler import static_handler
|
||||||
|
from torrent_add import torrent_add
|
||||||
|
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
import os
|
import os
|
||||||
|
from deluge import component
|
||||||
|
|
||||||
|
page_manager = component.get("PageManager")
|
||||||
|
|
||||||
#from json_api import json_api #secuity leak, todo:fix
|
#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:
|
#routing:
|
||||||
urls = [
|
urls = [
|
||||||
|
@ -142,7 +107,6 @@ urls = [
|
||||||
#/routing
|
#/routing
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pages:
|
#pages:
|
||||||
class login:
|
class login:
|
||||||
@deco.deluge_page_noauth
|
@deco.deluge_page_noauth
|
||||||
|
@ -495,15 +459,4 @@ class pixmaps:
|
||||||
|
|
||||||
#/pages
|
#/pages
|
||||||
|
|
||||||
#for plugins:
|
page_manager.register_pages(urls,globals())
|
||||||
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
|
|
||||||
|
|
||||||
|
|
|
@ -31,29 +31,16 @@
|
||||||
# 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 deluge.component as component
|
from deluge import component, pluginmanagerbase
|
||||||
import deluge.pluginmanagerbase
|
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
from deluge.log import LOG as log
|
from deluge.log import LOG as log
|
||||||
|
|
||||||
import lib.webpy022 as web
|
class PluginManager(pluginmanagerbase.PluginManagerBase,
|
||||||
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,
|
|
||||||
component.Component):
|
component.Component):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
component.Component.__init__(self, "PluginManager")
|
component.Component.__init__(self, "WebPluginManager")
|
||||||
self.config = ConfigManager("gtkui.conf")
|
self.config = ConfigManager("webui.conf")
|
||||||
deluge.pluginmanagerbase.PluginManagerBase.__init__(
|
pluginmanagerbase.PluginManagerBase.__init__(
|
||||||
self, "webui.conf", "deluge.plugin.webui")
|
self, "webui.conf", "deluge.plugin.webui")
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
@ -73,22 +60,7 @@ class PluginManager(deluge.pluginmanagerbase.PluginManagerBase,
|
||||||
self.enable_plugins()
|
self.enable_plugins()
|
||||||
|
|
||||||
|
|
||||||
register_template_path = staticmethod(render.register_template_path)
|
__plugin_manager = PluginManager()
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
__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
|
#load template-meta-data
|
||||||
cfg_template = ws.config.get('template')
|
cfg_template = ws.config.get('template')
|
||||||
template_path = os.path.join(ws.webui_path, 'templates/%s/' % cfg_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()))
|
self.meta = Storage(eval(open(os.path.join(template_path,'meta.cfg')).read()))
|
||||||
|
|
||||||
#load renerders
|
#load renerders
|
||||||
|
@ -186,5 +188,4 @@ template.Template.globals.update({
|
||||||
})
|
})
|
||||||
#/template-defs
|
#/template-defs
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['render']
|
__all__ = ['render']
|
||||||
|
|
|
@ -84,7 +84,7 @@ $for torrent in torrent_list:
|
||||||
</td>
|
</td>
|
||||||
<td>$ftime(torrent.eta)</td>
|
<td>$ftime(torrent.eta)</td>
|
||||||
<td>$("%.3f" % torrent.distributed_copies)</td>
|
<td>$("%.3f" % torrent.distributed_copies)</td>
|
||||||
<td>$("%.3f" % torrent.ratio)</td\>
|
<td>$("%.3f" % torrent.ratio)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -19,7 +19,7 @@ $for group in groups:
|
||||||
<!--form block-->
|
<!--form block-->
|
||||||
<div class="panel" id="config_panel">
|
<div class="panel" id="config_panel">
|
||||||
<h2>$form.group / $form.title</h2>
|
<h2>$form.group / $form.title</h2>
|
||||||
<div id="info">$form.info</div>
|
<div class="info">$form.info</div>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<table id="config_table">
|
<table id="config_table">
|
||||||
$:form.as_table()
|
$:form.as_table()
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
$def with (connect_list, connected)
|
$def with (connect_list, connected)
|
||||||
|
|
||||||
$:render.header(_("Connect to Daemon"), 'connect')
|
$:render.header(_("Connect to Daemon"), 'Connect')
|
||||||
|
|
||||||
$:render.admin_toolbar('connect')
|
$:render.admin_toolbar('connect')
|
||||||
|
|
||||||
<div class="panel" align="left">
|
<div class="panel" align="left">
|
||||||
|
<h2>$_("Connect")</h2>
|
||||||
$if connected:
|
$if connected:
|
||||||
<table><tr>
|
<table><tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
$def with (error)
|
$def with (error)
|
||||||
$:render.header(_('Login'))
|
$:render.header(_('Login'))
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
|
<h2>$_("Deluge Login")</h2>
|
||||||
|
|
||||||
$if error > 0:
|
$if error > 0:
|
||||||
<div class="error">$_("Password is invalid,try again")</div>
|
<div class="error">$_("Password is invalid,try again")</div>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
$def with (add_form, options_form, error)
|
$def with (add_form, options_form, error)
|
||||||
$:render.header(_("Add Torrent"))
|
$:render.header(_("Add Torrent"))
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
|
<h2>$_("Add Torrent")</h2>
|
||||||
<form method="POST" action="/torrent/add" ENCTYPE="multipart/form-data">
|
<form method="POST" action="/torrent/add" ENCTYPE="multipart/form-data">
|
||||||
<input type="hidden" name="redir" value="$get('redir')">
|
<input type="hidden" name="redir" value="$get('redir')">
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
$def with (torrent_list, organize_filters)
|
$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>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Deluge:$_('Torrent list')</title>
|
<title>Deluge:$_('Torrent list')</title>
|
||||||
|
@ -34,6 +36,7 @@ $if organize_filters:
|
||||||
$:render.part_organize(organize_filters)
|
$:render.part_organize(organize_filters)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table id="torrent_list_block" width="70%">
|
<table id="torrent_list_block" width="70%">
|
||||||
<tr><td>
|
<tr><td>
|
||||||
<div id="toolbar">
|
<div id="toolbar">
|
||||||
|
@ -44,12 +47,11 @@ $if organize_filters:
|
||||||
|
|
||||||
</td></tr><tr><td height=100%>
|
</td></tr><tr><td height=100%>
|
||||||
|
|
||||||
<!-- torrent info here?-->
|
|
||||||
|
|
||||||
</td></tr>
|
</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
<div class="panel" id="info_panel_div" style="width:740px;">
|
<div class="panel" id="info_panel_div" style="width:740px;">
|
||||||
<iframe
|
<iframe
|
||||||
style="border-style:hidden;width:740px;height:200px;"
|
style="border-style:hidden;width:740px;height:200px;"
|
||||||
|
@ -57,10 +59,13 @@ $if organize_filters:
|
||||||
</iframe>
|
</iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script language='javascript'>
|
<script language='javascript'>
|
||||||
/*on_click_action = open_details;*/
|
/*on_click_action = open_details;*/
|
||||||
on_click_action = on_click_row_js;
|
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>
|
<div class="title">$_('Keyword')</div>
|
||||||
|
$if get('keyword'):
|
||||||
|
<div style="background-color:#F00">
|
||||||
<input type="text" name="keyword" value="$get('keyword')" style="width:100px"
|
<input type="text" name="keyword" value="$get('keyword')" style="width:100px"
|
||||||
title="$_('Filter on a keyword')"
|
title="$_('Filter on a keyword')"
|
||||||
/>
|
/>
|
||||||
$if get('keyword'):
|
$if get('keyword'):
|
||||||
selected
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -32,6 +32,22 @@ img{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*controls:*/
|
/*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 {
|
a.tab_button_active {
|
||||||
color: #0000AA;
|
color: #0000AA;
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
|
@ -47,7 +63,7 @@ div.panel {
|
||||||
border-style:solid;
|
border-style:solid;
|
||||||
border-width:2px;
|
border-width:2px;
|
||||||
border-color:#C3D9FF;
|
border-color:#C3D9FF;
|
||||||
background-color:#E0ECFF;
|
background-color:#FAFAFA; /*offf-topic-hint:allo allo*/
|
||||||
-moz-border-radius:5px;
|
-moz-border-radius:5px;
|
||||||
width:700px;
|
width:700px;
|
||||||
margin-left:20px;
|
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:*/
|
/*page from top to bottom:*/
|
||||||
|
|
||||||
/*top part :*/
|
/*top part :*/
|
||||||
|
@ -216,9 +243,6 @@ div.progress_bar{
|
||||||
text-align:right;
|
text-align:right;
|
||||||
}
|
}
|
||||||
|
|
||||||
#config_panel table {
|
|
||||||
background-color:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,11 @@ class Ws:
|
||||||
def init_process(self):
|
def init_process(self):
|
||||||
self.config = pickle.load(open(self.config_file))
|
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'):
|
def init_06(self, uri = 'http://localhost:58846'):
|
||||||
proxy.set_core_uri(uri)
|
proxy.set_core_uri(uri)
|
||||||
|
|
||||||
|
@ -153,8 +158,11 @@ class Ws:
|
||||||
pickle.dump(CONFIG_DEFAULTS,f)
|
pickle.dump(CONFIG_DEFAULTS,f)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
self.init_process()
|
self.init_process()
|
||||||
self.env = '0.6'
|
self.env = '0.6'
|
||||||
|
from render import render
|
||||||
|
render.apply_cfg()
|
||||||
|
|
||||||
#utils for config:
|
#utils for config:
|
||||||
def get_templates(self):
|
def get_templates(self):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue