webui sync r168

This commit is contained in:
Marcos Pinto 2007-12-22 08:15:51 +00:00
commit b803d39d63
33 changed files with 204 additions and 44 deletions

View file

@ -97,7 +97,7 @@ class plugin_WebUi(object):
if status[0] == 0: if status[0] == 0:
os.kill(int(status[1].split()[0]), 9) os.kill(int(status[1].split()[0]), 9)
time.sleep(1) #safe time to wait for kill to finish. time.sleep(1) #safe time to wait for kill to finish.
self.config_file = os.path.join(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)
try: try:
self.config.load() self.config.load()
@ -162,7 +162,7 @@ class plugin_WebUi(object):
else: else:
print 'Start Webui(in process)..' print 'Start Webui(in process)..'
server_bin = os.path.join(os.path.dirname(__file__), 'run_webserver') server_bin = os.path.dirname(__file__) + '/run_webserver'
self.proc = Popen((server_bin,'env=0.5')) self.proc = Popen((server_bin,'env=0.5'))
def kill_server(self): def kill_server(self):

View file

@ -11,9 +11,9 @@ http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
__all__ = ["debugerror", "djangoerror"] __all__ = ["debugerror", "djangoerror"]
import sys, urlparse, pprint import sys, urlparse, pprint
from webpy022.net import websafe from lib.webpy022.net import websafe
from webpy022.template import Template from lib.webpy022.template import Template
import webpy022.webapi as web import lib.webpy022.webapi as web
import webserver_common as ws import webserver_common as ws
from traceback import format_tb from traceback import format_tb

View file

