webui-rev73

This commit is contained in:
Marcos Pinto 2007-10-05 21:16:46 +00:00
parent 20d63448cb
commit 24fbfccfb0
9 changed files with 1379 additions and 289 deletions

View File

@ -31,17 +31,31 @@
plugin_name = "Web User Interface" plugin_name = "Web User Interface"
plugin_author = "Martijn Voncken" plugin_author = "Martijn Voncken"
plugin_version = "rev." plugin_version = "rev."
plugin_description = "A Web based User Interface\n" plugin_description = """A Web based User Interface
Firefox greasemonkey script: http://userscripts.org/scripts/show/12639
Remotely add a file: "curl -F torrent=@./test1.torrent -F pwd=deluge http://localhost:8112/remote/torrent/add"
There is support for multiple templates, but just one is included.
Other contributors:
*somedude : template enhancements.
"""
import deluge.common import deluge.common
import deluge.pref import deluge.pref
from deluge.dialogs import show_popup_warning from deluge.dialogs import show_popup_warning
from dbus_interface import DbusManager from dbus_interface import get_dbus_manager
import webserver_common
import time
import gtk import gtk
import os import os
from subprocess import Popen from subprocess import Popen
from md5 import md5 from md5 import md5
from threading import Thread
import random import random
random.seed() random.seed()
@ -49,10 +63,6 @@ plugin_version += open(os.path.join(os.path.dirname(__file__),'revno')).read()
plugin_description += ( plugin_description += (
open(os.path.join(os.path.dirname(__file__),'version')).read()) open(os.path.join(os.path.dirname(__file__),'version')).read())
#not found a way to stop a dbus manager.
#global so it does not get started twice.
dbus_manager = None
def deluge_init(deluge_path): def deluge_init(deluge_path):
global path global path
path = deluge_path path = deluge_path
@ -61,15 +71,13 @@ def enable(core, interface):
global path global path
return plugin_WebUi(path, core, interface) return plugin_WebUi(path, core, interface)
class plugin_WebUi: class plugin_WebUi(object):
def __init__(self, path, deluge_core, deluge_interface): def __init__(self, path, deluge_core, deluge_interface):
global dbus_manager
self.path = path self.path = path
self.core = deluge_core self.core = deluge_core
self.interface = deluge_interface self.interface = deluge_interface
self.proc = None self.proc = None
self.web_server = None
self.config_file = deluge.common.CONFIG_DIR + "/webui.conf" self.config_file = deluge.common.CONFIG_DIR + "/webui.conf"
self.config = deluge.pref.Preferences(self.config_file, False) self.config = deluge.pref.Preferences(self.config_file, False)
@ -98,19 +106,17 @@ class plugin_WebUi:
if self.config.get("cache_templates") == None: if self.config.get("cache_templates") == None:
self.config.set("cache_templates", True) self.config.set("cache_templates", True)
if self.config.get("run_in_thread") == None:
self.config.set("run_in_thread", True)
if not dbus_manager: self.dbus_manager = get_dbus_manager(deluge_core, deluge_interface,
dbus_manager = self.dbusManager = DbusManager(deluge_core, deluge_interface self.config, self.config_file)
, self.config, self.config_file)
self.dbus_manager = dbus_manager
self.start_server() self.start_server()
def unload(self): def unload(self):
print 'WebUI:unload..' print 'WebUI:unload..'
self.kill_server() self.kill_server()
#self.dbusManager.
def update(self): def update(self):
pass pass
@ -124,18 +130,38 @@ class plugin_WebUi:
def start_server(self): def start_server(self):
self.kill_server() self.kill_server()
print 'start Webui..'
path = os.path.dirname(__file__) if self.config.get("run_in_thread"):
server_bin = path + '/run_webserver' print 'start Webui(inside gtk)..'
port = str(self.config.get('port')) webserver_common.init() #reload changed config.
self.proc = Popen((server_bin, port),cwd=path) from deluge_webserver import WebServer #only import in threaded mode
self.web_server = WebServer()
self.web_server.start_gtk()
else:
print 'start Webui(in process)..'
path = os.path.dirname(__file__)
server_bin = path + '/run_webserver'
port = str(self.config.get('port'))
self.proc = Popen((server_bin, port),cwd=path)
def kill_server(self): def kill_server(self):
if self.web_server:
print "webserver: stop"
self.web_server.stop_gtk()
self.web_server = None
if self.proc: if self.proc:
print "webserver: kill %i"%self.proc.pid print "webserver: kill %i" % self.proc.pid
os.system("kill %i"%self.proc.pid) os.system("kill %i" % self.proc.pid)
time.sleep(1) #safe time to wait for kill to finish.
self.proc = None self.proc = None
def __del__(self):
self.kill_server()
class ConfigDialog(gtk.Dialog): class ConfigDialog(gtk.Dialog):
""" """
@ -160,12 +186,15 @@ class ConfigDialog(gtk.Dialog):
self.template = self.add_widget(_('Template'), gtk.combo_box_new_text()) self.template = self.add_widget(_('Template'), gtk.combo_box_new_text())
self.button_style = self.add_widget(_('Button Style'), self.button_style = self.add_widget(_('Button Style'),
gtk.combo_box_new_text()) gtk.combo_box_new_text())
self.cache_templates = self.add_widget(_('Cache Templates'),
gtk.CheckButton())
self.download_dir = self.add_widget(_('Download Directory'), self.download_dir = self.add_widget(_('Download Directory'),
gtk.FileChooserButton(_('Download Directory'))) gtk.FileChooserButton(_('Download Directory')))
self.torrent_dir = self.add_widget(_('Torrent Directory'), self.torrent_dir = self.add_widget(_('Torrent Directory'),
gtk.FileChooserButton(_('Torrent Directory'))) gtk.FileChooserButton(_('Torrent Directory')))
self.cache_templates = self.add_widget(_('Cache Templates'),
gtk.CheckButton())
self.run_in_thread = self.add_widget(_('Run inside gtk'),
gtk.CheckButton())
self.download_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) self.download_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
self.torrent_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) self.torrent_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
@ -189,10 +218,13 @@ class ConfigDialog(gtk.Dialog):
self.template.set_active( self.template.set_active(
self.templates.index(self.config.get("template"))) self.templates.index(self.config.get("template")))
self.button_style.set_active(self.config.get("button_style")) self.button_style.set_active(self.config.get("button_style"))
self.cache_templates.set_active(self.config.get("cache_templates"))
self.torrent_dir.set_filename(self.config.get("torrent_dir")) self.torrent_dir.set_filename(self.config.get("torrent_dir"))
self.download_dir.set_filename(self.config.get("download_dir")) self.download_dir.set_filename(self.config.get("download_dir"))
self.run_in_thread.set_active(self.config.get("run_in_thread"))
self.cache_templates.set_active(self.config.get("cache_templates"))
self.vbox.pack_start(self.vb, True, True, 0) self.vbox.pack_start(self.vb, True, True, 0)
self.vb.show_all() self.vb.show_all()
@ -226,17 +258,9 @@ class ConfigDialog(gtk.Dialog):
self.config.set("port", int(self.port.get_value())) self.config.set("port", int(self.port.get_value()))
self.config.set("template", self.template.get_active_text()) self.config.set("template", self.template.get_active_text())
self.config.set("button_style", self.button_style.get_active()) self.config.set("button_style", self.button_style.get_active())
self.config.set("cache_templates", self.cache_templates.get_active())
self.config.set("torrent_dir", self.torrent_dir.get_filename()) self.config.set("torrent_dir", self.torrent_dir.get_filename())
self.config.set("download_dir",self.download_dir.get_filename()) self.config.set("download_dir",self.download_dir.get_filename())
self.config.set("cache_templates", self.cache_templates.get_active())
self.config.set("run_in_thread", self.run_in_thread.get_active())
self.config.save(self.plugin.config_file) self.config.save(self.plugin.config_file)
self.plugin.start_server() #restarts server self.plugin.start_server() #restarts server

