#! /usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------------------------------------------------------------
# Name: p2pgauge.py
# Purpose:
#
# Author: Jeremy Arendt
#
# Created: 2004/28/01
# RCS-ID: $Id: p2pgauge.py,v 1.1 2005/06/09 16:37:53 Inigo Exp $
# Copyright: (c) 2002
# Licence: See G3.LICENCE.TXT
#-----------------------------------------------------------------------------
import wx
from traceback import print_exc
from images import Images
from btconfig import BTConfig
import math
MAX_X_SCALE = 1600
class Avail_Gauge(wx.Window):
def __init__(self, parent, btconfig, size=wx.DefaultSize, pos=wx.DefaultPosition,
style=wx.SUNKEN_BORDER):
wx.Window.__init__(self, parent, -1, pos, size, style)
self.size = self.GetClientSize()
self.btconfig = btconfig
wx.EVT_SIZE(self, self.OnSize)
wx.EVT_PAINT(self, self.OnPaint)
wx.EVT_ERASE_BACKGROUND(self, self.AntiFlicker)
self._SetValue(0,[])
def AntiFlicker(self,event):
pass
def InitBuffer(self):
self.buffer = wx.EmptyBitmap(max(1,self.size.width), max(1,self.size.height))
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
dc.Clear()
self.DrawAvailabilty(dc)
# self.Refresh(False)
def OnSize(self, event):
self.size = self.GetClientSize()
if self.IsShown():
self.InitBuffer()
def OnPaint(self, event):
try:
dc = wx.BufferedPaintDC(self, self.buffer)
except wx.PyAssertionError:
# there is bug I can't reproduce that needs to be caught here
print_exc()
def DrawAvailabilty(self, dc):
size = self.GetClientSize()
have_color = self.btconfig.GetColor('g_have_color')
nothave_color = self.btconfig.GetColor('g_nothave_color')
gauge_color = self.btconfig.GetColor('g_overall_color')
bgcolor = self.btconfig.GetColor('g_nothave_color')
have_brush = wx.Brush(have_color, wx.SOLID)
nothave_brush = wx.Brush(nothave_color, wx.SOLID)
#dc.SetOptimization(True)
dc.BeginDrawing()
dc.SetBackground(nothave_brush)
dc.Clear()
dc.SetPen(wx.Pen(nothave_color, 0, wx.TRANSPARENT ))
nhashes = len(self.availlist)
if nhashes > 0:
width = max(min(MAX_X_SCALE, size.width, nhashes), 1)
height = size.height
delta = float(size.width) / width
try:
delta2 = float(nhashes) / width
except ZeroDivisionError:
delta2 = 0
i = 0
j = 0
last_brush = -9
brushtype = 0
h_rect_w = 0
h_start_x = 0
availlist = self.availlist
dc.SetBrush(have_brush)
w = max(1, int(delta2))
rects = []
brushes = []
largest = max(availlist)
if largest < 1:
largest = 1
last_x = 0
while i < width:
k = int(i*delta2)
x = int(i*delta)
freq = 0
smallest = 0
slicelen = len(availlist[k:k+w])
if slicelen > 0:
lsum = sum(availlist[k:k+w])
freq = min(1, (float(lsum) / slicelen) / largest)
rects.append((last_x, height-int(height*freq), (x-last_x)+int(delta), int(height*freq)))
h_rect_w = 0
last_x = x+int(delta)
i += 1
dc.DrawRectangleList(rects, None, have_brush)
dc.EndDrawing()
def _SetValue(self, fractionDone=0.0, availlist=[]):
self.fractionDone = fractionDone
self.availlist = availlist
if self.IsShown():
self.InitBuffer()
def SetValue(self, fractionDone, availlist):
if not availlist:
availlist = []
self._SetValue(fractionDone, availlist)
def GetValue(self):
return self.fractionDone
class P2P_Gauge(wx.Window):
def __init__(self, parent, btconfig, size=wx.DefaultSize, pos=wx.DefaultPosition,
style=wx.SUNKEN_BORDER, showtext=True):
wx.Window.__init__(self, parent, -1, pos, size, style)
self.size = wx.Size(size[0], size[1])
self.btconfig = btconfig
self.doneflag = 0
self.showtext = showtext
wx.EVT_SIZE(self, self.OnSize)
wx.EVT_PAINT(self, self.OnPaint)
wx.EVT_ERASE_BACKGROUND(self, self.AntiFlicker)
self._SetValue(-1,-1)
def AntiFlicker(self,event):
pass
def InitBuffer(self):
self.buffer = wx.EmptyBitmap(max(1,self.size.width), max(1,self.size.height))
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
dc.Clear()
self.DrawGauge(dc)
# self.Refresh(False)
def OnSize(self, event):
self.size = self.GetClientSize()
if self.IsShown():
self.InitBuffer()
def OnPaint(self, event):
try:
dc = wx.BufferedPaintDC(self, self.buffer)
except wx.PyAssertionError:
# there is bug I can't reproduce that needs to be caught here
print_exc()
def DrawGauge(self, dc):
size = self.size
have_color = self.btconfig.GetColor('g_have_color')
requested_color = self.btconfig.GetColor('g_requested_color')
nothave_color = self.btconfig.GetColor('g_nothave_color')
gauge_color = self.btconfig.GetColor('g_overall_color')
gauge_text = self.btconfig.GetColor('g_text_color')
bgcolor = self.btconfig.GetColor('g_nothave_color')
have_brush = wx.Brush(have_color, wx.SOLID)
nothave_brush = wx.Brush(nothave_color, wx.SOLID)
requested_brush = wx.Brush(requested_color, wx.SOLID)
#dc.SetOptimization(True)
dc.BeginDrawing()
dc.SetBackground(wx.Brush(bgcolor, wx.SOLID))
dc.Clear()
dc.SetPen(wx.Pen(nothave_color, 0, wx.TRANSPARENT ))
# draw p2p style gauge
if self.nhashes > 0 and self.nhashes is not None:
width = max(1, min(MAX_X_SCALE, size.width, self.nhashes))
height = size.height
delta = float(size.width) / width
try:
delta2 = float(self.nhashes) / width
except ZeroDivisionError:
delta2 = 0
j = 0
last_brush = -9
brushtype = 0
rq_rect_w = 0
h_rect_w = 0
rq_start_x = 0
h_start_x = 0
havelist = self.havelist
availlist = self.availlist
dc.SetBrush(have_brush)
rects = []
kpp = int(delta2)
last_x = -1
for i in range(width):
k = int(i*delta2)
x = int(i*delta)
if x == last_x:
continue
kpp = int((i+1)*delta2)
slice_len = kpp-k
lsum = sum(havelist[k:kpp])
if (lsum+lsum) > slice_len:
if last_brush != 0:
h_start_x = x
brushtype = 0
h_rect_w += delta
else:
brushtype = -1
if brushtype != 0 and last_brush == 0:
rects.append( (h_start_x, 0, int(round(h_rect_w)), height) )
h_rect_w = 0
j += 1
last_brush = brushtype
last_x = x
#end while
if brushtype == 0:
rects.append( (h_start_x, 0, int(h_rect_w), height) )
j += 1
dc.DrawRectangleList(rects, None, have_brush)
#print 'drew graph with ' + str(j) + ' iterations out of ' + str(i)
#end if
if self.showtext:
#draw text
if self.doneflag == 0:
stat_str = str(round(100*self.fractionDone,2)) + '%'
elif self.doneflag == 1:
stat_str = _("100% complete")
elif self.doneflag == -1:
stat_str = _("Failed")
elif self.doneflag == -2:
stat_str = ""
elif self.doneflag == -3:
stat_str = _("Paused")
elif self.doneflag == -4:
stat_str = _("Stopped")
else:
stat_str = ""
dc.SetFont(wx.Font(11, wx.SWISS, wx.ITALIC, wx.BOLD))
tsize = dc.GetTextExtent(stat_str)
dc.SetTextForeground(gauge_text)
dc.DrawText(stat_str, int(size.width/2) - int(tsize[0]/2), 4)
# traditional gauge on top
dc.SetBrush(wx.Brush(gauge_color, wx.SOLID))
dc.DrawRectangle(0, 0, int(size.width*self.fractionDone), 2+int(size.height*0.10))
dc.EndDrawing()
def SetValueStopped(self):
self._SetValue(-4)
def SetValuePaused(self):
self._SetValue(-3)
def SetValueUnknown(self):
self._SetValue(-2)
def SetValueFinished(self):
self._SetValue(1, 1.0, [1,1], [1,1])
def SetValueFailed(self):
self.doneflag = -1
if self.nhashes is 0 or self.nhashes is None:
self.fractionDone = 0
self.nhashes = 0
self.havelist = []
self.availlist = []
else:
self.fractionDone = 0.0
if self.IsShown():
self.InitBuffer()
def _SetValue(self, doneflag=0, fractionDone=0.0, havelist=[], availlist=[]):
self.doneflag = doneflag
self.fractionDone = fractionDone
self.nhashes = len(havelist)
self.havelist = havelist
self.availlist = availlist
self.InitBuffer()
def SetValue(self, fractionDone, havelist, availlist=None):
if not havelist:
havelist = []
if havelist != self.havelist or round(fractionDone, 4) != round(self.fractionDone, 4):
self._SetValue(0, fractionDone, havelist)
def GetValue(self):
return self.fractionDone
#---------------------------------------------------------------------------
class P2P_Gauge2(wx.Window):
""" Uses color shades to show a closer approximation. Slower than the standard P2P_Gauge."""
def __init__(self, parent, btconfig, size=wx.DefaultSize, pos=wx.DefaultPosition,
style=wx.SUNKEN_BORDER, showtext=True):
wx.Window.__init__(self, parent, -1, pos, size, style)
self.size = self.GetClientSize()
self.btconfig = btconfig
self.doneflag = 0
self.showtext = showtext
self.counter = 0
wx.EVT_SIZE(self, self.OnSize)
wx.EVT_PAINT(self, self.OnPaint)
wx.EVT_ERASE_BACKGROUND(self, self.AntiFlicker)
self.last_have_color = None
self._SetValue(-1,-1)
def UpdateGauge(self):
self.UpdateColors()
self.InitBuffer()
def UpdateColors(self):
have_color = self.btconfig.GetColor('g_have_color')
self.last_have_color = have_color
self.have_brushes = []
for i in range(0,101):
self.have_brushes.append( wx.Brush(wx.Color(
int(255 - (255-have_color.Red()) * float(i)/100),
int(255 - (255-have_color.Green()) * float(i)/100),
int(255 - (255-have_color.Blue()) * float(i)/100)
),
wx.SOLID))
def AntiFlicker(self,event):
pass
def InitBuffer(self):
self.buffer = wx.EmptyBitmap(max(1,self.size.width), max(1,self.size.height))
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
dc.Clear()
self.DrawGauge(dc)
# self.Refresh(False)
def OnSize(self, event):
self.size = self.GetClientSize()
if self.IsShown():
self.InitBuffer()
def OnPaint(self, event):
try:
dc = wx.BufferedPaintDC(self, self.buffer)
except wx.PyAssertionError:
# there is bug I can't reproduce that needs to be caught here
print_exc()
def DrawGauge(self, dc):
size = self.GetClientSize()
have_color = self.btconfig.GetColor('g_have_color')
requested_color = self.btconfig.GetColor('g_requested_color')
nothave_color = self.btconfig.GetColor('g_nothave_color')
gauge_color = self.btconfig.GetColor('g_overall_color')
gauge_text = self.btconfig.GetColor('g_text_color')
bgcolor = self.btconfig.GetColor('g_nothave_color')
if self.last_have_color != have_color:
self.UpdateColors()
self.last_have_color = have_color
if have_color != self.last_have_color:
self.UpdateColors()
self.last_have_color = have_color
have_brush = wx.Brush(have_color, wx.SOLID)
nothave_brush = wx.Brush(nothave_color, wx.SOLID)
requested_brush = wx.Brush(requested_color, wx.SOLID)
#dc.SetOptimization(True)
dc.BeginDrawing()
dc.SetBackground(wx.Brush(bgcolor, wx.SOLID))
dc.Clear()
dc.SetPen(wx.Pen(nothave_color, 0, wx.TRANSPARENT ))
# draw p2p style gauge
if self.nhashes > 0 and self.nhashes is not None:
width = max(1, min(MAX_X_SCALE, size.width, self.nhashes))
height = size.height
delta = float(size.width) / width
try:
delta2 = float(self.nhashes) / width
except ZeroDivisionError:
delta2 = 0
i = 0
j = 0
last_brush = 0
brushtype = 0
rq_rect_w = 0
h_rect_w = 0
rq_start_x = 0
h_start_x = 0
havelist = self.havelist
availlist = self.availlist
dc.SetBrush(have_brush)
rects = []
brushes = []
kpp = int(delta2)
last_x = -1
last_slice_len = 0
while i < width:
k = int(i*delta2)
x = int(i*delta)
if x == last_x:
continue
kpp = int((i+1)*delta2)
slice_len = kpp-k
if slice_len > 0:
lsum = sum(havelist[k:kpp])
else:
lsum = 0
if (lsum+lsum) > slice_len:
#if lsum > 0:
if last_brush != lsum:
if last_brush == 0:
h_start_x = x
brushtype = lsum
h_rect_w += delta
else:
brushtype = 0
if last_brush != brushtype and last_brush > 0:
freq = min(1, float(last_brush)/last_slice_len)
#print freq, last_brush, last_slice_len
brushes.append( self.have_brushes[int(100*freq)] )
rects.append( (h_start_x, 0, int(round(h_rect_w)), height) )
if brushtype == 0:
h_rect_w = 0
else:
h_rect_w = delta
h_start_x = x
j += 1
last_x = x
last_slice_len = slice_len
last_brush = brushtype
i += 1
#end while
if brushtype > 0:
freq = min(1, float(last_brush)/last_slice_len)
brushes.append(self.have_brushes[int(100*freq)])
rects.append( (h_start_x, 0, int(round(h_rect_w)), height) )
j += 1
dc.DrawRectangleList(rects, None, brushes)
#print 'drew graph with ' + str(j) + ' iterations out of ' + str(i)
#end if
if self.showtext:
#draw text
if self.doneflag == 0:
stat_str = str(round(100*self.fractionDone,2)) + '%'
elif self.doneflag == 1:
stat_str = _("100% complete")
elif self.doneflag == -1:
stat_str = _("Failed")
elif self.doneflag == -2:
stat_str = ""
elif self.doneflag == -3:
stat_str = _("Paused")
else:
stat_str = ""
dc.SetFont(wx.Font(11, wx.SWISS, wx.ITALIC, wx.BOLD))
tsize = dc.GetTextExtent(stat_str)
dc.SetTextForeground(gauge_text)
dc.DrawText(stat_str, int(size.width/2) - int(tsize[0]/2), 4)
# traditional gauge on top
dc.SetBrush(wx.Brush(gauge_color, wx.SOLID))
dc.DrawRectangle(0, 0, int(size.width*self.fractionDone), 2+int(size.height*0.10))
dc.EndDrawing()
def SetValuePaused(self):
self._SetValue(-3)
def SetValueUnknown(self):
self._SetValue(-2)
def SetValueFinished(self):
self._SetValue(1, 1.0, [1,1], [1,1])
def SetValueFailed(self):
self.doneflag = -1
if self.nhashes is 0 or self.nhashes is None:
self.fractionDone = 0
self.nhashes = 0
self.havelist = []
self.availlist = []
else:
self.fractionDone = 0.0
if self.IsShown():
self.InitBuffer()
def _SetValue(self, doneflag=0, fractionDone=0.0, havelist=[], availlist=[]):
self.doneflag = doneflag
self.fractionDone = fractionDone
self.nhashes = len(havelist)
self.havelist = havelist
self.availlist = availlist
self.InitBuffer()
def SetValue(self, fractionDone, havelist, availlist=None):
if not havelist:
havelist = []
if havelist != self.havelist or round(fractionDone, 4) != round(self.fractionDone, 4):
self._SetValue(0, fractionDone, havelist)
def GetValue(self):
return self.fractionDone
#---------------------------------------------------------------------------
class Mini_P2P_Gauge(P2P_Gauge):
def __init__(self, parent, btconfig, size=wx.DefaultSize,
style=wx.SIMPLE_BORDER, showtext=False, list_type=0):
self.list_type = list_type
P2P_Gauge.__init__(self, parent, btconfig, (1, 1), (-100, -100),
style, showtext)
def DrawGauge(self, dc):
size = self.size
have_color = self.btconfig.GetColor('g_have_color')
nothave_color = self.btconfig.GetColor('g_nothave_color')
gauge_color = self.btconfig.GetColor('g_overall_color')
border = wx.Color(120,120,160)
have_brush = wx.Brush(have_color, wx.SOLID)
nothave_brush = wx.Brush(nothave_color, wx.SOLID)
dc.BeginDrawing()
#dc.SetOptimization(True)
dc.SetBackground(wx.Brush(nothave_color, wx.SOLID))
dc.Clear()
dc.SetPen(wx.Pen(nothave_color, 0, wx.TRANSPARENT))
# peer list torrent list
if (self.btconfig.Get('p_gauge_type') == True and self.list_type == 0) or (self.btconfig.Get('t_gauge_type') == True and self.list_type == 1):
# traditional percentage gauge
dc.SetBrush(have_brush)
dc.DrawRectangle(0, 0, int(size.width*self.fractionDone), size.height)
else: #defaults to 'pieces' p2p gauge
# draw p2p style gauge
if self.nhashes > 0:
width = 50
height = size.height
delta = float(size.width) / width
delta2 = float(self.nhashes) / width
i = 0
j = 0
last_brush = -1
brushtype = 0
rect_w = 0
start_x = 0
havelist = self.havelist
dc.SetBrush(have_brush)
rects = []
while i < width:
k = int(i*delta2)
x = int(i*delta)
kpp = int(i*delta2+1)
slice_len = kpp-k
lsum = sum(havelist[k:kpp])
if (lsum+lsum) > slice_len:
## if havelist[k]:
if last_brush != 0:
start_x = x
brushtype = 0
rect_w += delta
else:
brushtype = 1
if last_brush != brushtype and brushtype == 1:
rects.append( (start_x, 0, int(rect_w), height) )
rect_w = 0
j += 1
last_brush = brushtype
i += 1
#end while
if brushtype == 0:
rects.append( (start_x, 0, int(rect_w), height) )
j += 1
#print 'drew graph with ' + str(j) + ' iterations out of ' + str(i)
dc.DrawRectangleList(rects, None, have_brush)
dc.SetBrush(wx.Brush(gauge_color, wx.TRANSPARENT))
dc.SetPen(wx.Pen(border, 1, wx.SOLID))
dc.DrawRectangle(0, 0, size.width, size.height)
dc.EndDrawing()
def SetValue(self, fractionDone, havelist, availlist=None):
if not havelist:
havelist = []
if havelist != self.havelist or round(fractionDone, 2) != round(self.fractionDone, 2):
self._SetValue(0, fractionDone, havelist)
#---------------------------------------------------------------------------
import random
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Test', size = (600, 130), style = wx.DEFAULT_FRAME_STYLE)
panel = wx.Panel(self, -1, size=(600, 130))
#self.p1 = Mini_P2P_Gauge(panel, BTConfig(), size=(1,27))
self.p1 = Avail_Gauge(panel, BTConfig(), size=(1,27))
#self.p1 = P2P_Gauge1(panel, BTConfig(), size=(1,27))
self.p2 = P2P_Gauge(panel, BTConfig(), size=(-1,27))
#self.p2 = P2P_Gauge2(panel, BTConfig(), size=(-1,27))
tt1 = wx.ToolTip("Style1 - gradiant")
self.p1.SetToolTip(tt1)
tt2 = wx.ToolTip("Style2 - solid")
self.p2.SetToolTip(tt2)
testbutton1 = wx.Button(panel, 100, "Draw 1x")
testbutton2 = wx.Button(panel, 101, "Draw 100x")
wx.EVT_BUTTON(self, 100, self.OnClick1)
wx.EVT_BUTTON(self, 101, self.OnClick2)
sizer = wx.FlexGridSizer(cols=1)
sizer.Add(self.p1, 0, wx.EXPAND)
sizer.Add(self.p2, 0, wx.EXPAND)
sizer.AddGrowableCol(0)
hsizer = wx.BoxSizer(wx.HORIZONTAL)
hsizer.Add(testbutton1)
hsizer.Add(testbutton2)
sizer.Add(hsizer)
panel.SetSizer(sizer)
panel.Layout()
self.panel = panel
#wx.EVT_SIZE(self, self.OnSize)
def OnSize(self, event):
fsize = self.GetClientSize()
self.panel.SetSize(fsize)
def TestDraw(self, havelist, availlist):
j = 0
for i in xrange(len(availlist)):
if math.sin(j/100) > 0:
havelist[i] = 1
havelist[i] = int(2 * random.random())
j+=1
availlist[i] += int(10 * random.random())
self.p1.SetValue(0.0, availlist)
#self.p1._SetValue(0, 0.0, [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0])
#self.p1._SetValue(0, 0.0, havelist)
self.p2._SetValue(0, 0.0, havelist)
#self.p.SetValueUnknown()
#self.p.SetValueFinished()
def OnClick1(self, event):
import time
len = 2000
havelist = [1] * len
availlist = [3] * len
t = time.time()
self.TestDraw(havelist, availlist)
print time.time() - t
def OnClick2(self, event):
import time
len = 2000
havelist = [1] * len
availlist = [3] * len
t = time.time()
for i in range(0,10):
self.TestDraw(havelist, availlist)
print time.time() - t
if __name__ == "__main__":
_ = lambda x: x # needed for gettext
app = wx.PySimpleApp()
frame = TestFrame()
app.SetTopWindow(frame)
frame.Show(True)
app.MainLoop()
|