graph plugin; initial commit
This commit is contained in:
parent
92608b436b
commit
1cb4559362
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
mkdir temp
|
||||||
|
export PYTHONPATH=./temp
|
||||||
|
python setup.py build develop --install-dir ./temp
|
||||||
|
cp ./temp/Graph.egg-link ~/.config/deluge/plugins
|
||||||
|
rm -fr ./temp
|
|
@ -0,0 +1,65 @@
|
||||||
|
#
|
||||||
|
# __init__.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
#
|
||||||
|
# Basic plugin template created by:
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
|
||||||
|
#
|
||||||
|
# Deluge is free software.
|
||||||
|
#
|
||||||
|
# You may redistribute it and/or modify it under the terms of the
|
||||||
|
# GNU General Public License, as published by the Free Software
|
||||||
|
# Foundation; either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# deluge 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 deluge. 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
|
||||||
|
|
||||||
|
from deluge.log import LOG as log
|
||||||
|
|
||||||
|
from deluge.plugins.init import PluginBase
|
||||||
|
|
||||||
|
class CorePlugin(PluginBase):
|
||||||
|
def __init__(self, plugin_api, plugin_name):
|
||||||
|
# Load the Core portion of the plugin
|
||||||
|
try:
|
||||||
|
from core import Core
|
||||||
|
self.plugin = Core(plugin_api, plugin_name)
|
||||||
|
except Exception, e:
|
||||||
|
log.debug("Did not load a Core plugin: %s", e)
|
||||||
|
|
||||||
|
class WebUIPlugin(PluginBase):
|
||||||
|
def __init__(self, plugin_api, plugin_name):
|
||||||
|
try:
|
||||||
|
from webui import WebUI
|
||||||
|
self.plugin = WebUI(plugin_api, plugin_name)
|
||||||
|
except Exception, e:
|
||||||
|
log.debug("Did not load a WebUI plugin: %s", e)
|
||||||
|
|
||||||
|
class GtkUIPlugin(PluginBase):
|
||||||
|
def __init__(self, plugin_api, plugin_name):
|
||||||
|
# Load the GtkUI portion of the plugin
|
||||||
|
try:
|
||||||
|
from gtkui import GtkUI
|
||||||
|
self.plugin = GtkUI(plugin_api, plugin_name)
|
||||||
|
except Exception, e:
|
||||||
|
log.debug("Did not load a GtkUI plugin: %s", e)
|
|
@ -0,0 +1,93 @@
|
||||||
|
#
|
||||||
|
# core.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
# Copyright (C) Marcos Pinto 2007 <markybob@gmail.com>
|
||||||
|
#
|
||||||
|
# Deluge is free software.
|
||||||
|
#
|
||||||
|
# You may redistribute it and/or modify it under the terms of the
|
||||||
|
# GNU General Public License, as published by the Free Software
|
||||||
|
# Foundation; either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# deluge 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 deluge. 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
|
||||||
|
|
||||||
|
import deluge
|
||||||
|
from deluge.log import LOG as log
|
||||||
|
from deluge.plugins.corepluginbase import CorePluginBase
|
||||||
|
from deluge import component
|
||||||
|
import gobject
|
||||||
|
#from deluge.plugins.coreclient import client #1.1 and later only
|
||||||
|
#client: see http://dev.deluge-torrent.org/wiki/Development/UiClient#Remoteapi
|
||||||
|
|
||||||
|
DEFAULT_PREFS = {
|
||||||
|
"test":"NiNiNi",
|
||||||
|
"update_interval":2000, #2 seconds.
|
||||||
|
"length":150, # 2 seconds * 150 --> 5 minutes.
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
port of the old NetworkGraph Plugin.
|
||||||
|
"""
|
||||||
|
class Core(CorePluginBase):
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
self.core = component.get("Core")
|
||||||
|
self.savedUpSpeeds = []
|
||||||
|
self.savedDownSpeeds = []
|
||||||
|
self.savedConnections = []
|
||||||
|
self.config = deluge.configmanager.ConfigManager("graph.conf", DEFAULT_PREFS)
|
||||||
|
self.update_timer = gobject.timeout_add(self.config.get("update_interval"), self.update_stats)
|
||||||
|
self.length = self.config.get("length")
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
gobject.source_remove(self.update_timer)
|
||||||
|
|
||||||
|
def update_stats(self):
|
||||||
|
try:
|
||||||
|
status = self.core.session.status()
|
||||||
|
self.savedUpSpeeds.insert(0, int(status.payload_upload_rate))
|
||||||
|
if len(self.savedUpSpeeds) > self.length:
|
||||||
|
self.savedUpSpeeds.pop()
|
||||||
|
self.savedDownSpeeds.insert(0, int(status.payload_download_rate))
|
||||||
|
if len(self.savedDownSpeeds) > self.length:
|
||||||
|
self.savedDownSpeeds.pop()
|
||||||
|
except Exception,e:
|
||||||
|
log.error(e.message)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def export_get_upload(self,length=None):
|
||||||
|
return self.savedUpSpeeds
|
||||||
|
|
||||||
|
def export_get_download(self,length=None):
|
||||||
|
return self.savedDownSpeeds
|
||||||
|
|
||||||
|
def export_set_config(self, config):
|
||||||
|
"sets the config dictionary"
|
||||||
|
for key in config.keys():
|
||||||
|
self.config[key] = config[key]
|
||||||
|
self.config.save()
|
||||||
|
|
||||||
|
def export_get_config(self):
|
||||||
|
"returns the config dictionary"
|
||||||
|
return self.config.get_config()
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||||
|
<!--Generated with glade3 3.4.5 on Fri Aug 8 23:34:44 2008 -->
|
||||||
|
<glade-interface>
|
||||||
|
<widget class="GtkWindow" id="window1">
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHBox" id="prefs_box">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label" translatable="yes">Test config value:</property>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkEntry" id="txt_test">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
</glade-interface>
|
|
@ -0,0 +1,183 @@
|
||||||
|
#graph.py
|
||||||
|
"""
|
||||||
|
port of old plugin by markybob.
|
||||||
|
"""
|
||||||
|
import cairo
|
||||||
|
import math
|
||||||
|
from deluge.log import LOG as log
|
||||||
|
import deluge.common
|
||||||
|
import time
|
||||||
|
from deluge.ui.client import aclient
|
||||||
|
|
||||||
|
class NetworkGraph:
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.width = 100
|
||||||
|
self.height = 100
|
||||||
|
|
||||||
|
self.length = 150
|
||||||
|
|
||||||
|
self.savedUpSpeeds = []
|
||||||
|
self.savedDownSpeeds = []
|
||||||
|
|
||||||
|
self.download_line = True
|
||||||
|
self.download_fill = True
|
||||||
|
self.upload_line = True
|
||||||
|
self.upload_fill = True
|
||||||
|
self.download_line_color = (0, 0.75,0, 1.0)
|
||||||
|
self.download_fill_color = (0.6 ,1.1 , 0.6, 1.0)
|
||||||
|
self.upload_line_color = (0, 0, 1.0, 0.75)
|
||||||
|
self.upload_fill_color = (0.43,0.43,1.1, 0.5)
|
||||||
|
self.mean_selected = True
|
||||||
|
self.legend_selected = True
|
||||||
|
self.max_selected = True
|
||||||
|
self.line_size = 4
|
||||||
|
self.black = (0, 0 , 0,)
|
||||||
|
self.interval = 2000 #2secs
|
||||||
|
self.text_bg = (255, 255 , 255, 128) #prototyping.
|
||||||
|
|
||||||
|
def async_request(self):
|
||||||
|
"""
|
||||||
|
convenience method, see test.py
|
||||||
|
"""
|
||||||
|
aclient.graph_get_upload(self.set_upload)
|
||||||
|
aclient.graph_get_download(self.set_download)
|
||||||
|
aclient.graph_get_config(self.set_config)
|
||||||
|
|
||||||
|
#async callbacks:
|
||||||
|
def set_config(self, config):
|
||||||
|
self.length = config["stats_length"]
|
||||||
|
self.interval = config["update_interval"]
|
||||||
|
|
||||||
|
def set_upload(self , upload):
|
||||||
|
self.savedUpSpeeds = upload
|
||||||
|
|
||||||
|
def set_download(self , download):
|
||||||
|
self.savedDownSpeeds = download
|
||||||
|
|
||||||
|
|
||||||
|
def draw(self, width, height):
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
|
||||||
|
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width,self.height)
|
||||||
|
self.ctx = cairo.Context(self.surface)
|
||||||
|
|
||||||
|
if (self.download_fill or self.download_line) and (self.upload_fill or self.upload_line):
|
||||||
|
maxSpeed = max(max(self.savedDownSpeeds),max(self.savedUpSpeeds))
|
||||||
|
meanSpeed = max(sum(self.savedUpSpeeds) /len(self.savedUpSpeeds), sum(self.savedDownSpeeds)/len(self.savedDownSpeeds))
|
||||||
|
elif self.download_fill or self.download_line:
|
||||||
|
maxSpeed = max(self.savedDownSpeeds)
|
||||||
|
meanSpeed = sum(self.savedDownSpeeds)/len(self.savedDownSpeeds)
|
||||||
|
elif self.upload_fill or self.upload_line:
|
||||||
|
maxSpeed = max(self.savedUpSpeeds)
|
||||||
|
meanSpeed = sum(self.savedUpSpeeds) /len(self.savedUpSpeeds)
|
||||||
|
else:
|
||||||
|
maxSpeed = 0
|
||||||
|
|
||||||
|
|
||||||
|
if maxSpeed > 0:
|
||||||
|
|
||||||
|
if self.max_selected:
|
||||||
|
self.drawText(deluge.common.fspeed(maxSpeed),4,2)
|
||||||
|
|
||||||
|
if self.download_fill:
|
||||||
|
self.drawSpeedPoly(self.savedDownSpeeds,self.download_fill_color, maxSpeed, True)
|
||||||
|
|
||||||
|
if self.download_line:
|
||||||
|
self.drawSpeedPoly(self.savedDownSpeeds,self.download_line_color,maxSpeed, False)
|
||||||
|
|
||||||
|
if self.upload_fill:
|
||||||
|
self.drawSpeedPoly(self.savedUpSpeeds,self.upload_fill_color,maxSpeed, True)
|
||||||
|
|
||||||
|
if self.upload_line:
|
||||||
|
self.drawSpeedPoly(self.savedUpSpeeds,self.upload_line_color,maxSpeed, False)
|
||||||
|
|
||||||
|
|
||||||
|
if self.mean_selected:
|
||||||
|
mean = int(self.height - 1 - ((self.height-28)*meanSpeed/maxSpeed))
|
||||||
|
|
||||||
|
self.drawLine(self.black, 0,mean, self.width, mean)
|
||||||
|
self.drawText(deluge.common.fspeed(meanSpeed), 4, mean - 12 - 2)
|
||||||
|
|
||||||
|
if self.legend_selected:
|
||||||
|
self.drawLegend()
|
||||||
|
return self.surface
|
||||||
|
|
||||||
|
|
||||||
|
def tracePath(self, speeds, maxSpeed):
|
||||||
|
lineWidth = self.line_size
|
||||||
|
|
||||||
|
self.ctx.set_line_width(lineWidth)
|
||||||
|
self.ctx.move_to(self.width + lineWidth,self.height + lineWidth)
|
||||||
|
self.ctx.line_to(self.width + lineWidth,int(self.height-((self.height-28)*speeds[0]/maxSpeed)))
|
||||||
|
|
||||||
|
for i in range(len(speeds)):
|
||||||
|
self.ctx.line_to(int(self.width-1-((i*self.width)/(self.length-1))),int(self.height-1-((self.height-28)*speeds[i]/maxSpeed)))
|
||||||
|
|
||||||
|
self.ctx.line_to(int(self.width-1-(((len(speeds)-1)*self.width)/(self.length-1))),int(self.height)-1 + lineWidth)
|
||||||
|
self.ctx.close_path()
|
||||||
|
|
||||||
|
def drawSpeedPoly(self, speeds, color, maxSpeed, fill):
|
||||||
|
self.tracePath(speeds, maxSpeed)
|
||||||
|
self.ctx.set_source_rgba(color[0],color[1],color[2], color[3])
|
||||||
|
|
||||||
|
if fill:
|
||||||
|
self.ctx.fill()
|
||||||
|
else:
|
||||||
|
self.ctx.stroke()
|
||||||
|
|
||||||
|
def drawLegend(self):
|
||||||
|
showDown = self.download_fill or self.download_line
|
||||||
|
showUp = self.upload_fill or self.upload_line
|
||||||
|
downBox_X = self.width-113
|
||||||
|
|
||||||
|
self.drawText("Download:", self.width-180,3)
|
||||||
|
self.drawText("Upload:", self.width-80,3)
|
||||||
|
|
||||||
|
if self.download_fill and self.download_line:
|
||||||
|
self.drawRect(self.download_line_color,downBox_X,5,12,12)
|
||||||
|
self.drawRect(self.download_fill_color,downBox_X+12,5,12,12)
|
||||||
|
elif self.download_fill:
|
||||||
|
self.drawRect(self.download_fill_color,downBox_X,5,24,12)
|
||||||
|
elif self.download_line:
|
||||||
|
self.drawRect(self.download_line_color,downBox_X,5,24,12)
|
||||||
|
|
||||||
|
if self.upload_fill and self.upload_line:
|
||||||
|
self.drawRect(self.upload_line_color,self.width-30,5,12,12)
|
||||||
|
self.drawRect(self.upload_fill_color,self.width-18,5,12,12)
|
||||||
|
elif self.upload_fill:
|
||||||
|
self.drawRect(self.upload_fill_color,self.width-30,5,24,12)
|
||||||
|
elif self.upload_line:
|
||||||
|
self.drawRect(self.upload_line_color,self.width-30,5,24,12)
|
||||||
|
|
||||||
|
if True:
|
||||||
|
txt_end = time.strftime("%H:%M:%S")
|
||||||
|
txt_start = time.strftime("%H:%M:%S",time.localtime(time.time() - self.length * (self.interval / 1000.0) ))
|
||||||
|
self.length * self.interval
|
||||||
|
self.drawText(txt_end, self.width-60,self.height - 20)
|
||||||
|
self.drawText(txt_start, 4 ,self.height - 20)
|
||||||
|
|
||||||
|
|
||||||
|
def drawText(self,text,x,y):
|
||||||
|
self.ctx.set_font_size(12)
|
||||||
|
self.ctx.move_to(x, y +12)
|
||||||
|
self.ctx.set_source_rgba(*self.black)
|
||||||
|
self.ctx.show_text(text)
|
||||||
|
|
||||||
|
def drawRect(self,color,x,y,height,width):
|
||||||
|
self.ctx.set_source_rgba(color[0],color[1],color[2],color[3],)
|
||||||
|
self.ctx.rectangle(x,y,height,width)
|
||||||
|
self.ctx.fill()
|
||||||
|
|
||||||
|
def drawLine(self,color,x1,y1,x2,y2):
|
||||||
|
self.ctx.set_source_rgba(*color)
|
||||||
|
self.ctx.set_line_width(1)
|
||||||
|
self.ctx.move_to(x1, y1)
|
||||||
|
self.ctx.line_to(x2, y2)
|
||||||
|
self.ctx.stroke()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import test
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
#
|
||||||
|
# gtkui.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
#
|
||||||
|
# Basic plugin template created by:
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
|
||||||
|
#
|
||||||
|
# Deluge is free software.
|
||||||
|
#
|
||||||
|
# You may redistribute it and/or modify it under the terms of the
|
||||||
|
# GNU General Public License, as published by the Free Software
|
||||||
|
# Foundation; either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# deluge 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 deluge. 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
|
||||||
|
|
||||||
|
from deluge.log import LOG as log
|
||||||
|
from deluge.ui.client import aclient
|
||||||
|
import gtk
|
||||||
|
|
||||||
|
class GtkUI(object):
|
||||||
|
def __init__(self, plugin_api, plugin_name):
|
||||||
|
log.debug("Calling Graph UI init")
|
||||||
|
self.plugin = plugin_api
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
self.glade = gtk.glade.XML(self.get_resource("config.glade"))
|
||||||
|
|
||||||
|
self.plugin.add_preferences_page("Graph", self.glade.get_widget("prefs_box"))
|
||||||
|
self.plugin.register_hook("on_apply_prefs", self.on_apply_prefs)
|
||||||
|
self.plugin.register_hook("on_show_prefs", self.on_show_prefs)
|
||||||
|
self.on_show_prefs()
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
self.plugin.remove_preferences_page("Graph")
|
||||||
|
self.plugin.deregister_hook("on_apply_prefs", self.on_apply_prefs)
|
||||||
|
self.plugin.deregister_hook("on_show_prefs", self.on_show_prefs)
|
||||||
|
|
||||||
|
def on_apply_prefs(self):
|
||||||
|
log.debug("applying prefs for Graph")
|
||||||
|
config = {
|
||||||
|
"test":self.glade.get_widget("txt_test").get_text()
|
||||||
|
}
|
||||||
|
aclient.graph_set_config(None, config)
|
||||||
|
|
||||||
|
def on_show_prefs(self):
|
||||||
|
aclient.graph_get_config(self.cb_get_config)
|
||||||
|
|
||||||
|
def cb_get_config(self, config):
|
||||||
|
"callback for on show_prefs"
|
||||||
|
self.glade.get_widget("txt_test").set_text(config["test"])
|
||||||
|
|
||||||
|
def get_resource(self, filename):
|
||||||
|
import pkg_resources, os
|
||||||
|
return pkg_resources.resource_filename("graph", os.path.join("data", filename))
|
|
@ -0,0 +1,10 @@
|
||||||
|
$:render.header(_("Network Graph"), 'graph')
|
||||||
|
$:render.admin_toolbar('graph')
|
||||||
|
|
||||||
|
<div style="padding-left:20px">
|
||||||
|
<img src="$base/graph/network.png?height=400&width=800">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$:render.footer()
|
|
@ -0,0 +1,60 @@
|
||||||
|
from deluge.ui.client import sclient, aclient
|
||||||
|
sclient.set_core_uri()
|
||||||
|
from graph import NetworkGraph
|
||||||
|
|
||||||
|
|
||||||
|
def test_sync():
|
||||||
|
if 1:
|
||||||
|
upload = sclient.graph_get_upload()
|
||||||
|
download = sclient.graph_get_download()
|
||||||
|
print upload
|
||||||
|
print download
|
||||||
|
else:
|
||||||
|
upload = [66804, 66915, 66974, 67447, 67540, 67318, 67320, 67249, 66659, 66489, 67027, 66914, 66802, 67303, 67654, 67643, 67763, 67528, 67523, 67431, 67214, 66939, 67316, 67020, 66881, 67103, 67377, 67141, 67366, 67492, 67375, 67203, 67056, 67010, 67029, 66741, 66695, 66868, 66805, 66264, 66249, 66317, 66459, 66306, 66681, 66954, 66662, 66278, 65921, 65695, 65681, 65942, 66000, 66140, 66424, 66480, 66257, 66271, 66145, 65854, 65568, 65268, 65112, 65050, 65027, 64676, 64655, 64178, 64386, 63979, 63271, 62746, 62337, 62297, 62496, 62902, 63801, 64121, 62957, 62921, 63051, 62644, 63240, 64107, 63968, 63987, 63644, 63263, 63153, 62999, 62843, 62777, 63101, 63078, 63178, 63126, 63401, 62630, 62451, 62505, 62254, 61485, 61264, 60937, 60568, 61011, 61109, 60325, 60196, 59640, 59619, 59514, 60813, 60572, 61632, 61689, 63365, 64583, 66396, 67179, 68209, 68295, 67674, 67559, 67195, 66178, 65632, 66124, 66456, 66676, 67183, 67620, 66960, 66347, 65925, 65907, 65896, 66738, 66703, 67060, 67004, 67007, 66329, 65304, 52002, 38969, 25433, 12426, 0, 0]
|
||||||
|
download = [42926, 43853, 43157, 45470, 44254, 46272, 45083, 47344, 46716, 51963, 50112, 52334, 55525, 57545, 53691, 51637, 49574, 49836, 48295, 49843, 52878, 56014, 56966, 56938, 60065, 60461, 56542, 59526, 58678, 54424, 51862, 55109, 52132, 53783, 51687, 56567, 52182, 50758, 46714, 50511, 48161, 50920, 48694, 50528, 55074, 55420, 55882, 59268, 59958, 57938, 57115, 51424, 51180, 53184, 52879, 51177, 54417, 51097, 47901, 49870, 55865, 61118, 61476, 63498, 58878, 49630, 45975, 45632, 45892, 44855, 49495, 48304, 45829, 42152, 39403, 37574, 32384, 34933, 34901, 33492, 31953, 36271, 33826, 34515, 36408, 41106, 43054, 44110, 40810, 41383, 37267, 35881, 38660, 37525, 34857, 36718, 36842, 34281, 39528, 41854, 42952, 40021, 41722, 41045, 42917, 39287, 38672, 32824, 28765, 22686, 18490, 15714, 15268, 14793, 15305, 16354, 16720, 17502, 17857, 16622, 18447, 19929, 31138, 36965, 36158, 32795, 30445, 21997, 18100, 22491, 27227, 29317, 32436, 35700, 39140, 36258, 33697, 24751, 20354, 8211, 3836, 1560, 834, 2034, 1744, 1637, 1637, 1637, 0, 0]
|
||||||
|
|
||||||
|
from graph import NetworkGraph
|
||||||
|
n = NetworkGraph()
|
||||||
|
n.savedUpSpeeds = upload
|
||||||
|
n.savedDownSpeeds = download
|
||||||
|
|
||||||
|
n.draw(800,200)
|
||||||
|
n.surface.write_to_png('output_sync.png')
|
||||||
|
|
||||||
|
def test_async():
|
||||||
|
n = NetworkGraph()
|
||||||
|
n.async_request()
|
||||||
|
aclient.force_call(True)
|
||||||
|
surface = n.draw(600,300)
|
||||||
|
surface.write_to_png('output_async.png')
|
||||||
|
|
||||||
|
def test_write():
|
||||||
|
"""
|
||||||
|
writing to a file-like object; need this for webui.
|
||||||
|
"""
|
||||||
|
class fake_file:
|
||||||
|
def __init__(self):
|
||||||
|
self.data = []
|
||||||
|
def write(self, str):
|
||||||
|
self.data.append(str)
|
||||||
|
|
||||||
|
n = NetworkGraph()
|
||||||
|
n.async_request()
|
||||||
|
aclient.force_call(True)
|
||||||
|
surface = n.draw(900,150)
|
||||||
|
|
||||||
|
file_like = fake_file()
|
||||||
|
surface.write_to_png(file_like)
|
||||||
|
data = "".join(file_like.data)
|
||||||
|
|
||||||
|
f = open("file_like.png","wb")
|
||||||
|
f.write(data)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
test_sync()
|
||||||
|
test_async()
|
||||||
|
test_write()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
#
|
||||||
|
# webui.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
#
|
||||||
|
# Basic plugin template created by:
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
|
||||||
|
#
|
||||||
|
# Deluge is free software.
|
||||||
|
#
|
||||||
|
# You may redistribute it and/or modify it under the terms of the
|
||||||
|
# GNU General Public License, as published by the Free Software
|
||||||
|
# Foundation; either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# deluge 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 deluge. 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
|
||||||
|
|
||||||
|
import os
|
||||||
|
from deluge.log import LOG as log
|
||||||
|
from deluge.ui.client import sclient, aclient
|
||||||
|
from deluge.plugins.webuipluginbase import WebUIPluginBase
|
||||||
|
from deluge import component
|
||||||
|
from graph import NetworkGraph
|
||||||
|
|
||||||
|
api = component.get("WebPluginApi")
|
||||||
|
forms = api.forms
|
||||||
|
|
||||||
|
#pages:
|
||||||
|
class graph_page:
|
||||||
|
@api.deco.deluge_page
|
||||||
|
def GET(self, args):
|
||||||
|
return api.render.graph.graph()
|
||||||
|
|
||||||
|
class network_png:
|
||||||
|
@api.deco.check_session
|
||||||
|
def GET(self, args):
|
||||||
|
vars = api.web.input(width = 600, height = 150)
|
||||||
|
log.debug("1")
|
||||||
|
api.web.header("Content-Type", "image/png")
|
||||||
|
n = NetworkGraph()
|
||||||
|
n.async_request()
|
||||||
|
aclient.force_call(True)
|
||||||
|
self.data = ""
|
||||||
|
surface = n.draw(int(vars.width), int(vars.height))
|
||||||
|
surface.write_to_png(self)
|
||||||
|
print self.data
|
||||||
|
|
||||||
|
def write(self, str): #file like object for pango; write_to_png
|
||||||
|
self.data += str
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class WebUI(WebUIPluginBase):
|
||||||
|
#map url's to classes: [(url,class), ..]
|
||||||
|
urls = [
|
||||||
|
('/graph', graph_page),
|
||||||
|
('/graph/network.png', network_png)
|
||||||
|
]
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
api.config_page_manager.register('plugins', 'graph' ,ConfigForm)
|
||||||
|
api.menu_manager.register_admin_page("graph", _("Graph"), "/graph") #<--top menu
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
api.config_page_manager.deregister('graph')
|
||||||
|
api.menu_manager.deregister_admin_page("graph") #<--top menu
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigForm(forms.Form):
|
||||||
|
#meta:
|
||||||
|
title = _("Graph")
|
||||||
|
|
||||||
|
#load/save:
|
||||||
|
def initial_data(self):
|
||||||
|
return sclient.graph_get_config()
|
||||||
|
|
||||||
|
def save(self, data):
|
||||||
|
cfg = dict(data)
|
||||||
|
sclient.graph_set_config(cfg)
|
||||||
|
|
||||||
|
#django newforms magic: define config fields:
|
||||||
|
test = forms.CharField(label=_("Test config value"))
|
|
@ -0,0 +1,56 @@
|
||||||
|
#
|
||||||
|
# setup.py
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
#
|
||||||
|
# Basic plugin template created by:
|
||||||
|
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||||
|
# Copyright (C) 2007, 2008 Andrew Resch ('andar') <andrewresch@gmail.com>
|
||||||
|
#
|
||||||
|
# Deluge is free software.
|
||||||
|
#
|
||||||
|
# You may redistribute it and/or modify it under the terms of the
|
||||||
|
# GNU General Public License, as published by the Free Software
|
||||||
|
# Foundation; either version 3 of the License, or (at your option)
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# deluge 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 deluge. 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
|
||||||
|
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
__author__ = "Martijn Voncken <mvoncken@gmail.com>"
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="Graph",
|
||||||
|
version="0.1",
|
||||||
|
description=__doc__,
|
||||||
|
author=__author__,
|
||||||
|
packages=["graph"],
|
||||||
|
package_data = {"graph": ["template/*","data/*"]},
|
||||||
|
entry_points="""
|
||||||
|
[deluge.plugin.core]
|
||||||
|
Graph = graph:CorePlugin
|
||||||
|
[deluge.plugin.webui]
|
||||||
|
Graph = graph:WebUIPlugin
|
||||||
|
[deluge.plugin.gtkui]
|
||||||
|
Graph = graph:GtkUIPlugin
|
||||||
|
"""
|
||||||
|
)
|
Loading…
Reference in New Issue