|
|
|
|
File: [Development] / bittornado / btdownloadgui.py
(download)
/
(as text)
Revision: 1.86, Tue Oct 11 22:48:31 2005 UTC (4 years, 10 months ago) by theshadow Branch: MAIN Changes since 1.85: +2 -2 lines boosted widths slightly for new wxPython version |
#!/usr/bin/env python
# Written by Bram Cohen and Myers Carpenter
# Modifications by various people
# see LICENSE.txt for license information
from BitTornado import PSYCO
if PSYCO.psyco:
try:
import psyco
assert psyco.__version__ >= 0x010100f0
psyco.full()
except:
pass
from sys import argv, version, exit
assert version >= '2', "Install Python 2.0 or greater"
try:
from wxPython.wx import *
except:
print 'wxPython is either not installed or has not been installed properly.'
exit(1)
from BitTornado.download_bt1 import BT1Download, defaults, parse_params, get_usage, get_response
from BitTornado.RawServer import RawServer, UPnP_ERROR
from random import seed
from socket import error as socketerror
from BitTornado.ConnChoice import *
from BitTornado.ConfigReader import configReader
from BitTornado.bencode import bencode, bdecode
from BitTornado.natpunch import UPnP_test
from threading import Event, Thread
from os.path import *
from os import getcwd
from time import strftime, time, localtime, sleep
from BitTornado.clock import clock
from webbrowser import open_new
from traceback import print_exc
from StringIO import StringIO
from sha import sha
import re
import sys, os
from BitTornado import version, createPeerID, report_email
try:
True
except:
True = 1
False = 0
PROFILER = False
WXPROFILER = False
try:
wxFULL_REPAINT_ON_RESIZE
except:
wxFULL_REPAINT_ON_RESIZE = 0 # fix for wx pre-2.5
# Note to packagers: edit OLDICONPATH in BitTornado/ConfigDir.py
def hours(n):
if n == 0:
return 'download complete'
try:
n = int(n)
assert n >= 0 and n < 5184000 # 60 days
except:
return '<unknown>'
m, s = divmod(n, 60)
h, m = divmod(m, 60)
if h > 0:
return '%d hour(s) %02d min %02d sec' % (h, m, s)
else:
return '%d min %02d sec' % (m, s)
def size_format(s):
if (s < 1024):
r = str(s) + 'B'
elif (s < 1048576):
r = str(int(s/1024)) + 'KiB'
elif (s < 1073741824L):
r = str(int(s/1048576)) + 'MiB'
elif (s < 1099511627776L):
r = str(int((s/1073741824.0)*100.0)/100.0) + 'GiB'
else:
r = str(int((s/1099511627776.0)*100.0)/100.0) + 'TiB'
return(r)
def comma_format(s):
r = str(s)
for i in range(len(r)-3, 0, -3):
r = r[:i]+','+r[i:]
return(r)
hexchars = '0123456789abcdef'
hexmap = []
for i in xrange(256):
x = hexchars[(i&0xF0)/16]+hexchars[i&0x0F]
hexmap.append(x)
def tohex(s):
r = []
for c in s:
r.append(hexmap[ord(c)])
return ''.join(r)
wxEVT_INVOKE = wxNewEventType()
def EVT_INVOKE(win, func):
win.Connect(-1, -1, wxEVT_INVOKE, func)
class InvokeEvent(wxPyEvent):
def __init__(self, func = None, args = None, kwargs = None):
wxPyEvent.__init__(self)
self.SetEventType(wxEVT_INVOKE)
self.func = func
self.args = args
self.kwargs = kwargs
class DownloadInfoFrame:
def __init__(self, flag, configfile):
self._errorwindow = None
try:
self.FONT = configfile.config['gui_font']
self.default_font = wxFont(self.FONT, wxDEFAULT, wxNORMAL, wxNORMAL, False)
frame = wxFrame(None, -1, 'BitTorrent ' + version + ' download',
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
self.flag = flag
self.configfile = configfile
self.configfileargs = configfile.config
self.uiflag = Event()
self.fin = False
self.aboutBox = None
self.detailBox = None
self.advBox = None
self.creditsBox = None
self.statusIconHelpBox = None
self.reannouncelast = 0
self.spinlock = 0
self.scrollock = 0
self.lastError = 0
self.spewwait = clock()
self.config = None
self.updateSpinnerFlag = 0
self.updateSliderFlag = 0
self.statusIconValue = ' '
self.iconized = 0
self.taskbaricon = False
self.checking = None
self.activity = 'Starting up...'
self.firstupdate = True
self.shuttingdown = False
self.ispaused = False
self.bgalloc_periods = 0
self.gui_fractiondone = None
self.fileList = None
self.lastexternalannounce = ''
self.refresh_details = False
self.lastuploadsettings = 0
self.old_download = 0
self.old_upload = 0
self.old_ratesettings = None
self.current_ratesetting = None
self.gaugemode = None
self.autorate = False
self.filename = None
self.dow = None
if sys.platform == 'win32':
self.invokeLaterEvent = InvokeEvent()
self.invokeLaterList = []
wxInitAllImageHandlers()
self.basepath = self.configfile.getIconDir()
self.icon = wxIcon(os.path.join(self.basepath,'icon_bt.ico'), wxBITMAP_TYPE_ICO)
self.finicon = wxIcon(os.path.join(self.basepath,'icon_done.ico'), wxBITMAP_TYPE_ICO)
self.statusIconFiles={
'startup':os.path.join(self.basepath,'white.ico'),
'disconnected':os.path.join(self.basepath,'black.ico'),
'noconnections':os.path.join(self.basepath,'red.ico'),
'nocompletes':os.path.join(self.basepath,'blue.ico'),
'noincoming':os.path.join(self.basepath,'yellow.ico'),
'allgood':os.path.join(self.basepath,'green.ico'),
}
self.statusIcons={}
self.filestatusIcons = wxImageList(16, 16)
self.filestatusIcons.Add(wxBitmap(os.path.join(self.basepath,'black1.ico'),wxBITMAP_TYPE_ICO))
self.filestatusIcons.Add(wxBitmap(os.path.join(self.basepath,'yellow1.ico'), wxBITMAP_TYPE_ICO))
self.filestatusIcons.Add(wxBitmap(os.path.join(self.basepath,'green1.ico'), wxBITMAP_TYPE_ICO))
self.allocbuttonBitmap = wxBitmap(os.path.join(self.basepath,'alloc.gif'), wxBITMAP_TYPE_GIF)
self.starttime = clock()
self.frame = frame
try:
self.frame.SetIcon(self.icon)
except:
pass
panel = wxPanel(frame, -1)
self.bgcolor = panel.GetBackgroundColour()
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
if color is not None:
x.SetForegroundColour(color)
return x
colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
topboxsizer = wxFlexGridSizer(cols = 3, vgap = 0)
topboxsizer.AddGrowableCol (0)
fnsizer = wxFlexGridSizer(cols = 1, vgap = 0)
fnsizer.AddGrowableCol (0)
fnsizer.AddGrowableRow (1)
fileNameText = StaticText('', self.FONT+4)
fnsizer.Add(fileNameText, 1, wxALIGN_BOTTOM|wxEXPAND)
self.fileNameText = fileNameText
fnsizer2 = wxFlexGridSizer(cols = 8, vgap = 0)
fnsizer2.AddGrowableCol (0)
fileSizeText = StaticText('')
fnsizer2.Add(fileSizeText, 1, wxALIGN_BOTTOM|wxEXPAND)
self.fileSizeText = fileSizeText
fileDetails = StaticText('Details', self.FONT, True, 'Blue')
fnsizer2.Add(fileDetails, 0, wxALIGN_BOTTOM)
fnsizer2.Add(StaticText(' '))
advText = StaticText('Advanced', self.FONT, True, 'Blue')
fnsizer2.Add(advText, 0, wxALIGN_BOTTOM)
fnsizer2.Add(StaticText(' '))
prefsText = StaticText('Prefs', self.FONT, True, 'Blue')
fnsizer2.Add(prefsText, 0, wxALIGN_BOTTOM)
fnsizer2.Add(StaticText(' '))
aboutText = StaticText('About', self.FONT, True, 'Blue')
fnsizer2.Add(aboutText, 0, wxALIGN_BOTTOM)
fnsizer2.Add(StaticText(' '))
fnsizer.Add(fnsizer2,0,wxEXPAND)
topboxsizer.Add(fnsizer,0,wxEXPAND)
topboxsizer.Add(StaticText(' '))
self.statusIcon = wxEmptyBitmap(32,32)
statidata = wxMemoryDC()
statidata.SelectObject(self.statusIcon)
statidata.SetPen(wxTRANSPARENT_PEN)
statidata.SetBrush(wxBrush(self.bgcolor,wxSOLID))
statidata.DrawRectangle(0,0,32,32)
self.statusIconPtr = wxStaticBitmap(panel, -1, self.statusIcon)
topboxsizer.Add(self.statusIconPtr)
self.fnsizer = fnsizer
self.fnsizer2 = fnsizer2
self.topboxsizer = topboxsizer
colSizer.Add(topboxsizer, 0, wxEXPAND)
self.gauge = wxGauge(panel, -1, range = 1000, style = wxGA_SMOOTH)
colSizer.Add(self.gauge, 0, wxEXPAND)
timeSizer = wxFlexGridSizer(cols = 2)
timeSizer.Add(StaticText('Time elapsed / estimated : '))
self.timeText = StaticText(self.activity+' ')
timeSizer.Add(self.timeText)
timeSizer.AddGrowableCol(1)
colSizer.Add(timeSizer)
destSizer = wxFlexGridSizer(cols = 2, hgap = 8)
self.fileDestLabel = StaticText('Download to:')
destSizer.Add(self.fileDestLabel)
self.fileDestText = StaticText('')
destSizer.Add(self.fileDestText, flag = wxEXPAND)
destSizer.AddGrowableCol(1)
colSizer.Add(destSizer, flag = wxEXPAND)
self.destSizer = destSizer
statSizer = wxFlexGridSizer(cols = 3, hgap = 8)
self.ratesSizer = wxFlexGridSizer(cols = 2)
self.infoSizer = wxFlexGridSizer(cols = 2)
self.ratesSizer.Add(StaticText(' Download rate: '))
self.downRateText = StaticText('0 kB/s ')
self.ratesSizer.Add(self.downRateText, flag = wxEXPAND)
self.downTextLabel = StaticText('Downloaded: ')
self.infoSizer.Add(self.downTextLabel)
self.downText = StaticText('0.00 MiB ')
self.infoSizer.Add(self.downText, flag = wxEXPAND)
self.ratesSizer.Add(StaticText(' Upload rate: '))
self.upRateText = StaticText('0 kB/s ')
self.ratesSizer.Add(self.upRateText, flag = wxEXPAND)
self.upTextLabel = StaticText('Uploaded: ')
self.infoSizer.Add(self.upTextLabel)
self.upText = StaticText('0.00 MiB ')
self.infoSizer.Add(self.upText, flag = wxEXPAND)
shareSizer = wxFlexGridSizer(cols = 2, hgap = 8)
shareSizer.Add(StaticText('Share rating:'))
self.shareRatingText = StaticText('')
shareSizer.AddGrowableCol(1)
shareSizer.Add(self.shareRatingText, flag = wxEXPAND)
statSizer.Add(self.ratesSizer)
statSizer.Add(self.infoSizer)
statSizer.Add(shareSizer, flag = wxALIGN_CENTER_VERTICAL)
colSizer.Add (statSizer)
torrentSizer = wxFlexGridSizer(cols = 1)
self.peerStatusText = StaticText('')
torrentSizer.Add(self.peerStatusText, 0, wxEXPAND)
self.seedStatusText = StaticText('')
torrentSizer.Add(self.seedStatusText, 0, wxEXPAND)
torrentSizer.AddGrowableCol(0)
colSizer.Add(torrentSizer, 0, wxEXPAND)
self.torrentSizer = torrentSizer
self.errorTextSizer = wxFlexGridSizer(cols = 1)
self.errorText = StaticText('', self.FONT, False, 'Red')
self.errorTextSizer.Add(self.errorText, 0, wxEXPAND)
colSizer.Add(self.errorTextSizer, 0, wxEXPAND)
cancelSizer=wxGridSizer(cols = 2, hgap = 40)
self.pauseButton = wxButton(panel, -1, 'Pause')
cancelSizer.Add(self.pauseButton, 0, wxALIGN_CENTER)
self.cancelButton = wxButton(panel, -1, 'Cancel')
cancelSizer.Add(self.cancelButton, 0, wxALIGN_CENTER)
colSizer.Add(cancelSizer, 0, wxALIGN_CENTER)
# Setting options
slideSizer = wxFlexGridSizer(cols = 7, hgap = 0, vgap = 5)
# dropdown
self.connChoiceLabel = StaticText('Settings for ')
slideSizer.Add (self.connChoiceLabel, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
self.connChoice = wxChoice (panel, -1, (-1, -1), (self.FONT*12, -1),
choices = connChoiceList)
self.connChoice.SetFont(self.default_font)
self.connChoice.SetSelection(0)
slideSizer.Add (self.connChoice, 0, wxALIGN_CENTER)
self.rateSpinnerLabel = StaticText(' Upload rate (kB/s) ')
slideSizer.Add (self.rateSpinnerLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
# max upload rate
self.rateSpinner = wxSpinCtrl (panel, -1, "", (-1,-1), (50, -1))
self.rateSpinner.SetFont(self.default_font)
self.rateSpinner.SetRange(0,5000)
self.rateSpinner.SetValue(0)
slideSizer.Add (self.rateSpinner, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
self.rateLowerText = StaticText(' %5d' % (0))
self.rateUpperText = StaticText('%5d' % (5000))
self.rateslider = wxSlider(panel, -1, 0, 0, 5000, (-1, -1), (80, -1))
slideSizer.Add(self.rateLowerText, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
slideSizer.Add(self.rateslider, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
slideSizer.Add(self.rateUpperText, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
slideSizer.Add(StaticText(''), 0, wxALIGN_LEFT)
self.bgallocText = StaticText('', self.FONT+2, False, 'Red')
slideSizer.Add(self.bgallocText, 0, wxALIGN_LEFT)
# max uploads
self.connSpinnerLabel = StaticText(' Max uploads ')
slideSizer.Add (self.connSpinnerLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
self.connSpinner = wxSpinCtrl (panel, -1, "", (-1,-1), (50, -1))
self.connSpinner.SetFont(self.default_font)
self.connSpinner.SetRange(4,100)
self.connSpinner.SetValue(4)
slideSizer.Add (self.connSpinner, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
self.connLowerText = StaticText(' %5d' % (4))
self.connUpperText = StaticText('%5d' % (100))
self.connslider = wxSlider(panel, -1, 4, 4, 100, (-1, -1), (80, -1))
slideSizer.Add(self.connLowerText, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
slideSizer.Add(self.connslider, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
slideSizer.Add(self.connUpperText, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
colSizer.Add(slideSizer, 1, wxALL|wxALIGN_CENTER|wxEXPAND, 0)
self.unlimitedLabel = StaticText('0 kB/s means unlimited. Tip: your download rate is proportional to your upload rate', self.FONT-2)
colSizer.Add(self.unlimitedLabel, 0, wxALIGN_CENTER)
self.priorityIDs = [wxNewId(),wxNewId(),wxNewId(),wxNewId()]
self.prioritycolors = [ wxColour(160,160,160),
wxColour(255,64,0),
wxColour(0,0,0),
wxColour(64,64,255) ]
EVT_LEFT_DOWN(aboutText, self.about)
EVT_LEFT_DOWN(fileDetails, self.details)
EVT_LEFT_DOWN(self.statusIconPtr,self.statusIconHelp)
EVT_LEFT_DOWN(advText, self.advanced)
EVT_LEFT_DOWN(prefsText, self.openConfigMenu)
EVT_CLOSE(frame, self.done)
EVT_BUTTON(frame, self.pauseButton.GetId(), self.pause)
EVT_BUTTON(frame, self.cancelButton.GetId(), self.done)
EVT_INVOKE(frame, self.onInvoke)
EVT_SCROLL(self.rateslider, self.onRateScroll)
EVT_SCROLL(self.connslider, self.onConnScroll)
EVT_CHOICE(self.connChoice, -1, self.onConnChoice)
EVT_SPINCTRL(self.connSpinner, -1, self.onConnSpinner)
EVT_SPINCTRL(self.rateSpinner, -1, self.onRateSpinner)
if (sys.platform == 'win32'):
self.frame.tbicon = wxTaskBarIcon()
EVT_ICONIZE(self.frame, self.onIconify)
EVT_TASKBAR_LEFT_DCLICK(self.frame.tbicon, self.onTaskBarActivate)
EVT_TASKBAR_RIGHT_UP(self.frame.tbicon, self.onTaskBarMenu)
EVT_MENU(self.frame.tbicon, self.TBMENU_RESTORE, self.onTaskBarActivate)
EVT_MENU(self.frame.tbicon, self.TBMENU_CLOSE, self.done)
colSizer.AddGrowableCol (0)
colSizer.AddGrowableRow (6)
self.frame.Show()
border.Fit(panel)
self.frame.Fit()
self.panel = panel
self.border = border
self.addwidth = aboutText.GetBestSize().GetWidth() + fileDetails.GetBestSize().GetWidth() + (self.FONT*16)
self.fnsizer = fnsizer
self.colSizer = colSizer
minsize = self.colSizer.GetSize()
minsize.SetWidth (minsize.GetWidth())
minsize.SetHeight (minsize.GetHeight())
self.colSizer.SetMinSize (minsize)
self.colSizer.Fit(self.frame)
colSizer.Fit(frame)
except:
self.exception()
if sys.platform == 'win32': # windows-only optimization
def onInvoke(self, event):
while self.invokeLaterList:
func,args,kwargs = self.invokeLaterList[0]
if self.uiflag.isSet():
return
try:
apply(func,args,kwargs)
except:
self.exception()
del self.invokeLaterList[0]
def invokeLater(self, func, args = [], kwargs = {}):
if not self.uiflag.isSet():
self.invokeLaterList.append((func,args,kwargs))
if len(self.invokeLaterList) == 1:
wxPostEvent(self.frame, self.invokeLaterEvent)
else:
def onInvoke(self, event):
if not self.uiflag.isSet():
try:
apply(event.func, event.args, event.kwargs)
except:
self.exception()
def invokeLater(self, func, args = [], kwargs = {}):
if not self.uiflag.isSet():
wxPostEvent(self.frame, InvokeEvent(func, args, kwargs))
def getStatusIcon(self, name, bitmap=False):
if self.statusIcons.has_key(name):
i = self.statusIcons[name]
if type(i) == type(self.icon) and not bitmap:
return i
if bitmap:
i = wxBitmap(self.statusIconFiles[name], wxBITMAP_TYPE_ICO)
else:
i = wxIcon(self.statusIconFiles[name], wxBITMAP_TYPE_ICO)
self.statusIcons[name] = i
return i
def setStatusIcon(self, name):
if name == self.statusIconValue:
return
self.statusIconValue = name
statidata = wxMemoryDC()
statidata.SelectObject(self.statusIcon)
statidata.BeginDrawing()
try:
statidata.DrawIcon(self.getStatusIcon(name),0,0)
except:
statidata.DrawBitmap(self.getStatusIcon(name,True),0,0,True)
statidata.EndDrawing()
statidata.SelectObject(wxNullBitmap)
self.statusIconPtr.Refresh()
def createStatusIcon(self, name):
iconbuffer = wxEmptyBitmap(32,32)
bbdata = wxMemoryDC()
bbdata.SelectObject(iconbuffer)
bbdata.SetPen(wxTRANSPARENT_PEN)
bbdata.SetBrush(wxBrush(self.bgcolor,wxSOLID))
bbdata.DrawRectangle(0,0,32,32)
try:
bbdata.DrawIcon(self.getStatusIcon(name),0,0)
except:
bbdata.DrawBitmap(self.getStatusIcon(name,True),0,0,True)
return iconbuffer
def setgaugemode(self, selection):
if selection is None:
selection = self.gaugemode
elif selection == self.gaugemode:
return
else:
self.gaugemode = selection
if selection < 0:
self.gauge.SetForegroundColour(self.configfile.getcheckingcolor())
self.gauge.SetBackgroundColour(wxSystemSettings_GetColour(wxSYS_COLOUR_MENU))
elif selection == 0:
self.gauge.SetForegroundColour(self.configfile.getdownloadcolor())
self.gauge.SetBackgroundColour(wxSystemSettings_GetColour(wxSYS_COLOUR_MENU))
else:
self.gauge.SetForegroundColour(self.configfile.getseedingcolor())
self.gauge.SetBackgroundColour(self.configfile.getdownloadcolor())
def onIconify(self, evt):
try:
if self.configfileargs['win32_taskbar_icon']:
if self.fin:
self.frame.tbicon.SetIcon(self.finicon, "BitTorrent")
else:
self.frame.tbicon.SetIcon(self.icon, "BitTorrent")
self.frame.Hide()
self.taskbaricon = True
else:
return
except:
self.exception()
def onTaskBarActivate(self, evt):
try:
if self.frame.IsIconized():
self.frame.Iconize(False)
if not self.frame.IsShown():
self.frame.Show(True)
self.frame.Raise()
self.frame.tbicon.RemoveIcon()
self.taskbaricon = False
except wxPyDeadObjectError:
pass
except:
self.exception()
TBMENU_RESTORE = 1000
TBMENU_CLOSE = 1001
def onTaskBarMenu(self, evt):
menu = wxMenu()
menu.Append(self.TBMENU_RESTORE, "Restore BitTorrent")
menu.Append(self.TBMENU_CLOSE, "Close")
self.frame.tbicon.PopupMenu(menu)
menu.Destroy()
def _try_get_config(self):
if self.config is None:
try:
self.config = self.dow.getConfig()
except:
pass
return self.config != None
def onRateScroll(self, event):
try:
if self.autorate:
return
if not self._try_get_config():
return
if (self.scrollock == 0):
self.scrollock = 1
self.updateSpinnerFlag = 1
self.dow.setUploadRate(self.rateslider.GetValue()
* connChoices[self.connChoice.GetSelection()]['rate'].get('div',1))
self.scrollock = 0
except:
self.exception()
def onConnScroll(self, event):
try:
if self.autorate:
return
if not self._try_get_config():
return
self.connSpinner.SetValue (self.connslider.GetValue ())
self.dow.setConns(self.connslider.GetValue())
except:
self.exception()
def onRateSpinner(self, event = None):
try:
if self.autorate:
return
if not self._try_get_config():
return
if (self.spinlock == 0):
self.spinlock = 1
spinnerValue = self.rateSpinner.GetValue()
div = connChoices[self.connChoice.GetSelection()]['rate'].get('div',1)
if div > 1:
if spinnerValue > (self.config['max_upload_rate']):
round_up = div - 1
else:
round_up = 0
newValue = int((spinnerValue + round_up) / div) * div
if newValue != spinnerValue:
self.rateSpinner.SetValue(newValue)
else:
newValue = spinnerValue
self.dow.setUploadRate(newValue)
self.updateSliderFlag = 1
self.spinlock = 0
except:
self.exception()
def onDownRateSpinner(self, event=None):
try:
if not self._try_get_config():
return
spinnerValue = self.downrateSpinner.GetValue()
self.dow.setDownloadRate(self.downrateSpinner.GetValue())
except:
self.exception()
def onConnSpinner(self, event = None):
try:
if self.autorate:
return
if not self._try_get_config():
return
self.connslider.SetValue (self.connSpinner.GetValue())
self.dow.setConns(self.connslider.GetValue())
except:
self.exception()
def onConnChoice(self, event, cons=None, rate=None):
try:
if not self._try_get_config():
return
num = self.connChoice.GetSelection()
choice = connChoices[num]
if choice.has_key('super-seed'): # selecting super-seed is now a toggle
self.dow.set_super_seed() # one way change, don't go back
self.connChoice.SetSelection(self.lastuploadsettings)
return
self.lastuploadsettings = num
self.current_ratesetting = self.connChoice.GetStringSelection()
if rate is None:
rate = choice['rate']['def']
self.rateSpinner.SetRange (choice['rate']['min'],
choice['rate']['max'])
self.rateSpinner.SetValue(rate)
self.rateslider.SetRange(
choice['rate']['min']/choice['rate'].get('div',1),
choice['rate']['max']/choice['rate'].get('div',1))
self.rateslider.SetValue (rate/choice['rate'].get('div',1))
self.rateLowerText.SetLabel (' %d' % (choice['rate']['min']))
self.rateUpperText.SetLabel ('%d' % (choice['rate']['max']))
if cons is None:
cons = choice['conn']['def']
self.connSpinner.SetRange (choice['conn']['min'],
choice['conn']['max'])
self.connSpinner.SetValue (cons)
self.connslider.SetRange (choice['conn']['min'],
choice['conn']['max'])
self.connslider.SetValue (cons)
self.connLowerText.SetLabel (' %d' % (choice['conn']['min']))
self.connUpperText.SetLabel ('%d' % (choice['conn']['max']))
self.onConnScroll (0)
self.onRateScroll (0)
self.dow.setInitiate(choice.get('initiate', 40))
if choice.has_key('automatic'):
if not self.autorate:
self.autorate = True
self.rateSpinner.Enable(False)
self.connSpinner.Enable(False)
self.dow.setUploadRate(-1)
else:
if self.autorate:
self.autorate = False
self.rateSpinner.Enable(True)
self.connSpinner.Enable(True)
self.onRateSpinner()
self.onConnSpinner()
except:
self.exception()
def about(self, event):
try:
if (self.aboutBox is not None):
try:
self.aboutBox.Close ()
except wxPyDeadObjectError, e:
self.aboutBox = None
self.aboutBox = wxFrame(None, -1, 'About BitTorrent', size = (1,1),
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
try:
self.aboutBox.SetIcon(self.icon)
except:
pass
panel = wxPanel(self.aboutBox, -1)
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
if color is not None:
x.SetForegroundColour(color)
return x
colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
titleSizer = wxBoxSizer(wxHORIZONTAL)
aboutTitle = StaticText('BitTorrent ' + version + ' ', self.FONT+4)
titleSizer.Add (aboutTitle)
linkDonate = StaticText('Donate to Bram', self.FONT, True, 'Blue')
titleSizer.Add (linkDonate, 1, wxALIGN_BOTTOM&wxEXPAND)
colSizer.Add(titleSizer, 0, wxEXPAND)
colSizer.Add(StaticText('created by Bram Cohen, Copyright 2001-2003,'))
colSizer.Add(StaticText('experimental version maintained by John Hoffman 2003'))
colSizer.Add(StaticText('modified from experimental version by Eike Frost 2003'))
credits = StaticText('full credits\n', self.FONT, True, 'Blue')
colSizer.Add(credits);
si = ( 'exact Version String: ' + version + '\n' +
'Python version: ' + sys.version + '\n' +
'wxWindows version: ' + wxVERSION_STRING + '\n' )
try:
si += 'Psyco version: ' + hex(psyco.__version__)[2:] + '\n'
except:
pass
colSizer.Add(StaticText(si))
babble1 = StaticText(
'This is an experimental, unofficial build of BitTorrent.\n' +
'It is Free Software under an MIT-Style license.')
babble2 = StaticText('BitTorrent Homepage (link)', self.FONT, True, 'Blue')
babble3 = StaticText("TheSHAD0W's Client Homepage (link)", self.FONT, True, 'Blue')
babble4 = StaticText("Eike Frost's Client Homepage (link)", self.FONT, True, 'Blue')
babble6 = StaticText('License Terms (link)', self.FONT, True, 'Blue')
colSizer.Add (babble1)
colSizer.Add (babble2)
colSizer.Add (babble3)
colSizer.Add (babble4)
colSizer.Add (babble6)
okButton = wxButton(panel, -1, 'Ok')
colSizer.Add(okButton, 0, wxALIGN_RIGHT)
colSizer.AddGrowableCol(0)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
def donatelink(self):
Thread(target = open_new('https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=bram@bitconjurer.org&item_name=BitTorrent&amount=5.00&submit=donate')).start()
EVT_LEFT_DOWN(linkDonate, donatelink)
def aboutlink(self):
Thread(target = open_new('http://bitconjurer.org/BitTorrent/')).start()
EVT_LEFT_DOWN(babble2, aboutlink)
def shadlink(self):
Thread(target = open_new('http://www.bittornado.com/')).start()
EVT_LEFT_DOWN(babble3, shadlink)
def explink(self):
Thread(target = open_new('http://ei.kefro.st/projects/btclient/')).start()
EVT_LEFT_DOWN(babble4, explink)
def licenselink(self):
Thread(target = open_new('http://ei.kefro.st/projects/btclient/LICENSE.TXT')).start()
EVT_LEFT_DOWN(babble6, licenselink)
EVT_LEFT_DOWN(credits, self.credits)
def closeAbout(e, self = self):
if self.aboutBox:
self.aboutBox.Close()
EVT_BUTTON(self.aboutBox, okButton.GetId(), closeAbout)
def kill(e, self = self):
try:
self.aboutBox.RemoveIcon()
except:
pass
self.aboutBox.Destroy()
self.aboutBox = None
EVT_CLOSE(self.aboutBox, kill)
self.aboutBox.Show()
border.Fit(panel)
self.aboutBox.Fit()
except:
self.exception()
def details(self, event):
try:
if not self.dow or not self.filename:
return
metainfo = self.dow.getResponse()
if metainfo is None:
return
if metainfo.has_key('announce'):
announce = metainfo['announce']
else:
announce = None
if metainfo.has_key('announce-list'):
announce_list = metainfo['announce-list']
else:
announce_list = None
info = metainfo['info']
info_hash = self.dow.infohash
piece_length = info['piece length']
fileselector = self.dow.fileselector
if (self.detailBox is not None):
try:
self.detailBox.Close()
except wxPyDeadObjectError, e:
self.detailBox = None
self.detailBox = wxFrame(None, -1, 'Torrent Details ', size = wxSize(405,230),
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
try:
self.detailBox.SetIcon(self.icon)
except:
pass
panel = wxPanel(self.detailBox, -1, size = wxSize (400,220))
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
x = wxStaticText(panel, -1, text, style = wxALIGN_CENTER_VERTICAL)
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
if color is not None:
x.SetForegroundColour(color)
return x
colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
colSizer.AddGrowableCol(0)
titleSizer = wxBoxSizer(wxHORIZONTAL)
aboutTitle = StaticText('Details about ' + self.filename, self.FONT+4)
titleSizer.Add (aboutTitle)
colSizer.Add (titleSizer)
detailSizer = wxFlexGridSizer(cols = 2, vgap = 6)
if info.has_key('length'):
fileListID = None
detailSizer.Add(StaticText('file name :'))
detailSizer.Add(StaticText(info['name']))
if info.has_key('md5sum'):
detailSizer.Add(StaticText('MD5 hash :'))
detailSizer.Add(StaticText(info['md5sum']))
file_length = info['length']
name = "file size"
else:
detail1Sizer = wxFlexGridSizer(cols = 1, vgap = 6)
detail1Sizer.Add(StaticText('directory name : ' + info['name']))
colSizer.Add (detail1Sizer)
bgallocButton = wxBitmapButton(panel, -1, self.allocbuttonBitmap, size = (52,20))
def bgalloc(self, frame = self):
if frame.dow.storagewrapper is not None:
frame.dow.storagewrapper.bgalloc()
EVT_BUTTON(self.detailBox, bgallocButton.GetId(), bgalloc)
bgallocbuttonSizer = wxFlexGridSizer(cols = 4, hgap = 4, vgap = 0)
bgallocbuttonSizer.Add(StaticText('(right-click to set priority)',self.FONT-1),0,wxALIGN_BOTTOM)
bgallocbuttonSizer.Add(StaticText('(finish allocation)'), -1, wxALIGN_CENTER_VERTICAL)
bgallocbuttonSizer.Add(bgallocButton, -1, wxALIGN_CENTER)
bgallocbuttonSizer.AddGrowableCol(0)
colSizer.Add(bgallocbuttonSizer, -1, wxEXPAND)
file_length = 0
fileListID = wxNewId()
fileList = wxListCtrl(panel, fileListID,
wxPoint(-1,-1), (325,100), wxLC_REPORT)
self.fileList = fileList
fileList.SetImageList(self.filestatusIcons, wxIMAGE_LIST_SMALL)
fileList.SetAutoLayout (True)
fileList.InsertColumn(0, "file")
fileList.InsertColumn(1, "", format=wxLIST_FORMAT_RIGHT, width=55)
fileList.InsertColumn(2, "")
for i in range(len(info['files'])):
x = wxListItem()
fileList.InsertItem(x)
x = 0
for file in info['files']:
path = ' '
for item in file['path']:
if (path != ''):
path = path + "/"
path = path + item
path += ' (' + str(file['length']) + ')'
fileList.SetStringItem(x, 0, path)
if file.has_key('md5sum'):
fileList.SetStringItem(x, 2, ' [' + str(file['md5sum']) + ']')
if fileselector:
p = fileselector[x]
item = self.fileList.GetItem(x)
item.SetTextColour(self.prioritycolors[p+1])
fileList.SetItem(item)
x += 1
file_length += file['length']
fileList.SetColumnWidth(0,wxLIST_AUTOSIZE)
fileList.SetColumnWidth(2,wxLIST_AUTOSIZE)
name = 'archive size'
colSizer.Add(fileList, 1, wxEXPAND)
colSizer.AddGrowableRow(3)
detailSizer.Add(StaticText('info_hash :'),0,wxALIGN_CENTER_VERTICAL)
detailSizer.Add(wxTextCtrl(panel, -1, tohex(info_hash), size = (325, -1), style = wxTE_READONLY))
num_pieces = int((file_length+piece_length-1)/piece_length)
detailSizer.Add(StaticText(name + ' : '))
detailSizer.Add(StaticText('%s (%s bytes)' % (size_format(file_length), comma_format(file_length))))
detailSizer.Add(StaticText('pieces : '))
if num_pieces > 1:
detailSizer.Add(StaticText('%i (%s bytes each)' % (num_pieces, comma_format(piece_length))))
else:
detailSizer.Add(StaticText('1'))
if announce_list is None:
detailSizer.Add(StaticText('announce url : '),0,wxALIGN_CENTER_VERTICAL)
detailSizer.Add(wxTextCtrl(panel, -1, announce, size = (325, -1), style = wxTE_READONLY))
else:
detailSizer.Add(StaticText(''))
trackerList = wxListCtrl(panel, -1, wxPoint(-1,-1), (325,75), wxLC_REPORT)
trackerList.SetAutoLayout (True)
trackerList.InsertColumn(0, "")
trackerList.InsertColumn(1, "announce urls")
for tier in range(len(announce_list)):
for t in range(len(announce_list[tier])):
i = wxListItem()
trackerList.InsertItem(i)
if announce is not None:
for l in [1,2]:
i = wxListItem()
trackerList.InsertItem(i)
x = 0
for tier in range(len(announce_list)):
for t in range(len(announce_list[tier])):
if t == 0:
trackerList.SetStringItem(x, 0, 'tier '+str(tier)+':')
trackerList.SetStringItem(x, 1, announce_list[tier][t])
x += 1
if announce is not None:
trackerList.SetStringItem(x+1, 0, 'single:')
trackerList.SetStringItem(x+1, 1, announce)
trackerList.SetColumnWidth(0,wxLIST_AUTOSIZE)
trackerList.SetColumnWidth(1,wxLIST_AUTOSIZE)
detailSizer.Add(trackerList)
if announce is None and announce_list is not None:
announce = announce_list[0][0]
if announce is not None:
detailSizer.Add(StaticText('likely tracker :'))
p = re.compile( '(.*/)[^/]+')
turl = p.sub (r'\1', announce)
trackerUrl = StaticText(turl, self.FONT, True, 'Blue')
detailSizer.Add(trackerUrl)
if metainfo.has_key('comment'):
detailSizer.Add(StaticText('comment :'))
detailSizer.Add(StaticText(metainfo['comment']))
if metainfo.has_key('creation date'):
detailSizer.Add(StaticText('creation date :'))
try:
detailSizer.Add(StaticText(
strftime('%x %X',localtime(metainfo['creation date']))))
except:
try:
detailSizer.Add(StaticText(metainfo['creation date']))
except:
detailSizer.Add(StaticText('<cannot read date>'))
detailSizer.AddGrowableCol(1)
colSizer.Add (detailSizer, 1, wxEXPAND)
okButton = wxButton(panel, -1, 'Ok')
colSizer.Add(okButton, 0, wxALIGN_RIGHT)
colSizer.AddGrowableCol(0)
if not self.configfileargs['gui_stretchwindow']:
aboutTitle.SetSize((400,-1))
else:
panel.SetAutoLayout(True)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
if fileselector and fileListID:
def onRightClick(evt, self = self):
s = []
i = -1
while True:
i = self.fileList.GetNextItem(i,state=wxLIST_STATE_SELECTED)
if i == -1:
break
s.append(i)
if not s: # just in case
return
oldstate = self.dow.fileselector[s[0]]
kind=wxITEM_RADIO
for i in s[1:]:
if self.dow.fileselector[i] != oldstate:
oldstate = None
kind = wxITEM_NORMAL
break
menu = wxMenu()
menu.Append(self.priorityIDs[1], "download first", kind=kind)
menu.Append(self.priorityIDs[2], "download normally", kind=kind)
menu.Append(self.priorityIDs[3], "download later", kind=kind)
menu.Append(self.priorityIDs[0], "download never (deletes)", kind=kind)
if oldstate is not None:
menu.Check(self.priorityIDs[oldstate+1], True)
def onSelection(evt, self = self, s = s):
p = evt.GetId()
priorities = self.dow.fileselector.get_priorities()
for i in xrange(len(self.priorityIDs)):
if p == self.priorityIDs[i]:
for ss in s:
priorities[ss] = i-1
item = self.fileList.GetItem(ss)
item.SetTextColour(self.prioritycolors[i])
self.fileList.SetItem(item)
self.dow.fileselector.set_priorities(priorities)
self.fileList.Refresh()
self.refresh_details = True
break
for id in self.priorityIDs:
EVT_MENU(self.detailBox, id, onSelection)
self.detailBox.PopupMenu(menu, evt.GetPoint())
EVT_LIST_ITEM_RIGHT_CLICK(self.detailBox, fileListID, onRightClick)
def closeDetail(evt, self = self):
if self.detailBox:
self.detailBox.Close()
EVT_BUTTON(self.detailBox, okButton.GetId(), closeDetail)
def kill(evt, self = self):
try:
self.detailBox.RemoveIcon()
except:
pass
self.detailBox.Destroy()
self.detailBox = None
self.fileList = None
self.dow.filedatflag.clear()
EVT_CLOSE(self.detailBox, kill)
def trackerurl(self, turl = turl):
try:
Thread(target = open_new(turl)).start()
except:
pass
EVT_LEFT_DOWN(trackerUrl, trackerurl)
self.detailBox.Show ()
border.Fit(panel)
self.detailBox.Fit()
self.refresh_details = True
self.dow.filedatflag.set()
except:
self.exception()
def credits(self, event):
try:
if (self.creditsBox is not None):
try:
self.creditsBox.Close()
except wxPyDeadObjectError, e:
self.creditsBox = None
self.creditsBox = wxFrame(None, -1, 'Credits', size = (1,1),
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
try:
self.creditsBox.SetIcon(self.icon)
except:
pass
panel = wxPanel(self.creditsBox, -1)
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
if color is not None:
x.SetForegroundColour(color)
return x
colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
titleSizer = wxBoxSizer(wxHORIZONTAL)
aboutTitle = StaticText('Credits', self.FONT+4)
titleSizer.Add (aboutTitle)
colSizer.Add (titleSizer)
colSizer.Add (StaticText(
'The following people have all helped with this\n' +
'version of BitTorrent in some way (in no particular order) -\n'));
creditSizer = wxFlexGridSizer(cols = 3)
creditSizer.Add(StaticText(
'Bill Bumgarner\n' +
'David Creswick\n' +
'Andrew Loewenstern\n' +
'Ross Cohen\n' +
'Jeremy Avnet\n' +
'Greg Broiles\n' +
'Barry Cohen\n' +
'Bram Cohen\n' +
'sayke\n' +
'Steve Jenson\n' +
'Myers Carpenter\n' +
'Francis Crick\n' +
'Petru Paler\n' +
'Jeff Darcy\n' +
'John Gilmore\n' +
'Xavier Bassery\n' +
'Pav Lucistnik'))
creditSizer.Add(StaticText(' '))
creditSizer.Add(StaticText(
'Yann Vernier\n' +
'Pat Mahoney\n' +
'Boris Zbarsky\n' +
'Eric Tiedemann\n' +
'Henry "Pi" James\n' +
'Loring Holden\n' +
'Robert Stone\n' +
'Michael Janssen\n' +
'Eike Frost\n' +
'Andrew Todd\n' +
'otaku\n' +
'Edward Keyes\n' +
'John Hoffman\n' +
'Uoti Urpala\n' +
'Jon Wolf\n' +
'Christoph Hohmann\n' +
'Micah Anderson'))
colSizer.Add (creditSizer, flag = wxALIGN_CENTER_HORIZONTAL)
okButton = wxButton(panel, -1, 'Ok')
colSizer.Add(okButton, 0, wxALIGN_RIGHT)
colSizer.AddGrowableCol(0)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
def closeCredits(e, self = self):
if self.creditsBox:
self.creditsBox.Close()
EVT_BUTTON(self.creditsBox, okButton.GetId(), closeCredits)
def kill(e, self = self):
try:
self.creditsBox.RemoveIcon()
except:
pass
self.creditsBox.Destroy()
self.creditsBox = None
EVT_CLOSE(self.creditsBox, kill)
self.creditsBox.Show()
border.Fit(panel)
self.creditsBox.Fit()
except:
self.exception()
def statusIconHelp(self, event):
try:
if (self.statusIconHelpBox is not None):
try:
self.statusIconHelpBox.Close()
except wxPyDeadObjectError, e:
self.statusIconHelpBox = None
self.statusIconHelpBox = wxFrame(None, -1, 'Help with the BitTorrent Status Light', size = (1,1),
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
try:
self.statusIconHelpBox.SetIcon(self.icon)
except:
pass
panel = wxPanel(self.statusIconHelpBox, -1)
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
if color is not None:
x.SetForegroundColour(color)
return x
fullsizer = wxFlexGridSizer(cols = 1, vgap = 13)
colsizer = wxFlexGridSizer(cols = 2, hgap = 13, vgap = 13)
disconnectedicon=self.createStatusIcon('disconnected')
colsizer.Add(wxStaticBitmap(panel, -1, disconnectedicon))
colsizer.Add(StaticText(
'Waiting to connect to the tracker.\n' +
'If the status light stays black for a long time the tracker\n' +
'you are trying to connect to may not be working. Unless you\n' +
'are receiving a message telling you otherwise, please wait,\n' +
'and BitTorrent will automatically try to reconnect for you.'), 1, wxALIGN_CENTER_VERTICAL)
noconnectionsicon=self.createStatusIcon('noconnections')
colsizer.Add(wxStaticBitmap(panel, -1, noconnectionsicon))
colsizer.Add(StaticText(
'You have no connections with other clients.\n' +
'Please be patient. If after several minutes the status\n' +
'light remains red, this torrent may be old and abandoned.'), 1, wxALIGN_CENTER_VERTICAL)
noincomingicon=self.createStatusIcon('noincoming')
colsizer.Add(wxStaticBitmap(panel, -1, noincomingicon))
colsizer.Add(StaticText(
'You have not received any incoming connections from others.\n' +
'It may only be because no one has tried. If you never see\n' +
'the status light turn green, it may indicate your system\n' +
'is behind a firewall or proxy server. Please look into\n' +
'routing BitTorrent through your firewall in order to receive\n' +
'the best possible download rate.'), 1, wxALIGN_CENTER_VERTICAL)
nocompletesicon=self.createStatusIcon('nocompletes')
colsizer.Add(wxStaticBitmap(panel, -1, nocompletesicon))
colsizer.Add(StaticText(
'There are no complete copies among the clients you are\n' +
'connected to. Don\'t panic, other clients in the torrent\n' +
"you can't see may have the missing data.\n" +
'If the status light remains blue, you may have problems\n' +
'completing your download.'), 1, wxALIGN_CENTER_VERTICAL)
allgoodicon=self.createStatusIcon('allgood')
colsizer.Add(wxStaticBitmap(panel, -1, allgoodicon))
colsizer.Add(StaticText(
'The torrent is operating properly.'), 1, wxALIGN_CENTER_VERTICAL)
fullsizer.Add(colsizer, 0, wxALIGN_CENTER)
colsizer2 = wxFlexGridSizer(cols = 1, hgap = 13)
colsizer2.Add(StaticText(
'Please note that the status light is not omniscient, and that it may\n' +
'be wrong in many instances. A torrent with a blue light may complete\n' +
"normally, and an occasional yellow light doesn't mean your computer\n" +
'has suddenly become firewalled.'), 1, wxALIGN_CENTER_VERTICAL)
colspacer = StaticText(' ')
colsizer2.Add(colspacer)
okButton = wxButton(panel, -1, 'Ok')
colsizer2.Add(okButton, 0, wxALIGN_CENTER)
fullsizer.Add(colsizer2, 0, wxALIGN_CENTER)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(fullsizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
def closeHelp(self, frame = self):
frame.statusIconHelpBox.Close()
EVT_BUTTON(self.statusIconHelpBox, okButton.GetId(), closeHelp)
self.statusIconHelpBox.Show ()
border.Fit(panel)
self.statusIconHelpBox.Fit()
except:
self.exception()
def openConfigMenu(self, event):
try:
self.configfile.configMenu(self)
except:
self.exception()
def advanced(self, event):
try:
if not self.dow or not self.filename:
return
if (self.advBox is not None):
try:
self.advBox.Close ()
except wxPyDeadObjectError, e:
self.advBox = None
self.advBox = wxFrame(None, -1, 'BitTorrent Advanced', size = wxSize(200,200),
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
try:
self.advBox.SetIcon(self.icon)
except:
pass
panel = wxPanel(self.advBox, -1, size = wxSize (200,200))
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
if color is not None:
x.SetForegroundColour(color)
return x
colSizer = wxFlexGridSizer (cols = 1, vgap = 1)
colSizer.Add (StaticText('Advanced Info for ' + self.filename, self.FONT+4))
try: # get system font width
fw = wxSystemSettings_GetFont(wxSYS_DEFAULT_GUI_FONT).GetPointSize()+1
except:
fw = wxSystemSettings_GetFont(wxSYS_SYSTEM_FONT).GetPointSize()+1
spewList = wxListCtrl(panel, -1, wxPoint(-1,-1), (fw*66,350), wxLC_REPORT|wxLC_HRULES|wxLC_VRULES)
self.spewList = spewList
spewList.SetAutoLayout (True)
colSizer.Add(spewList, -1, wxEXPAND)
colSizer.Add(StaticText(''))
self.storagestats1 = StaticText('')
self.storagestats2 = StaticText('')
colSizer.Add(self.storagestats1, -1, wxEXPAND)
colSizer.Add(self.storagestats2, -1, wxEXPAND)
spinnerSizer = wxFlexGridSizer(cols=4,vgap=0,hgap=0)
cstats = ' Listening on '
if self.connection_stats['interfaces']:
cstats += ', '.join(self.connection_stats['interfaces']) + ' on '
cstats += 'port ' + str(self.connection_stats['port'])
if self.connection_stats['upnp']:
cstats += ', UPnP port forwarded'
spinnerSizer.Add(StaticText(cstats), -1, wxEXPAND)
spinnerSizer.AddGrowableCol(0)
spinnerSizer.Add(StaticText('Max download rate (kB/s) '),0,wxALIGN_CENTER_VERTICAL)
self.downrateSpinner = wxSpinCtrl (panel, -1, "", (-1,-1), (50, -1))
self.downrateSpinner.SetFont(self.default_font)
self.downrateSpinner.SetRange(0,5000)
self.downrateSpinner.SetValue(self.config['max_download_rate'])
spinnerSizer.Add (self.downrateSpinner, 0)
EVT_SPINCTRL(self.downrateSpinner, -1, self.onDownRateSpinner)
spinnerSizer.Add(StaticText(' (0 = unlimited) '),0,wxALIGN_CENTER_VERTICAL)
colSizer.Add(spinnerSizer,0,wxEXPAND)
colSizer.Add(StaticText(''))
buttonSizer = wxFlexGridSizer (cols = 5, hgap = 20)
reannounceButton = wxButton(panel, -1, 'Manual Announce')
buttonSizer.Add (reannounceButton)
extannounceButton = wxButton(panel, -1, 'External Announce')
buttonSizer.Add (extannounceButton)
bgallocButton = wxButton(panel, -1, 'Finish Allocation')
buttonSizer.Add (bgallocButton)
buttonSizer.Add(StaticText(''))
okButton = wxButton(panel, -1, 'Ok')
buttonSizer.Add (okButton)
colSizer.Add (buttonSizer, 0, wxALIGN_CENTER)
colSizer.AddGrowableCol(0)
colSizer.AddGrowableRow(1)
panel.SetSizer(colSizer)
panel.SetAutoLayout(True)
spewList.InsertColumn(0, "Optimistic Unchoke", format=wxLIST_FORMAT_CENTER, width=fw*2)
spewList.InsertColumn(1, "Peer ID", width=0)
spewList.InsertColumn(2, "IP", width=fw*11)
spewList.InsertColumn(3, "Local/Remote", format=wxLIST_FORMAT_CENTER, width=fw*3)
spewList.InsertColumn(4, "Up", format=wxLIST_FORMAT_RIGHT, width=fw*6)
spewList.InsertColumn(5, "Interested", format=wxLIST_FORMAT_CENTER, width=fw*2)
spewList.InsertColumn(6, "Choking", format=wxLIST_FORMAT_CENTER, width=fw*2)
spewList.InsertColumn(7, "Down", format=wxLIST_FORMAT_RIGHT, width=fw*6)
spewList.InsertColumn(8, "Interesting", format=wxLIST_FORMAT_CENTER, width=fw*2)
spewList.InsertColumn(9, "Choked", format=wxLIST_FORMAT_CENTER, width=fw*2)
spewList.InsertColumn(10, "Snubbed", format=wxLIST_FORMAT_CENTER, width=fw*2)
spewList.InsertColumn(11, "Downloaded", format=wxLIST_FORMAT_RIGHT, width=fw*7)
spewList.InsertColumn(12, "Uploaded", format=wxLIST_FORMAT_RIGHT, width=fw*7)
spewList.InsertColumn(13, "Completed", format=wxLIST_FORMAT_RIGHT, width=fw*6)
spewList.InsertColumn(14, "Peer Download Speed", format=wxLIST_FORMAT_RIGHT, width=fw*6)
def reannounce(self, frame = self):
if (clock() - frame.reannouncelast > 60):
frame.reannouncelast = clock()
frame.dow.reannounce()
EVT_BUTTON(self.advBox, reannounceButton.GetId(), reannounce)
self.advextannouncebox = None
def reannounce_external(self, frame = self):
if (frame.advextannouncebox is not None):
try:
frame.advextannouncebox.Close ()
except wxPyDeadObjectError, e:
frame.advextannouncebox = None
frame.advextannouncebox = wxFrame(None, -1, 'External Announce', size = (1,1),
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
try:
frame.advextannouncebox.SetIcon(frame.icon)
except:
pass
panel = wxPanel(frame.advextannouncebox, -1)
fullsizer = wxFlexGridSizer(cols = 1, vgap = 13)
msg = wxStaticText(panel, -1, "Enter tracker anounce URL:")
msg.SetFont(frame.default_font)
fullsizer.Add(msg)
frame.advexturl = wxTextCtrl(parent = panel, id = -1, value = '',
size = (255, 20), style = wxTE_PROCESS_TAB)
frame.advexturl.SetFont(frame.default_font)
frame.advexturl.SetValue(frame.lastexternalannounce)
fullsizer.Add(frame.advexturl)
buttonSizer = wxFlexGridSizer (cols = 2, hgap = 10)
okButton = wxButton(panel, -1, 'OK')
buttonSizer.Add (okButton)
cancelButton = wxButton(panel, -1, 'Cancel')
buttonSizer.Add (cancelButton)
fullsizer.Add (buttonSizer, 0, wxALIGN_CENTER)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(fullsizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
def ok(self, frame = frame):
special = frame.advexturl.GetValue()
if special:
frame.lastexternalannounce = special
if (clock() - frame.reannouncelast > 60):
frame.reannouncelast = clock()
frame.dow.reannounce(special)
frame.advextannouncebox.Close()
EVT_BUTTON(frame.advextannouncebox, okButton.GetId(), ok)
def cancel(self, frame = frame):
frame.advextannouncebox.Close()
EVT_BUTTON(frame.advextannouncebox, cancelButton.GetId(), cancel)
frame.advextannouncebox.Show ()
fullsizer.Fit(panel)
frame.advextannouncebox.Fit()
EVT_BUTTON(self.advBox, extannounceButton.GetId(), reannounce_external)
def bgalloc(self, frame = self):
if frame.dow.storagewrapper is not None:
frame.dow.storagewrapper.bgalloc()
EVT_BUTTON(self.advBox, bgallocButton.GetId(), bgalloc)
def closeAdv(evt, self = self):
self.advBox.Close()
def killAdv(evt, self = self):
try:
self.advBox.RemoveIcon()
except:
pass
self.onDownRateSpinner()
self.dow.spewflag.clear()
self.advBox.Destroy()
self.advBox = None
if (self.advextannouncebox is not None):
try:
self.advextannouncebox.Close()
except wxPyDeadObjectError, e:
pass
self.advextannouncebox = None
EVT_BUTTON(self.advBox, okButton.GetId(), closeAdv)
EVT_CLOSE(self.advBox, killAdv)
self.advBox.Show ()
colSizer.Fit(panel)
self.advBox.Fit()
if self.dow:
self.dow.spewflag.set()
except:
self.exception()
def displayUsage(self, text):
self.invokeLater(self.onDisplayUsage, [text])
def onDisplayUsage(self, text):
try:
self.done(None)
w = wxFrame(None, -1, 'BITTORRENT USAGE',
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
panel = wxPanel(w, -1)
sizer = wxFlexGridSizer(cols = 1)
sizer.Add(wxTextCtrl(panel, -1, text,
size = (500,300), style = wxTE_READONLY|wxTE_MULTILINE))
okButton = wxButton(panel, -1, 'Ok')
def closeUsage(self, frame = self):
frame.usageBox.Close()
EVT_BUTTON(w, okButton.GetId(), closeUsage)
def kill(self, frame = self):
frame.usageBox.Destroy()
frame.usageBox = None
EVT_CLOSE(w, kill)
sizer.Add(okButton, 0, wxALIGN_RIGHT)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(sizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
border.Fit(panel)
w.Fit()
w.Show()
self.usageBox = w
except:
self.exception()
def updateStatus(self, dpflag = Event(), fractionDone = None,
timeEst = None, downRate = None, upRate = None,
activity = None, statistics = None, spew = None, sizeDone = None,
**kws):
if activity is not None:
self.activity = activity
self.gui_fractiondone = fractionDone
self.invokeLater(self.onUpdateStatus,
[dpflag, timeEst, downRate, upRate, statistics, spew, sizeDone])
def onUpdateStatus(self, dpflag, timeEst, downRate, upRate,
statistics, spew, sizeDone):
if self.firstupdate:
if not self.old_ratesettings:
self.old_ratesettings = {}
self.connChoice.SetStringSelection(
self.old_ratesettings.get('rate setting',
self.configfileargs['gui_ratesettingsdefault']))
self.onConnChoice(0,
self.old_ratesettings.get('uploads'),
self.old_ratesettings.get('max upload rate'))
if self.old_ratesettings.has_key('max download rate'):
self.dow.setDownloadRate(self.old_ratesettings['max download rate'])
if self.advBox:
self.downrateSpinner.SetValue(self.old_ratesettings['max download rate'])
self.firstupdate = False
if self.advBox:
self.dow.spewflag.set()
if self.ispaused or statistics is None:
self.setStatusIcon('startup')
elif statistics.numPeers + statistics.numSeeds + statistics.numOldSeeds == 0:
if statistics.last_failed:
self.setStatusIcon('disconnected')
else:
self.setStatusIcon('noconnections')
elif ( not statistics.external_connection_made
and not self.configfileargs['gui_forcegreenonfirewall'] ):
self.setStatusIcon('noincoming')
elif ( (statistics.numSeeds + statistics.numOldSeeds == 0)
and ( (self.fin and statistics.numCopies < 1)
or (not self.fin and statistics.numCopies2 < 1) ) ):
self.setStatusIcon('nocompletes')
elif timeEst == 0 and sizeDone < self.torrentsize:
self.setStatusIcon('nocompletes')
else:
self.setStatusIcon('allgood')
if statistics is None:
self.setgaugemode(-1)
elif self.gui_fractiondone == None or self.gui_fractiondone == 1.0:
self.setgaugemode(1)
else:
self.setgaugemode(0)
if self.updateSliderFlag == 1:
self.updateSliderFlag = 0
newValue = (self.rateSpinner.GetValue()
/ connChoices[self.connChoice.GetSelection()]['rate'].get('div',1))
if self.rateslider.GetValue() != newValue:
self.rateslider.SetValue(newValue)
if self.updateSpinnerFlag == 1:
self.updateSpinnerFlag = 0
cc = connChoices[self.connChoice.GetSelection()]
if cc.has_key('rate'):
newValue = (self.rateslider.GetValue() * cc['rate'].get('div',1))
if self.rateSpinner.GetValue() != newValue:
self.rateSpinner.SetValue(newValue)
if self.fin:
if statistics is not None:
if statistics.numOldSeeds > 0 or statistics.numCopies > 1:
self.gauge.SetValue(1000)
else:
self.gauge.SetValue(int(1000*statistics.numCopies))
elif self.gui_fractiondone is not None:
gaugelevel = int(self.gui_fractiondone * 1000)
self.gauge.SetValue(gaugelevel)
if statistics is not None and statistics.downTotal is not None:
if self.configfileargs['gui_displaymiscstats']:
self.frame.SetTitle('%.1f%% (%.2f MiB) %s - BitTorrent %s' % (float(gaugelevel)/10, float(sizeDone) / (1<<20), self.filename, version))
else:
self.frame.SetTitle('%.1f%% %s - BitTorrent %s' % (float(gaugelevel)/10, self.filename, version))
else:
self.frame.SetTitle('%.0f%% %s - BitTorrent %s' % (float(gaugelevel)/10, self.filename, version))
if self.ispaused:
self.timeText.SetLabel(hours(clock() - self.starttime) + ' /')
elif timeEst is None:
self.timeText.SetLabel(hours(clock() - self.starttime) + ' / ' + self.activity)
else:
self.timeText.SetLabel(hours(clock() - self.starttime) + ' / ' + hours(timeEst))
if not self.ispaused:
if downRate is not None:
self.downRateText.SetLabel('%.0f kB/s' % (float(downRate) / 1000))
if upRate is not None:
self.upRateText.SetLabel('%.0f kB/s' % (float(upRate) / 1000))
if self.taskbaricon:
icontext='BitTorrent '
if self.gui_fractiondone is not None and not self.fin:
if statistics is not None and statistics.downTotal is not None:
icontext=icontext+' %.1f%% (%.2f MiB)' % (self.gui_fractiondone*100, float(sizeDone) / (1<<20))
else:
icontext=icontext+' %.0f%%' % (self.gui_fractiondone*100)
if upRate is not None:
icontext=icontext+' u:%.0f kB/s' % (float(upRate) / 1000)
if downRate is not None:
icontext=icontext+' d:%.0f kB/s' % (float(downRate) / 1000)
icontext+=' %s' % self.filename
try:
if self.fin:
self.frame.tbicon.SetIcon(self.finicon,icontext)
else:
self.frame.tbicon.SetIcon(self.icon,icontext)
except:
pass
if statistics is not None:
if self.autorate:
self.rateSpinner.SetValue(statistics.upRate)
self.connSpinner.SetValue(statistics.upSlots)
downtotal = statistics.downTotal + self.old_download
uptotal = statistics.upTotal + self.old_upload
if self.configfileargs['gui_displaymiscstats']:
self.downText.SetLabel('%.2f MiB' % (float(downtotal) / (1 << 20)))
self.upText.SetLabel('%.2f MiB' % (float(uptotal) / (1 << 20)))
if downtotal > 0:
sharerating = float(uptotal)/downtotal
if sharerating == 0:
shareSmiley = ''
color = 'Black'
elif sharerating < 0.5:
shareSmiley = ':-('
color = 'Red'
elif sharerating < 1.0:
shareSmiley = ':-|'
color = 'Orange'
else:
shareSmiley = ':-)'
color = 'Forest Green'
elif uptotal == 0:
sharerating = None
shareSmiley = ''
color = 'Black'
else:
sharerating = None
shareSmiley = '00 :-D'
color = 'Forest Green'
if sharerating is None:
self.shareRatingText.SetLabel(shareSmiley)
else:
self.shareRatingText.SetLabel('%.3f %s' % (sharerating, shareSmiley))
self.shareRatingText.SetForegroundColour(color)
if self.configfileargs['gui_displaystats']:
if not self.fin:
self.seedStatusText.SetLabel('connected to %d seeds; also seeing %.3f distributed copies' % (statistics.numSeeds,0.001*int(1000*statistics.numCopies2)))
else:
self.seedStatusText.SetLabel('%d seeds seen recently; also seeing %.3f distributed copies' % (statistics.numOldSeeds,0.001*int(1000*statistics.numCopies)))
self.peerStatusText.SetLabel('connected to %d peers with an average of %.1f%% completed (total speed %.0f kB/s)' % (statistics.numPeers,statistics.percentDone,float(statistics.torrentRate) / (1000)))
if ((clock() - self.lastError) > 300):
self.errorText.SetLabel('')
if ( self.configfileargs['gui_displaymiscstats']
and statistics is not None and statistics.backgroundallocating ):
self.bgalloc_periods += 1
if self.bgalloc_periods > 3:
self.bgalloc_periods = 0
self.bgallocText.SetLabel('ALLOCATING'+(' .'*self.bgalloc_periods))
elif self.dow.superseedflag.isSet():
self.bgallocText.SetLabel('SUPER-SEED')
else:
self.bgallocText.SetLabel('')
if spew is not None and (clock()-self.spewwait>1):
if (self.advBox is not None):
self.spewwait = clock()
spewList = self.spewList
spewlen = len(spew)+2
if statistics is not None:
kickbanlen = len(statistics.peers_kicked)+len(statistics.peers_banned)
if kickbanlen:
spewlen += kickbanlen+1
else:
kickbanlen = 0
for x in range(spewlen-spewList.GetItemCount()):
i = wxListItem()
spewList.InsertItem(i)
for x in range(spewlen,spewList.GetItemCount()):
spewList.DeleteItem(len(spew)+1)
tot_uprate = 0.0
tot_downrate = 0.0
for x in range(len(spew)):
if (spew[x]['optimistic'] == 1):
a = '*'
else:
a = ' '
spewList.SetStringItem(x, 0, a)
spewList.SetStringItem(x, 1, spew[x]['id'])
spewList.SetStringItem(x, 2, spew[x]['ip'])
spewList.SetStringItem(x, 3, spew[x]['direction'])
if spew[x]['uprate'] > 100:
spewList.SetStringItem(x, 4, '%.0f kB/s' % (float(spew[x]['uprate']) / 1000))
else:
spewList.SetStringItem(x, 4, ' ')
tot_uprate += spew[x]['uprate']
if (spew[x]['uinterested'] == 1):
a = '*'
else:
a = ' '
spewList.SetStringItem(x, 5, a)
if (spew[x]['uchoked'] == 1):
a = '*'
else:
a = ' '
spewList.SetStringItem(x, 6, a)
if spew[x]['downrate'] > 100:
spewList.SetStringItem(x, 7, '%.0f kB/s' % (float(spew[x]['downrate']) / 1000))
else:
spewList.SetStringItem(x, 7, ' ')
tot_downrate += spew[x]['downrate']
if (spew[x]['dinterested'] == 1):
a = '*'
else:
a = ' '
spewList.SetStringItem(x, 8, a)
if (spew[x]['dchoked'] == 1):
a = '*'
else:
a = ' '
spewList.SetStringItem(x, 9, a)
if (spew[x]['snubbed'] == 1):
a = '*'
else:
a = ' '
spewList.SetStringItem(x, 10, a)
spewList.SetStringItem(x, 11, '%.2f MiB' % (float(spew[x]['dtotal']) / (1 << 20)))
if spew[x]['utotal'] is not None:
a = '%.2f MiB' % (float(spew[x]['utotal']) / (1 << 20))
else:
a = ''
spewList.SetStringItem(x, 12, a)
spewList.SetStringItem(x, 13, '%.1f%%' % (float(int(spew[x]['completed']*1000))/10))
if spew[x]['speed'] is not None:
a = '%.0f kB/s' % (float(spew[x]['speed']) / 1000)
else:
a = ''
spewList.SetStringItem(x, 14, a)
x = len(spew)
for i in range(15):
spewList.SetStringItem(x, i, '')
x += 1
spewList.SetStringItem(x, 2, ' TOTALS:')
spewList.SetStringItem(x, 4, '%.0f kB/s' % (float(tot_uprate) / 1000))
spewList.SetStringItem(x, 7, '%.0f kB/s' % (float(tot_downrate) / 1000))
if statistics is not None:
spewList.SetStringItem(x, 11, '%.2f MiB' % (float(statistics.downTotal) / (1 << 20)))
spewList.SetStringItem(x, 12, '%.2f MiB' % (float(statistics.upTotal) / (1 << 20)))
else:
spewList.SetStringItem(x, 11, '')
spewList.SetStringItem(x, 12, '')
for i in [0,1,3,5,6,8,9,10,13,14]:
spewList.SetStringItem(x, i, '')
if kickbanlen:
x += 1
for i in range(14):
spewList.SetStringItem(x, i, '')
for peer in statistics.peers_kicked:
x += 1
spewList.SetStringItem(x, 2, peer[0])
spewList.SetStringItem(x, 1, peer[1])
spewList.SetStringItem(x, 4, 'KICKED')
for i in [0,3,5,6,7,8,9,10,11,12,13,14]:
spewList.SetStringItem(x, i, '')
for peer in statistics.peers_banned:
x += 1
spewList.SetStringItem(x, 2, peer[0])
spewList.SetStringItem(x, 1, peer[1])
spewList.SetStringItem(x, 4, 'BANNED')
for i in [0,3,5,6,7,8,9,10,11,12,13,14]:
spewList.SetStringItem(x, i, '')
if statistics is not None:
l1 = (
' currently downloading %d pieces (%d just started), %d pieces partially retrieved'
% ( statistics.storage_active,
statistics.storage_new,
statistics.storage_dirty ) )
if statistics.storage_isendgame:
l1 += ', endgame mode'
self.storagestats2.SetLabel(l1)
self.storagestats1.SetLabel(
' %d of %d pieces complete (%d just downloaded), %d failed hash check, %sKiB redundant data discarded'
% ( statistics.storage_numcomplete,
statistics.storage_totalpieces,
statistics.storage_justdownloaded,
statistics.storage_numflunked,
comma_format(int(statistics.discarded/1024)) ) )
if ( self.fileList is not None and statistics is not None
and (statistics.filelistupdated.isSet() or self.refresh_details) ):
for i in range(len(statistics.filecomplete)):
if self.dow.fileselector[i] == -1:
self.fileList.SetItemImage(i,0,0)
self.fileList.SetStringItem(i,1,'')
elif statistics.fileinplace[i]:
self.fileList.SetItemImage(i,2,2)
self.fileList.SetStringItem(i,1,"done")
elif statistics.filecomplete[i]:
self.fileList.SetItemImage(i,1,1)
self.fileList.SetStringItem(i,1,"100%")
else:
self.fileList.SetItemImage(i,0,0)
frac = statistics.fileamtdone[i]
if frac:
self.fileList.SetStringItem(i,1,'%d%%' % (frac*100))
else:
self.fileList.SetStringItem(i,1,'')
statistics.filelistupdated.clear()
self.refresh_details = False
if self.configfile.configReset(): # whoopee! Set everything invisible! :-)
self.dow.config['security'] = self.configfileargs['security']
statsdisplayflag = self.configfileargs['gui_displaymiscstats']
self.downTextLabel.Show(statsdisplayflag)
self.upTextLabel.Show(statsdisplayflag)
self.fileDestLabel.Show(statsdisplayflag)
self.fileDestText.Show(statsdisplayflag)
self.colSizer.Layout()
self.downText.SetLabel('') # blank these to flush them
self.upText.SetLabel('')
self.seedStatusText.SetLabel('')
self.peerStatusText.SetLabel('')
ratesettingsmode = self.configfileargs['gui_ratesettingsmode']
ratesettingsflag1 = True #\ settings
ratesettingsflag2 = False #/ for 'basic'
if ratesettingsmode == 'none':
ratesettingsflag1 = False
elif ratesettingsmode == 'full':
ratesettingsflag2 = True
self.connChoiceLabel.Show(ratesettingsflag1)
self.connChoice.Show(ratesettingsflag1)
self.rateSpinnerLabel.Show(ratesettingsflag2)
self.rateSpinner.Show(ratesettingsflag2)
self.rateLowerText.Show(ratesettingsflag2)
self.rateUpperText.Show(ratesettingsflag2)
self.rateslider.Show(ratesettingsflag2)
self.connSpinnerLabel.Show(ratesettingsflag2)
self.connSpinner.Show(ratesettingsflag2)
self.connLowerText.Show(ratesettingsflag2)
self.connUpperText.Show(ratesettingsflag2)
self.connslider.Show(ratesettingsflag2)
self.unlimitedLabel.Show(ratesettingsflag2)
self.setgaugemode(None)
self.frame.Layout()
self.frame.Refresh()
self.gui_fractiondone = None
dpflag.set()
def finished(self):
self.fin = True
self.invokeLater(self.onFinishEvent)
def failed(self):
self.fin = True
self.invokeLater(self.onFailEvent)
def error(self, errormsg):
self.invokeLater(self.onErrorEvent, [errormsg])
def onFinishEvent(self):
self.activity = hours(clock() - self.starttime) + ' / ' +'Download Succeeded!'
self.cancelButton.SetLabel('Finish')
self.gauge.SetValue(0)
self.frame.SetTitle('%s - Upload - BitTorrent %s' % (self.filename, version))
try:
self.frame.SetIcon(self.finicon)
except:
pass
if self.taskbaricon:
self.frame.tbicon.SetIcon(self.finicon, "BitTorrent - Finished")
self.downRateText.SetLabel('')
def onFailEvent(self):
if not self.shuttingdown:
self.timeText.SetLabel(hours(clock() - self.starttime) + ' / ' +'Failed!')
self.activity = 'Failed!'
self.cancelButton.SetLabel('Close')
self.gauge.SetValue(0)
self.downRateText.SetLabel('')
self.setStatusIcon('startup')
def onErrorEvent(self, errormsg):
if errormsg[:2] == ' ': # indent at least 2 spaces means a warning message
self.errorText.SetLabel(errormsg)
self.lastError = clock()
else:
self.errorText.SetLabel(strftime('ERROR (%x %X) -\n') + errormsg)
self.lastError = clock()
def chooseFile(self, default, size, saveas, dir):
f = Event()
bucket = [None]
self.invokeLater(self.onChooseFile, [default, bucket, f, size, dir, saveas])
f.wait()
return bucket[0]
def onChooseFile(self, default, bucket, f, size, dir, saveas):
if saveas == '':
if self.configfileargs['gui_default_savedir'] != '':
start_dir = self.configfileargs['gui_default_savedir']
else:
start_dir = self.configfileargs['last_saved']
if not isdir(start_dir): # if it's not set properly
start_dir = '/' # yes, this hack does work in Windows
if dir:
start_dir1 = start_dir
if isdir(join(start_dir,default)):
start_dir = join(start_dir,default)
dl = wxDirDialog(self.frame,
'Choose a directory to save to, pick a partial download to resume',
defaultPath = start_dir, style = wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON)
else:
dl = wxFileDialog(self.frame,
'Choose file to save as, pick a partial download to resume',
defaultDir = start_dir, defaultFile = default, wildcard = '*',
style = wxSAVE)
if dl.ShowModal() != wxID_OK:
f.set()
self.done(None)
return
d = dl.GetPath()
if d == start_dir:
d = start_dir1
bucket[0] = d
d1,d2 = split(d)
if d2 == default:
d = d1
self.configfile.WriteLastSaved(d)
else:
bucket[0] = saveas
default = basename(saveas)
self.onChooseFileDone(default, size)
f.set()
def ChooseFileDone(self, name, size):
self.invokeLater(self.onChooseFileDone, [name, size])
def onChooseFileDone(self, name, size):
self.torrentsize = size
lname = basename(name)
self.filename = lname
self.fileNameText.SetLabel('%s' % (lname))
self.fileSizeText.SetLabel('(%.2f MiB)' % (float(size) / (1 << 20)))
self.timeText.SetLabel(hours(clock() - self.starttime) + ' / ' + self.activity)
self.fileDestText.SetLabel(name)
self.frame.SetTitle(lname + '- BitTorrent ' + version)
minsize = self.fileNameText.GetBestSize()
if (not self.configfileargs['gui_stretchwindow'] or
minsize.GetWidth() < self.addwidth):
minsize.SetWidth(self.addwidth)
self.fnsizer.SetMinSize (minsize)
minsize.SetHeight(self.fileSizeText.GetBestSize().GetHeight())
self.fnsizer2.SetMinSize (minsize)
minsize.SetWidth(minsize.GetWidth()+(self.FONT*8))
minsize.SetHeight(self.fileNameText.GetBestSize().GetHeight()+self.fileSizeText.GetBestSize().GetHeight())
minsize.SetHeight(2*self.errorText.GetBestSize().GetHeight())
self.errorTextSizer.SetMinSize(minsize)
self.topboxsizer.SetMinSize(minsize)
# Kludge to make details and about catch the event
self.frame.SetSize ((self.frame.GetSizeTuple()[0]+1, self.frame.GetSizeTuple()[1]+1))
self.frame.SetSize ((self.frame.GetSizeTuple()[0]-1, self.frame.GetSizeTuple()[1]-1))
self.colSizer.Fit(self.frame)
self.frame.Layout()
self.frame.Refresh()
def newpath(self, path):
self.invokeLater(self.onNewpath, [path])
def onNewpath(self, path):
self.fileDestText.SetLabel(path)
def pause(self, event):
self.invokeLater(self.onPause)
def onPause(self):
if not self.dow:
return
if self.ispaused:
self.ispaused = False
self.pauseButton.SetLabel('Pause')
self.dow.Unpause()
else:
if self.dow.Pause():
self.ispaused = True
self.pauseButton.SetLabel('Resume')
self.downRateText.SetLabel(' ')
self.upRateText.SetLabel(' ')
self.setStatusIcon('startup')
def done(self, event):
self.uiflag.set()
self.flag.set()
self.shuttingdown = True
try:
self.frame.tbicon.RemoveIcon()
except:
pass
try:
self.frame.tbicon.Destroy()
except:
pass
try:
self.detailBox.Close()
except:
self.detailBox = None
try:
self.aboutBox.Close()
except:
self.aboutBox = None
try:
self.creditsBox.Close()
except:
self.creditsBox = None
try:
self.advBox.Close()
except:
self.advBox = None
try:
self.statusIconHelpBox.Close()
except:
self.statusIconHelpBox = None
try:
self.frame.RemoveIcon()
except:
pass
self.frame.Destroy()
try:
self.icon.Destroy()
except:
pass
try:
self.finicon.Destroy()
except:
pass
def exception(self):
data = StringIO()
print_exc(file = data)
print data.getvalue() # report exception here too
self.on_errorwindow(data.getvalue())
def errorwindow(self, err):
self.invokeLater(self.on_errorwindow,[err])
def on_errorwindow(self, err):
if self._errorwindow is None:
w = wxFrame(None, -1, 'BITTORRENT ERROR', size = (1,1),
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
panel = wxPanel(w, -1)
sizer = wxFlexGridSizer(cols = 1)
t = ( 'BitTorrent ' + version + '\n' +
'OS: ' + sys.platform + '\n' +
'Python version: ' + sys.version + '\n' +
'wxWindows version: ' + wxVERSION_STRING + '\n' )
try:
t += 'Psyco version: ' + hex(psyco.__version__)[2:] + '\n'
except:
pass
try:
t += 'Allocation method: ' + self.config['alloc_type']
if self.dow.storagewrapper.bgalloc_active:
t += '*'
t += '\n'
except:
pass
sizer.Add(wxTextCtrl(panel, -1, t + '\n' + err,
size = (500,300), style = wxTE_READONLY|wxTE_MULTILINE))
sizer.Add(wxStaticText(panel, -1,
'\nHelp us iron out the bugs in the engine!'))
linkMail = wxStaticText(panel, -1,
'Please report this error to '+report_email)
linkMail.SetFont(wxFont(self.FONT, wxDEFAULT, wxNORMAL, wxNORMAL, True))
linkMail.SetForegroundColour('Blue')
sizer.Add(linkMail)
def maillink(self):
Thread(target = open_new("mailto:" + report_email
+ "?subject=autobugreport")).start()
EVT_LEFT_DOWN(linkMail, maillink)
border = wxBoxSizer(wxHORIZONTAL)
border.Add(sizer, 1, wxEXPAND | wxALL, 4)
panel.SetSizer(border)
panel.SetAutoLayout(True)
w.Show()
border.Fit(panel)
w.Fit()
self._errorwindow = w
class btWxApp(wxApp):
def __init__(self, x, params):
self.params = params
wxApp.__init__(self, x)
def OnInit(self):
doneflag = Event()
self.configfile = configReader()
d = DownloadInfoFrame(doneflag, self.configfile)
self.SetTopWindow(d.frame)
if len(self.params) == 0:
b = wxFileDialog (d.frame, 'Choose .torrent file to use',
defaultDir = '', defaultFile = '', wildcard = '*.torrent',
style = wxOPEN)
if b.ShowModal() == wxID_OK:
self.params.append (b.GetPath())
thread = Thread(target = next, args = [self.params, d, doneflag, self.configfile])
thread.setDaemon(False)
thread.start()
return 1
def run(params):
if WXPROFILER:
import profile, pstats
p = profile.Profile()
p.runcall(_run, params)
log = open('profile_data_wx.'+strftime('%y%m%d%H%M%S')+'.txt','a')
normalstdout = sys.stdout
sys.stdout = log
# pstats.Stats(p).strip_dirs().sort_stats('cumulative').print_stats()
pstats.Stats(p).strip_dirs().sort_stats('time').print_stats()
sys.stdout = normalstdout
else:
_run(params)
def _run(params):
app = btWxApp(0, params)
app.MainLoop()
def next(params, d, doneflag, configfile):
if PROFILER:
import profile, pstats
p = profile.Profile()
p.runcall(_next, params, d, doneflag, configfile)
log = open('profile_data.'+strftime('%y%m%d%H%M%S')+'.txt','a')
normalstdout = sys.stdout
sys.stdout = log
# pstats.Stats(p).strip_dirs().sort_stats('cumulative').print_stats()
pstats.Stats(p).strip_dirs().sort_stats('time').print_stats()
sys.stdout = normalstdout
else:
_next(params, d, doneflag, configfile)
def _next(params, d, doneflag, configfile):
err = False
try:
while 1:
try:
config = parse_params(params, configfile.config)
except ValueError, e:
d.error('error: ' + str(e) + '\nrun with no args for parameter explanations')
break
if not config:
d.displayUsage(get_usage(presets = configfile.config))
break
myid = createPeerID()
seed(myid)
rawserver = RawServer(doneflag, config['timeout_check_interval'],
config['timeout'], ipv6_enable = config['ipv6_enabled'],
failfunc = d.error, errorfunc = d.errorwindow)
upnp_type = UPnP_test(config['upnp_nat_access'])
while True:
try:
listen_port = rawserver.find_and_bind(config['minport'], config['maxport'],
config['bind'], ipv6_socket_style = config['ipv6_binds_v4'],
upnp = upnp_type, randomizer = config['random_port'])
break
except socketerror, e:
if upnp_type and e == UPnP_ERROR:
d.error('WARNING: COULD NOT FORWARD VIA UPnP')
upnp_type = 0
continue
d.error("Couldn't listen - " + str(e))
d.failed()
return
d.connection_stats = rawserver.get_stats()
response = get_response(config['responsefile'], config['url'], d.error)
if not response:
break
infohash = sha(bencode(response['info'])).digest()
torrentdata = configfile.getTorrentData(infohash)
if torrentdata:
oldsave = torrentdata.get('saved as')
d.old_ratesettings = torrentdata.get('rate settings')
s = torrentdata.get('stats')
if s:
d.old_upload = s['uploaded']
d.old_download = s['downloaded']
else:
oldsave = None
dow = BT1Download(d.updateStatus, d.finished, d.error, d.errorwindow, doneflag,
config, response, infohash, myid, rawserver, listen_port,
configfile.getConfigDir())
d.dow = dow
if config['gui_saveas_ask'] == 1:
oldsave = None
if oldsave:
if not dow.checkSaveLocation(oldsave):
oldsave = None
if oldsave:
def choosefile(default, size, saveas, dir, oldsave = oldsave):
d.ChooseFileDone(oldsave, size)
return oldsave
elif config['gui_saveas_ask'] == 0:
def choosefile(default, size, saveas, dir,
spot = config['gui_default_savedir']):
spot = os.path.join(spot,default)
d.ChooseFileDone(spot, size)
return spot
else:
choosefile = d.chooseFile
savedas = dow.saveAs(choosefile, d.newpath)
if not savedas:
break
if not dow.initFiles(old_style = True):
break
if not dow.startEngine():
dow.shutdown()
break
dow.startRerequester()
dow.autoStats()
if not dow.am_I_finished():
d.updateStatus(activity = 'connecting to peers')
rawserver.listen_forever(dow.getPortHandler())
ratesettings = {
'rate setting': d.current_ratesetting,
'max download rate': config['max_download_rate']
}
if d.current_ratesetting != 'automatic':
ratesettings['uploads'] = config['min_uploads']
ratesettings['max upload rate'] = config['max_upload_rate']
up, dn = dow.get_transfer_stats()
stats = {
'uploaded': up + d.old_upload,
'downloaded': dn + d.old_download
}
torrentdata = {
'saved as': savedas,
'rate settings': ratesettings,
'stats': stats
}
dow.shutdown(torrentdata)
break
except:
err = True
data = StringIO()
print_exc(file = data)
print data.getvalue() # report exception here too
d.errorwindow(data.getvalue())
try:
rawserver.shutdown()
except:
pass
if not d.fin:
d.failed()
if err:
sleep(3600*24*30) # this will make the app stick in the task manager,
# but so be it
if __name__ == '__main__':
if argv[1:] == ['--version']:
print version
exit(0)
run(argv[1:])
| No CVS admin address has been configured |
Powered by ViewCVS 0.9.3 |