View File

@ -32,20 +32,25 @@
# 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 os import os
import gtk import gtk
import dbus import dbus
import deluge.common as common import deluge.common as common
from dbus_pythonize import pythonize from dbus_pythonize import pythonize
import base64 import base64
from md5 import md5
import random import random
random.seed() random.seed()
dbus_interface="org.deluge_torrent.dbusplugin" dbus_interface="org.deluge_torrent.dbusplugin"
dbus_service="/org/deluge_torrent/DelugeDbusPlugin" 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): class DbusManager(dbus.service.Object):
def __init__(self, core, interface,config,config_file): def __init__(self, core, interface,config,config_file):
@ -103,7 +108,6 @@ class DbusManager(dbus.service.Object):
"eta": common.estimate_eta(state), "eta": common.estimate_eta(state),
"ratio": self.interface.manager.calc_ratio(torrent_id,state), "ratio": self.interface.manager.calc_ratio(torrent_id,state),
#non 0.6 values follow here: #non 0.6 values follow here:
"message": self.interface.get_message_from_state(state),
"tracker_status": state.get("tracker_status","?"), "tracker_status": state.get("tracker_status","?"),
"uploaded_memory": torrent.uploaded_memory, "uploaded_memory": torrent.uploaded_memory,
} }
@ -175,39 +179,6 @@ class DbusManager(dbus.service.Object):
self._add_torrent(filename) self._add_torrent(filename)
return True return True
@dbus.service.method(dbus_interface=dbus_interface,
in_signature="s",out_signature="v")
def get_webui_config(self,key):
"""
return data from wevbui config.
not in 0.6
"""
retval = self.config.get(str(key))
#print 'get webui config:', str(key), retval
if retval == None:
retval = False #dbus does not accept None :(
return retval
@dbus.service.method(dbus_interface=dbus_interface,
in_signature="sv",out_signature="")
def set_webui_config(self, key, value):
"""
return data from wevbui config.
not in 0.6
"""
#print 'set webui config:', str(key), pythonize(value)
self.config.set(str(key), pythonize(value))
self.config.save(self.config_file)
@dbus.service.method(dbus_interface=dbus_interface,
in_signature="s",out_signature="b")
def check_pwd(self, pwd):
m = md5()
m.update(self.config.get('pwd_salt'))
m.update(pwd)
return (m.digest() == self.config.get('pwd_md5'))
#internal #internal
def _add_torrent(self, filename): def _add_torrent(self, filename):
#dbus types break pickle, again..... #dbus types break pickle, again.....