@ -34,13 +34,15 @@
import webserver_common as ws import webserver_common as ws
from webserver_framework import * from webserver_framework import *
import webpy022 as web import lib.webpy022 as web
from webpy022.http import seeother, url from lib.webpy022.http import seeother, url
import base64 import base64
from operator import attrgetter from operator import attrgetter
import os import os
from json_api import json_api
#routing: #routing:
urls = ( urls = (
"/login", "login", "/login", "login",
@ -64,6 +66,7 @@ urls = (
"/logout", "logout", "/logout", "logout",
#remote-api: #remote-api:
"/remote/torrent/add(.*)", "remote_torrent_add", "/remote/torrent/add(.*)", "remote_torrent_add",
"/json/(.*)","json_api",
#static: #static:
"/static/(.*)", "static", "/static/(.*)", "static",
"/template/static/(.*)", "template_static", "/template/static/(.*)", "template_static",

132
plugins/WebUi/json_api.py Normal file
View file

@ -0,0 +1,132 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# webserver_framework.py
#
# 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.
"""
json api.
only used for XUL and/or external scripts
it would be possible not to incluse the python-json dependency.
"""
import deluge.ui.client as proxy
from new import instancemethod
from inspect import getargspec
from webserver_framework import remote,ws,get_torrent_status,log
proxy = ws.proxy
def to_json(obj):
from lib.pythonize import pythonize
obj = pythonize(obj)
try:
import json
return json.write(obj)
except ImportError:
raise ImportError("""Install python-json using your package-manager
http://sourceforge.net/projects/json-py/""")
class json_api:
"""
eperimental json api
generic proxy for all methods onm self.
"""
illegal_methods = ['shutdown', 'socket', 'xmlrpclib','pickle','os',
'is_localhost','CoreProxy','connect_on_new_core', 'connect_on_no_core',
'connected','deluge','GET','POST']
def __init__(self):
self._add_proxy_methods()
@remote
def GET(self,name):
if name.startswith('_'):
raise AttributeError('_ methods are illegal!')
if name in self.illegal_methods:
raise AttributeError('Illegal method , I smell a rat!')
if not(hasattr(self,name)):
raise AttributeError('No such Method')
method = getattr(self,name)
kwargs = {}
result = method(**kwargs)
return to_json(result)
POST = GET
def list_methods(self):
"""
list all json methods
returns a dict of {methodname:{args:[list of kwargs],doc:'string'},..}
"""
methods = [getattr(self,m) for m in dir(self)
if not m.startswith('_')
and (not m in self.illegal_methods)
and callable(getattr(self,m))
]
return dict([(f.__name__,
{'args':getargspec(f)[0],'doc':(f.__doc__ or '').strip()})
for f in methods])
def _add_proxy_methods(self):
methods = [getattr(proxy,m) for m in dir(proxy)
if not m.startswith('_')
and (not m in self.illegal_methods)
and callable(getattr(proxy,m))
]
for m in methods:
setattr(self,m.__name__,m)
#extra's:
def list_torrents(self):
return [get_torrent_status(torrent_id)
for torrent_id in ws.proxy.get_session_state()]
get_torrent_status = get_torrent_status
if __name__ == '__main__':
from pprint import pprint
#proxy.set_core_uri('http://localhost:58846') #How to configure this?
j = json_api()
if True:
print 'list-methods:'
methods = j.list_methods()
names = methods.keys()
names.sort()
for name in names:
m = methods[name]
print "%s(%s)\n %s\n" % (name , m['args'] , m['doc'])
#j.GET('list_torrents')
j.POST('list_torrents')

View file

View file

@ -0,0 +1,8 @@
This folder may only contain general purpose utilities/files/tools.
They should be usable outside of deluge.
Disclaimer:
Some may have been adapted to work better with deluge.
But they will not other import parts of deluge or Webui.

View file

@ -1 +0,0 @@
165

View file

@ -47,7 +47,7 @@ $:render.header(_('Torrent list'))
<div id="tableContainer" class="tableContainer"> <div id="tableContainer" class="tableContainer">
<table class="torrent_list" border=1 id="torrent_list"> <table class="torrent_list" border=0 cellspacing=0 cellpadding=2 id="torrent_list">
<thead class="fixedHeader"> <thead class="fixedHeader">
<tr> <tr>
$:(sort_head('calc_state_str', 'S')) $:(sort_head('calc_state_str', 'S'))
@ -67,9 +67,10 @@ $:render.header(_('Torrent list'))
</tr> </tr>
</thead> </thead>
<tbody class="scrollContent"> <tbody class="scrollContent">
$altrow(True)
$#4-space indentation is mandatory for for-loops in templetor! $#4-space indentation is mandatory for for-loops in templetor!
$for torrent in torrent_list: $for torrent in torrent_list:
<tr class="torrent_table" onclick="on_click_row(event, '$torrent.id')" id="torrent_$torrent.id"> <tr class="$altrow()" onclick="on_click_row(event, '$torrent.id')" id="torrent_$torrent.id">
<td> <td>
<form action="/torrent/$torrent.action/$torrent.id" method="POST" <form action="/torrent/$torrent.action/$torrent.id" method="POST"
class="pause_resume"> class="pause_resume">

View file

@ -78,6 +78,19 @@ tr.torrent_table:hover {
background-color:#68a; background-color:#68a;
} }
tr.altrow0:hover {
background-color:#68a;
}
tr.altrow1:hover {
background-color:#68a;
}
tr.altrow1{
background-color: #37506f;
}
tr.torrent_table_selected { tr.torrent_table_selected {
background-color:#900; background-color:#900;
} }
@ -85,6 +98,9 @@ tr.torrent_table_selected {
th.torrent_table:hover { th.torrent_table:hover {
background-color:#68a; background-color:#68a;
} }
th.torrent_table {
background-color: #37506f;
}
img.button { img.button {
margin-bottom:0px; margin-bottom:0px;

View file

@ -45,6 +45,9 @@ function on_click_row_js(e, id) {
function select_row(id){ function select_row(id){
var row = get_row(id); var row = get_row(id);
if (row) { if (row) {
if (!(row.default_class_name)) {
row.default_class_name = row.className;
}
row.className = 'torrent_table_selected'; row.className = 'torrent_table_selected';
state.selected_rows[state.selected_rows.length] = id; state.selected_rows[state.selected_rows.length] = id;
setCookie('selected_rows',state.selected_rows); setCookie('selected_rows',state.selected_rows);
@ -54,7 +57,7 @@ function select_row(id){
function deselect_row(id){ function deselect_row(id){
var row = get_row(id); var row = get_row(id);
if (row) { if (row) {
row.className = 'torrent_table' row.className = row.default_class_name
/*remove from state.selected_rows*/ /*remove from state.selected_rows*/
var idx = state.selected_rows.indexOf(id); var idx = state.selected_rows.indexOf(id);
state.selected_rows.splice(idx,1); state.selected_rows.splice(idx,1);

View file

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

View file

@ -1,5 +0,0 @@
revision-id: mvoncken@gmail.com-20070930083408-sv8mo0mi1rbjnfvk
date: 2007-12-05 15:10:08 +0200
build-date: 2007-12-05 15:34:50 +0200
revno: 165
branch-nick: WebUi

View file

@ -31,8 +31,8 @@
""" """
initializes config,render and proxy. initializes config,render and proxy.
contains all hacks to support running in process0.5 ,run inside-gtk0.5 and All hacks go here, so this is a really ugly source-file..
run in process0.6 Support running in process0.5 ,run inside-gtk0.5 and run in process0.6
""" """
import os import os
@ -41,7 +41,7 @@ import random
import pickle import pickle
import sys import sys
import base64 import base64
from webpy022 import template from lib.webpy022 import template
random.seed() random.seed()
webui_path = os.path.dirname(__file__) webui_path = os.path.dirname(__file__)
@ -163,7 +163,8 @@ def init_gtk_05():
def init_logger(): def init_logger():
#only for 0.5.. #only for 0.5..
import logging import logging
logging.basicConfig(level=logging.DEBUG,format="[%(levelname)-8s] %(module)s:%(lineno)d %(message)s") logging.basicConfig(level=logging.DEBUG,
format="[%(levelname)s] %(message)s")
globals()['log'] = logging globals()['log'] = logging

View file

@ -40,13 +40,13 @@ Todo's before stable:
-clear finished? -clear finished?
-torrent files. -torrent files.
""" """
import webpy022 as web import lib.webpy022 as web
from webpy022.webapi import cookies, setcookie as w_setcookie from lib.webpy022.webapi import cookies, setcookie as w_setcookie
from webpy022.http import seeother, url from lib.webpy022.http import seeother, url
from webpy022 import template,changequery as self_url from lib.webpy022 import template,changequery as self_url
from webpy022.utils import Storage from lib.webpy022.utils import Storage
from static_handler import static_handler from lib.static_handler import static_handler
from deluge.common import fsize,fspeed from deluge.common import fsize,fspeed
@ -144,7 +144,8 @@ def check_session(func):
return func if session is valid, else redirect to login page. return func if session is valid, else redirect to login page.
""" """
def deco(self, name = None): def deco(self, name = None):
log.debug('%s.%s(name=%s)' % (self.__class__.__name__,func.__name__,name)) log.debug('%s.%s(name=%s)' % (self.__class__.__name__, func.__name__,
name))
vars = web.input(redir_after_login = None) vars = web.input(redir_after_login = None)
ck = cookies() ck = cookies()
if ck.has_key("session_id") and ck["session_id"] in ws.SESSIONS: if ck.has_key("session_id") and ck["session_id"] in ws.SESSIONS:
@ -282,6 +283,7 @@ def filter_torrent_state(torrent_list,filter_name):
,'queued':lambda t: (t.paused and not t.user_paused) ,'queued':lambda t: (t.paused and not t.user_paused)
,'paused':lambda t: (t.user_paused) ,'paused':lambda t: (t.user_paused)
,'seeding':lambda t:(t.is_seed and not t.paused ) ,'seeding':lambda t:(t.is_seed and not t.paused )
,'active':lambda t: (t.download_rate > 0 or t.upload_rate > 0)
} }
filter_func = filters[filter_name] filter_func = filters[filter_name]
return [t for t in torrent_list if filter_func(t)] return [t for t in torrent_list if filter_func(t)]
@ -300,7 +302,8 @@ def category_tabs(torrent_list):
(_('Downloading'),'downloading') , (_('Downloading'),'downloading') ,
(_('Queued'),'queued') , (_('Queued'),'queued') ,
(_('Paused'),'paused') , (_('Paused'),'paused') ,
(_('Seeding'),'seeding') (_('Seeding'),'seeding'),
(_('Active'),'active')
]: ]:
title += ' (%s)' % ( title += ' (%s)' % (
len(filter_torrent_state(torrent_list, filter_name)), ) len(filter_torrent_state(torrent_list, filter_name)), )
@ -349,6 +352,17 @@ def template_part_stats():
def get_config(var): def get_config(var):
return ws.config.get(var) return ws.config.get(var)
irow = 0
def altrow(reset = False):
global irow
if reset:
irow = 1
return
irow +=1
irow = irow % 2
return "altrow%s" % irow
template.Template.globals.update({ template.Template.globals.update({
'sort_head': template_sort_head, 'sort_head': template_sort_head,
'part_stats':template_part_stats, 'part_stats':template_part_stats,
@ -357,6 +371,7 @@ template.Template.globals.update({
'_': _ , #gettext/translations '_': _ , #gettext/translations
'str': str, #because % in templetor is broken. 'str': str, #because % in templetor is broken.
'sorted': sorted, 'sorted': sorted,
'altrow':altrow,
'get_config': get_config, 'get_config': get_config,
'self_url': self_url, 'self_url': self_url,
'fspeed': common.fspeed, 'fspeed': common.fspeed,
@ -370,9 +385,9 @@ template.Template.globals.update({
#/template-defs #/template-defs
def create_webserver(urls, methods): def create_webserver(urls, methods):
from webpy022.request import webpyfunc from lib.webpy022.request import webpyfunc
from webpy022 import webapi from lib.webpy022 import webapi
from gtk_cherrypy_wsgiserver import CherryPyWSGIServer from lib.gtk_cherrypy_wsgiserver import CherryPyWSGIServer
import os import os
func = webapi.wsgifunc(webpyfunc(urls, methods, False)) func = webapi.wsgifunc(webpyfunc(urls, methods, False))