View File

@ -31,149 +31,35 @@
# 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's before stable: from webserver_common import TORRENT_KEYS, STATE_MESSAGES
-__init__:kill->restart is not waiting for kill to be finished. import webserver_common as ws
--later/features:--- from webserver_framework import *
-alternating rows?
-set prio
-clear finished?
-torrent files.
"""
import webpy022 as web import webpy022 as web
from webpy022.webapi import cookies, setcookie
from webpy022.http import seeother, url from webpy022.http import seeother, url
from webpy022.webapi import setcookie
from webpy022.utils import Storage from webpy022.utils import Storage
from webpy022.net import urlquote
from webpy022 import template, changequery as self_url
import dbus from md5 import md5
import gettext, os, platform, locale, traceback
import random
import base64 import base64
from deluge.common import fsize
from operator import attrgetter from operator import attrgetter
from deluge import common
from deluge.common import INSTALL_PREFIX
#init:
APP = 'deluge'
DIR = os.path.join(INSTALL_PREFIX, 'share', 'locale')
if platform.system() != "Windows":
locale.setlocale(locale.LC_MESSAGES, '')
locale.bindtextdomain(APP, DIR)
locale.textdomain(APP)
else:
locale.setlocale(locale.LC_ALL, '')
gettext.bindtextdomain(APP, DIR)
gettext.textdomain(APP)
gettext.install(APP, DIR)
random.seed()
bus = dbus.SessionBus()
proxy = bus.get_object("org.deluge_torrent.dbusplugin"
, "/org/deluge_torrent/DelugeDbusPlugin")
web.webapi.internalerror = web.debugerror
render = template.render('templates/%s/' % proxy.get_webui_config('template')
,cache=proxy.get_webui_config('cache_templates'))
#/init
#framework:
SESSIONS = {}
def do_redirect():
"""for redirects after a POST"""
vars = web.input(redir = None)
ck = cookies()
if vars.redir:
seeother(vars.redir)
elif ("order" in ck and "sort" in ck):
seeother(url("/index", sort=ck['sort'], order=ck['order']))
else:
seeother(url("/index"))
def deluge_page_noauth(func):
"""
add http headers
print result of func
"""
def deco(self, name=None):
web.header("Content-Type", "text/html; charset=utf-8")
web.header("Cache-Control", "no-cache, must-revalidate")
res = func(self, name)
print res
return deco
def check_session(func):
"""
a decorator
return func if session is valid, else redirect to login page.
"""
def deco(self, name):
vars = web.input(redir_after_login=None)
ck = cookies()
if ck.has_key("session_id") and ck["session_id"] in SESSIONS:
return func(self, name) #ok, continue..
elif vars.redir_after_login:
seeother("/login?redir=" + urlquote(self_url()))
else:
seeother("/login") #do not continue, and redirect to login page
return deco
def deluge_page(func):
return check_session(deluge_page_noauth(func))
def auto_refreshed(func):
"decorator:adds a refresh header"
def deco(self, name):
if proxy.get_webui_config('auto_refresh'):
web.header("Refresh", "%i ; url=%s" %
(proxy.get_webui_config('auto_refresh_secs'),self_url()))
return func(self, name)
return deco
def error_page(error):
web.header("Content-Type", "text/html; charset=utf-8")
web.header("Cache-Control", "no-cache, must-revalidate")
print render.error(error)
def remote(func):
"decorator for remote api's"
def deco(self, name):
try:
print func(self, name)
except Exception, e:
print 'error:' + e.message
print '-'*20
print traceback.format_exc()
return deco
#/framework
#utils: #utils:
torrent_keys = ['distributed_copies', 'download_payload_rate', def check_pwd(pwd):
'download_rate', 'eta', 'is_seed', 'message', 'name', 'next_announce', m = md5()
'num_files', 'num_peers', 'num_pieces', 'num_seeds', 'paused', m.update(ws.config.get('pwd_salt'))
'piece_length','progress', 'ratio', 'total_done', 'total_download', m.update(pwd)
'total_payload_download', 'total_payload_upload', 'total_peers', return (m.digest() == ws.config.get('pwd_md5'))
'total_seeds', 'total_size', 'total_upload', 'total_wanted',
'tracker_status', 'upload_payload_rate', 'upload_rate',
'uploaded_memory','tracker','state']
def get_torrent_status(torrent_id): def get_torrent_status(torrent_id):
""" """
helper method. helper method.
enhance proxy.get_torrent_status with some extra data enhance ws.proxy.get_torrent_status with some extra data
""" """
status = proxy.get_torrent_status(torrent_id,torrent_keys) status = ws.proxy.get_torrent_status(torrent_id,TORRENT_KEYS)
status["id"] = torrent_id status["id"] = torrent_id
#for naming the status-images #for naming the status-images
@ -189,63 +75,25 @@ def get_torrent_status(torrent_id):
else: else:
status["action"] = "stop" status["action"] = "stop"
status["message"] += str(status["state"]) if status["paused"]:
status["message"] = _("Paused %s%%") % status['progress']
else:
status["message"] = "%s %i%%" % (STATE_MESSAGES[status["state"]]
, status['progress'])
#add some pre-calculated values #add some pre-calculated values
status.update({ status.update({
"calc_total_downloaded" : (common.fsize(status["total_done"]) "calc_total_downloaded" : (fsize(status["total_done"])
+ " (" + common.fsize(status["total_download"]) + ")"), + " (" + fsize(status["total_download"]) + ")"),
"calc_total_uploaded": (common.fsize(status['uploaded_memory'] "calc_total_uploaded": (fsize(status['uploaded_memory']
+ status["total_payload_upload"]) + " (" + status["total_payload_upload"]) + " ("
+ common.fsize(status["total_upload"]) + ")"), + fsize(status["total_upload"]) + ")"),
}) })
return Storage(status) #Storage for easy templating. return Storage(status) #Storage for easy templating.
#/utils #/utils
#template-defs:
def template_crop(text, end):
if len(text) > end:
return text[0:end - 3] + '...'
return text
def template_sort_head(id,name):
#got tired of doing these complex things inside templetor..
vars = web.input(sort=None, order=None)
active_up = False
active_down = False
order = 'down'
if vars.sort == id:
if vars.order == 'down':
order = 'up'
active_down = True
else:
active_up = True
return render.sort_column_head(id, name, order, active_up, active_down)
template.Template.globals.update({
'sort_head': template_sort_head,
'crop': template_crop,
'_': _ , #gettext/translations
'str': str, #because % in templetor is broken.
'sorted': sorted,
'get_config': proxy.get_webui_config,
'self_url': self_url,
'fspeed': common.fspeed,
'fsize': common.fsize,
'render': render, #for easy resuse of templates
'button_style': (proxy.get_webui_config('button_style')),
'rev': ('rev.' +
open(os.path.join(os.path.dirname(__file__),'revno')).read()),
'version': (
open(os.path.join(os.path.dirname(__file__),'version')).read()),
'get': lambda (var): getattr(web.input(**{var:None}),var) # unreadable :-(
})
#/template-defs
#routing: #routing:
urls = ( urls = (
"/login(.*)", "login", "/login(.*)", "login",
@ -274,19 +122,17 @@ class login:
@deluge_page_noauth @deluge_page_noauth
def GET(self, name): def GET(self, name):
vars = web.input(error = None) vars = web.input(error = None)
return render.login(vars.error) return ws.render.login(vars.error)
def POST(self, name): def POST(self, name):
vars = web.input(pwd = None ,redir = None) vars = web.input(pwd = None ,redir = None)
if proxy.check_pwd(vars.pwd): if check_pwd(vars.pwd):
#start new session #start new session
session_id = str(random.random()) start_session()
SESSIONS[session_id] = {"not":"used"}
setcookie("session_id", session_id)
do_redirect() do_redirect()
elif vars.redir: elif vars.redir:
seeother('/login?error=1&redir=' + urlquote(vars.redir)) seeother(url('/login',error=1,redir=vars.redir))
else: else:
seeother('/login?error=1') seeother('/login?error=1')
@ -303,7 +149,7 @@ class index:
vars = web.input(sort=None, order=None) vars = web.input(sort=None, order=None)
status_rows = [get_torrent_status(torrent_id) status_rows = [get_torrent_status(torrent_id)
for torrent_id in proxy.get_torrent_state()] for torrent_id in ws.proxy.get_torrent_state()]
#sorting: #sorting:
if vars.sort: if vars.sort:
@ -314,14 +160,14 @@ class index:
setcookie("order", vars.order) setcookie("order", vars.order)
setcookie("sort", vars.sort) setcookie("sort", vars.sort)
return render.index(status_rows) return ws.render.index(status_rows)
class torrent_info: class torrent_info:
"torrent details" "torrent details"
@auto_refreshed @auto_refreshed
@deluge_page @deluge_page
def GET(self, torrent_id): def GET(self, torrent_id):
return render.torrent_info(get_torrent_status(torrent_id)) return ws.render.torrent_info(get_torrent_status(torrent_id))
class torrent_pause: class torrent_pause:
"start/stop a torrent" "start/stop a torrent"
@ -329,16 +175,16 @@ class torrent_pause:
def POST(self, name): def POST(self, name):
vars = web.input(stop = None, start = None, redir = None) vars = web.input(stop = None, start = None, redir = None)
if vars.stop: if vars.stop:
proxy.pause_torrent(vars.stop) ws.proxy.pause_torrent(vars.stop)
elif vars.start: elif vars.start:
proxy.resume_torrent(vars.start) ws.proxy.resume_torrent(vars.start)
do_redirect() do_redirect()
class torrent_add: class torrent_add:
@deluge_page @deluge_page
def GET(self, name): def GET(self, name):
return render.torrent_add() return ws.render.torrent_add()
@check_session @check_session
def POST(self, name): def POST(self, name):
@ -347,13 +193,13 @@ class torrent_add:
if vars.url and vars.torrent.filename: if vars.url and vars.torrent.filename:
error_page(_("Choose an url or a torrent, not both.")) error_page(_("Choose an url or a torrent, not both."))
if vars.url: if vars.url:
proxy.add_torrent_url(vars.url) ws.proxy.add_torrent_url(vars.url)
do_redirect() do_redirect()
elif vars.torrent.filename: elif vars.torrent.filename:
data = vars.torrent.file.read() data = vars.torrent.file.read()
data_b64 = base64.b64encode(data) data_b64 = base64.b64encode(data)
#b64 because of strange bug-reports related to binary data #b64 because of strange bug-reports related to binary data
proxy.add_torrent_filecontent(vars.torrent.filename,data_b64) ws.proxy.add_torrent_filecontent(vars.torrent.filename,data_b64)
do_redirect() do_redirect()
else: else:
error_page(_("no data.")) error_page(_("no data."))
@ -362,23 +208,22 @@ class remote_torrent_add:
""" """
For use in remote scripts etc. For use in remote scripts etc.
POST pwd and torrent POST pwd and torrent
Example : curl -F torrent=@./test1.torrent -F pwd=deluge http://localhost:8112/remote/torrent/add"
""" """
@remote @remote
def POST(self, name): def POST(self, name):
vars = web.input(pwd = None, torrent = {}) vars = web.input(pwd = None, torrent = {})
if not proxy.check_pwd(vars.pwd): if not check_pwd(vars.pwd):
return 'error:wrong password' return 'error:wrong password'
data_b64 = base64.b64encode(vars.torrent.file.read()) data_b64 = base64.b64encode(vars.torrent.file.read())
proxy.add_torrent_filecontent(vars.torrent.filename,data_b64) ws.proxy.add_torrent_filecontent(vars.torrent.filename,data_b64)
return 'ok' return 'ok'
class torrent_delete: class torrent_delete:
@deluge_page @deluge_page
def GET(self, torrent_id): def GET(self, torrent_id):
return render.torrent_delete(get_torrent_status(torrent_id)) return ws.render.torrent_delete(get_torrent_status(torrent_id))
@check_session @check_session
def POST(self, name): def POST(self, name):
@ -386,42 +231,42 @@ class torrent_delete:
vars = web.input(data_also = None, torrent_also = None) vars = web.input(data_also = None, torrent_also = None)
data_also = bool(vars.data_also) data_also = bool(vars.data_also)
torrent_also = bool(vars.torrent_also) torrent_also = bool(vars.torrent_also)
proxy.remove_torrent(torrent_id, data_also, torrent_also) ws.proxy.remove_torrent(torrent_id, data_also, torrent_also)
do_redirect() do_redirect()
class pause_all: class pause_all:
@check_session @check_session
def POST(self, name): def POST(self, name):
for torrent_id in proxy.get_torrent_state(): for torrent_id in ws.proxy.get_torrent_state():
proxy.pause_torrent(torrent_id) ws.proxy.pause_torrent(torrent_id)
do_redirect() do_redirect()
class resume_all: class resume_all:
@check_session @check_session
def POST(self, name): def POST(self, name):
for torrent_id in proxy.get_torrent_state(): for torrent_id in ws.proxy.get_torrent_state():
proxy.resume_torrent(torrent_id) ws.proxy.resume_torrent(torrent_id)
do_redirect() do_redirect()
class refresh: class refresh:
@check_session @check_session
def POST(self, name): def POST(self, name):
auto_refresh = {'off':False, 'on':True}[name] auto_refresh = {'off':'0', 'on':'1'}[name]
proxy.set_webui_config('auto_refresh', auto_refresh) setcookie('auto_refresh',auto_refresh)
do_redirect() do_redirect()
class refresh_set: class refresh_set:
@deluge_page @deluge_page
def GET(self, name): def GET(self, name):
return render.refresh_form() return ws.render.refresh_form()
@check_session @check_session
def POST(self, name): def POST(self, name):
vars = web.input(refresh = 0) vars = web.input(refresh = 0)
refresh = int(vars.refresh) refresh = int(vars.refresh)
if refresh > 0: if refresh > 0:
proxy.set_webui_config('refresh', refresh) setcookie('auto_refresh','1')
proxy.set_webui_config('auto_refresh', True) setcookie('auto_refresh_secs', str(refresh))
do_redirect() do_redirect()
else: else:
error_page(_('refresh must be > 0')) error_page(_('refresh must be > 0'))
@ -429,11 +274,21 @@ class refresh_set:
class about: class about:
@deluge_page_noauth @deluge_page_noauth
def GET(self, name): def GET(self, name):
return render.about() return ws.render.about()
#/pages #/pages
def WebServer():
return create_webserver(urls, globals())
def run():
server = WebServer()
try:
server.start()
except KeyboardInterrupt:
server.stop()
if __name__ == "__main__": if __name__ == "__main__":
web.run(urls, globals()) run()

File diff suppressed because it is too large Load Diff

View File

@ -3,20 +3,20 @@ $def with (method, url, title, image='')
<form method="$method" action="$url" class="deluge_button"> <form method="$method" action="$url" class="deluge_button">
<button type="submit" class="deluge_button"> <button type="submit" class="deluge_button">
<input type="hidden" name="redir" value="$self_url()"> <input type="hidden" name="redir" value="$self_url()">
$if (button_style == 0): $if (get_config('button_style') == 0):
$title $title
$if image: $if image:
<image src="/static/images/$image" class="button" alt="$title"/> <image src="/static/images/$image" class="button" alt="$title"/>
$if (button_style == 1): $if (get_config('button_style') == 1):
$if image: $if image:
<image src="/static/images/$image" class="button" alt="$title"/> <image src="/static/images/$image" class="button" alt="$title"/>
$else: $else:
$title $title
$if (button_style == 2): $if (get_config('button_style') == 2):
$title $title
</button> </button>
</form> </form>
</div> </div>

View File

@ -1,8 +1,8 @@
<div id='refresh_panel'> <div id='refresh_panel'>
<div class="panel" > <div class="panel" >
$_('Auto refresh:') $_('Auto refresh:')
$if get_config('auto_refresh'): $if getcookie('auto_refresh') == '1':
($(get_config('refresh')) $_('seconds')) &nbsp; ($getcookie('auto_refresh_secs')) $_('seconds')) &nbsp;
$:render.part_button('GET', '/refresh/set', _('Set'), 'tango/preferences-system.png') $:render.part_button('GET', '/refresh/set', _('Set'), 'tango/preferences-system.png')
$:render.part_button('POST', '/refresh/off', _('Disable'), 'tango/process-stop.png') $:render.part_button('POST', '/refresh/off', _('Disable'), 'tango/process-stop.png')
$else: $else:
@ -10,4 +10,4 @@ $else:
$:render.part_button('POST', '/refresh/on', _('Enable'), 'tango/view-refresh.png') $:render.part_button('POST', '/refresh/on', _('Enable'), 'tango/view-refresh.png')
$#end $#end
</div> </div>
</div> </div>

View File

@ -2,9 +2,10 @@ $:render.header(_('Set Timeout'))
<div class="panel"> <div class="panel">
<form action="/refresh/set" method="POST"> <form action="/refresh/set" method="POST">
$_('Refresh page every:') $_('Refresh page every:')
<input type="text" name="refresh" value="$get_config('refresh')" size="3"> <input type="text" name="refresh" value="$getcookie('auto_refresh_secs')"
size="3">
$_('seconds') $_('seconds')
<input type="submit" value="$_('Set')"> <input type="submit" value="$_('Set')">
</form> </form>
</div> </div>
$:render.footer() $:render.footer()

View File

@ -0,0 +1,81 @@
#!/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.
import os
import deluge
from deluge.common import INSTALL_PREFIX
import random
import pickle
from webpy022 import template
random.seed()
config_file = deluge.common.CONFIG_DIR + "/webui.conf"
#a bit hacky way of detecting i'm in the deluge gui or in a process :(
if not hasattr(deluge,'pref'):
import dbus
bus = dbus.SessionBus()
proxy = bus.get_object("org.deluge_torrent.dbusplugin"
, "/org/deluge_torrent/DelugeDbusPlugin")
config = pickle.load(open(config_file))
render = template.render('templates/%s/' % config.get('template'),
cache=config.get('cache_templates'))
def init():
#appy possibly changed config-vars, only called in when runing inside gtk.
from dbus_interface import get_dbus_manager
globals()['proxy'] = get_dbus_manager()
globals()['config'] = deluge.pref.Preferences(config_file, False)
globals()['render'] = template.render('templates/%s/' % config.get('template'),
cache=config.get('cache_templates'))
REVNO = open(os.path.join(os.path.dirname(__file__),'revno')).read()
VERSION = open(os.path.join(os.path.dirname(__file__),'version')).read()
TORRENT_KEYS = ['distributed_copies', 'download_payload_rate',
'download_rate', 'eta', 'is_seed', 'name', 'next_announce',
'num_files', 'num_peers', 'num_pieces', 'num_seeds', 'paused',
'piece_length','progress', 'ratio', 'total_done', 'total_download',
'total_payload_download', 'total_payload_upload', 'total_peers',
'total_seeds', 'total_size', 'total_upload', 'total_wanted',
'tracker_status', 'upload_payload_rate', 'upload_rate',
'uploaded_memory','tracker','state']
STATE_MESSAGES = (_("Queued"),
_("Checking"),
_("Connecting"),
_("Downloading Metadata"),
_("Downloading"),
_("Finished"),
_("Seeding"),
_("Allocating"))

View File

@ -0,0 +1,81 @@
#!/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.
import os
import deluge
from deluge.common import INSTALL_PREFIX
import random
import pickle
from webpy022 import template
random.seed()
config_file = deluge.common.CONFIG_DIR + "/webui.conf"
#a bit hacky way of detecting i'm in the deluge gui or in a process :(
if not hasattr(deluge,'pref'):
import dbus
bus = dbus.SessionBus()
proxy = bus.get_object("org.deluge_torrent.dbusplugin"
, "/org/deluge_torrent/DelugeDbusPlugin")
config = pickle.load(open(config_file))
render = template.render('templates/%s/' % config.get('template'),
cache=config.get('cache_templates'))
def init():
#appy possibly changed config-vars, only called in when runing inside gtk.
from dbus_interface import get_dbus_manager
globals()['proxy'] = get_dbus_manager()
globals()['config'] = deluge.pref.Preferences(config_file, False)
globals()['render'] = template.render('templates/%s/' % config.get('template'),
cache=config.get('cache_templates'))
REVNO = open(os.path.join(os.path.dirname(__file__),'revno')).read()
VERSION = open(os.path.join(os.path.dirname(__file__),'version')).read()
TORRENT_KEYS = ['distributed_copies', 'download_payload_rate',
'download_rate', 'eta', 'is_seed', 'name', 'next_announce',
'num_files', 'num_peers', 'num_pieces', 'num_seeds', 'paused',
'piece_length','progress', 'ratio', 'total_done', 'total_download',
'total_payload_download', 'total_payload_upload', 'total_peers',
'total_seeds', 'total_size', 'total_upload', 'total_wanted',
'tracker_status', 'upload_payload_rate', 'upload_rate',
'uploaded_memory','tracker','state']
STATE_MESSAGES = (_("Queued"),
_("Checking"),
_("Connecting"),
_("Downloading Metadata"),
_("Downloading"),
_("Finished"),
_("Seeding"),
_("Allocating"))