1 theshadow 1.1 #!/usr/bin/env python
2
3 # Written by Bram Cohen and Myers Carpenter
|
4 theshadow 1.2 # Modifications by various people
|
5 theshadow 1.1 # see LICENSE.txt for license information
6
|
7 theshadow 1.41 from BitTorrent import PSYCO
|
8 theshadow 1.20 if PSYCO.psyco:
9 try:
10 import psyco
11 assert psyco.__version__ >= 0x010100f0
12 psyco.full()
13 except:
14 pass
15
|
16 theshadow 1.1 from sys import argv, version
17 assert version >= '2', "Install Python 2.0 or greater"
18
|
19 theshadow 1.32 from BitTorrent.download import Download
|
20 theshadow 1.2 from BitTorrent.ConnChoice import *
|
21 theshadow 1.35 from BitTorrent.ConfigReader import configReader
|
22 theshadow 1.36 from BitTorrent.bencode import bencode
|
23 theshadow 1.1 from threading import Event, Thread
|
24 theshadow 1.2 from os.path import *
|
25 theshadow 1.1 from os import getcwd
26 from wxPython.wx import *
|
27 theshadow 1.15 from time import strftime, time, localtime
|
28 theshadow 1.1 from webbrowser import open_new
|
29 theshadow 1.15 from traceback import print_exc
30 from StringIO import StringIO
|
31 theshadow 1.36 from sha import sha
|
32 theshadow 1.2 import re
|
33 theshadow 1.4 import sys, os
|
34 theshadow 1.6 from BitTorrent import version
|
35 theshadow 1.13
|
36 theshadow 1.2 true = 1
37 false = 0
|
38 theshadow 1.1
|
39 theshadow 1.11 PROFILER = false
40
|
41 theshadow 1.4 basepath=os.path.abspath(os.path.dirname(sys.argv[0]))
42
|
43 theshadow 1.1 def hours(n):
44 if n == -1:
45 return '<unknown>'
46 if n == 0:
47 return 'complete!'
48 n = int(n)
49 h, r = divmod(n, 60 * 60)
50 m, sec = divmod(r, 60)
51 if h > 1000000:
52 return '<unknown>'
53 if h > 0:
|
54 theshadow 1.3 return '%d hour(s) %02d min %02d sec' % (h, m, sec)
|
55 theshadow 1.1 else:
56 return '%d min %02d sec' % (m, sec)
57
|
58 theshadow 1.9 def size_format(s):
59 if (s < 1024):
60 r = str(s) + 'B'
61 elif (s < 1048576):
62 r = str(int(s/1024)) + 'KiB'
63 elif (s < 1073741824L):
64 r = str(int(s/1048576)) + 'MiB'
65 elif (s < 1099511627776L):
66 r = str(int((s/1073741824.0)*100.0)/100.0) + 'GiB'
67 else:
68 r = str(int((s/1099511627776.0)*100.0)/100.0) + 'TiB'
69 return(r)
70
71 def comma_format(s):
72 r = str(s)
73 for i in range(len(r)-3, 0, -3):
74 r = r[:i]+','+r[i:]
75 return(r)
76
|
77 theshadow 1.1 wxEVT_INVOKE = wxNewEventType()
78
79 def EVT_INVOKE(win, func):
80 win.Connect(-1, -1, wxEVT_INVOKE, func)
81
82 class InvokeEvent(wxPyEvent):
83 def __init__(self, func, args, kwargs):
84 wxPyEvent.__init__(self)
85 self.SetEventType(wxEVT_INVOKE)
86 self.func = func
87 self.args = args
88 self.kwargs = kwargs
89
|
90 theshadow 1.2 def pr(event):
91 print 'augh!'
92
|
93 theshadow 1.4
|
94 theshadow 1.1 class DownloadInfoFrame:
|
95 theshadow 1.13 def __init__(self, flag, configfile):
|
96 theshadow 1.16 try:
|
97 theshadow 1.13 self.FONT = configfile.configfileargs['gui_font']
|
98 theshadow 1.14 self.default_font = wxFont(self.FONT, wxDEFAULT, wxNORMAL, wxNORMAL, false)
|
99 theshadow 1.2 frame = wxFrame(None, -1, 'BitTorrent ' + version + ' download')
|
100 theshadow 1.3 self.aaa = 0
|
101 theshadow 1.1 self.flag = flag
|
102 theshadow 1.6 self.uiflag = Event()
|
103 theshadow 1.1 self.fin = false
|
104 theshadow 1.2 self.aboutBox = None
105 self.detailBox = None
|
106 theshadow 1.3 self.advBox = None
|
107 theshadow 1.2 self.creditsBox = None
|
108 theshadow 1.4 self.statusIconHelpBox = None
|
109 theshadow 1.3 self.reannouncelast = 0
|
110 theshadow 1.2 self.spinlock = 0
|
111 theshadow 1.4 self.scrollock = 0
|
112 theshadow 1.3 self.lastError = 0
|
113 theshadow 1.6 self.spewwait = time()
|
114 theshadow 1.3 self.config = None
|
115 theshadow 1.4 self.updateSpinnerFlag = 0
116 self.updateSliderFlag = 0
117 self.statusIconValue = ' '
118 self.iconized = 0
|
119 theshadow 1.5 self.checking = None
|
120 theshadow 1.6 self.activity = 'Starting up...'
121 self.firstupdate = true
122 self.shuttingdown = false
|
123 theshadow 1.7 self.ispaused = false
|
124 theshadow 1.9 self.bgalloc_periods = 0
125 self.gui_lastupdate = time()
|
126 theshadow 1.11 self.gui_fractiondone = None
127 self.fileList = None
|
128 theshadow 1.13 self.lastexternalannounce = ''
|
129 theshadow 1.15 self.refresh_details = false
130 self._errorwindow = None
|
131 theshadow 1.16 self.lastuploadsettings = 0
|
132 theshadow 1.21 self.filename = None
|
133 theshadow 1.11
134 wxInitAllImageHandlers()
135 self.statusIcons={
136 'startup':wxIcon(os.path.join(basepath,'white.ico'), wxBITMAP_TYPE_ICO),
137 'disconnected':wxIcon(os.path.join(basepath,'black.ico'), wxBITMAP_TYPE_ICO),
138 'noconnections':wxIcon(os.path.join(basepath,'red.ico'), wxBITMAP_TYPE_ICO),
139 'nocompletes':wxIcon(os.path.join(basepath,'blue.ico'), wxBITMAP_TYPE_ICO),
140 'noincoming':wxIcon(os.path.join(basepath,'yellow.ico'), wxBITMAP_TYPE_ICO),
141 'allgood':wxIcon(os.path.join(basepath,'green.ico'), wxBITMAP_TYPE_ICO)
142 }
143
144 self.filestatusIcons = wxImageList(16, 16)
145 self.filestatusIcons.Add(wxBitmap(os.path.join(basepath,'black1.ico'),wxBITMAP_TYPE_ICO))
146 self.filestatusIcons.Add(wxBitmap(os.path.join(basepath,'yellow1.ico'), wxBITMAP_TYPE_ICO))
147 self.filestatusIcons.Add(wxBitmap(os.path.join(basepath,'green1.ico'), wxBITMAP_TYPE_ICO))
148
149 self.allocbuttonBitmap = wxBitmap(os.path.join(basepath,'alloc.gif'), wxBITMAP_TYPE_GIF)
|
150 theshadow 1.3
|
151 theshadow 1.2 if (sys.platform == 'win32'):
|
152 theshadow 1.4 self.icon = wxIcon(os.path.join(basepath,'icon_bt.ico'), wxBITMAP_TYPE_ICO)
|
153 theshadow 1.2 self.starttime = time ()
154
155 self.frame = frame
156 if (sys.platform == 'win32'):
157 self.frame.SetIcon(self.icon)
|
158 theshadow 1.1
159 panel = wxPanel(frame, -1)
|
160 theshadow 1.11
|
161 theshadow 1.13 def StaticText(text, font = self.FONT, underline = false, color = None, panel = panel):
|
162 theshadow 1.11 x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
163 x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
164 if color is not None:
165 x.SetForegroundColour(color)
166 return x
167
|
168 theshadow 1.1 colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
|
169 theshadow 1.4
|
170 theshadow 1.2 border = wxBoxSizer(wxHORIZONTAL)
171 border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
172 panel.SetSizer(border)
173 panel.SetAutoLayout(true)
|
174 theshadow 1.1
|
175 theshadow 1.4 topboxsizer = wxFlexGridSizer(cols = 3, vgap = 0)
176 topboxsizer.AddGrowableCol (0)
177
178 fnsizer = wxFlexGridSizer(cols = 1, vgap = 0)
|
179 theshadow 1.3 fnsizer.AddGrowableCol (0)
|
180 theshadow 1.4 fnsizer.AddGrowableRow (1)
181
|
182 theshadow 1.13 fileNameText = StaticText('', self.FONT+4)
|
183 theshadow 1.2 fnsizer.Add(fileNameText, 1, wxALIGN_BOTTOM|wxEXPAND)
|
184 theshadow 1.4 self.fileNameText = fileNameText
185
186 fnsizer2 = wxFlexGridSizer(cols = 8, vgap = 0)
187 fnsizer2.AddGrowableCol (0)
188
|
189 theshadow 1.11 fileSizeText = StaticText('')
|
190 theshadow 1.4 fnsizer2.Add(fileSizeText, 1, wxALIGN_BOTTOM|wxEXPAND)
191 self.fileSizeText = fileSizeText
|
192 theshadow 1.2
|
193 theshadow 1.13 fileDetails = StaticText('Details', self.FONT, true, 'Blue')
|
194 theshadow 1.4 fnsizer2.Add(fileDetails, 0, wxALIGN_BOTTOM)
|
195 theshadow 1.2
|
196 theshadow 1.31 fnsizer2.Add(StaticText(' '))
|
197 theshadow 1.4
|
198 theshadow 1.13 advText = StaticText('Advanced', self.FONT, true, 'Blue')
|
199 theshadow 1.4 fnsizer2.Add(advText, 0, wxALIGN_BOTTOM)
|
200 theshadow 1.31 fnsizer2.Add(StaticText(' '))
|
201 theshadow 1.4
|
202 theshadow 1.13 prefsText = StaticText('Prefs', self.FONT, true, 'Blue')
|
203 theshadow 1.4 fnsizer2.Add(prefsText, 0, wxALIGN_BOTTOM)
|
204 theshadow 1.31 fnsizer2.Add(StaticText(' '))
|
205 theshadow 1.2
|
206 theshadow 1.13 aboutText = StaticText('About', self.FONT, true, 'Blue')
|
207 theshadow 1.4 fnsizer2.Add(aboutText, 0, wxALIGN_BOTTOM)
208
|
209 theshadow 1.31 fnsizer2.Add(StaticText(' '))
|
210 theshadow 1.4 fnsizer.Add(fnsizer2,0,wxEXPAND)
211 topboxsizer.Add(fnsizer,0,wxEXPAND)
|
212 theshadow 1.11 topboxsizer.Add(StaticText(' '))
|
213 theshadow 1.4
214 self.statusIcon = wxEmptyBitmap(32,32)
215 statidata = wxMemoryDC()
216 statidata.SelectObject(self.statusIcon)
217 statidata.SetPen(wxTRANSPARENT_PEN)
218 statidata.SetBrush(wxBrush(wx.wxSystemSettings_GetColour(wxSYS_COLOUR_MENU),wxSOLID))
219 statidata.DrawRectangle(0,0,32,32)
220 self.statusIconPtr = wxStaticBitmap(panel, -1, self.statusIcon)
221 topboxsizer.Add(self.statusIconPtr)
222
223
|
224 theshadow 1.2 self.fnsizer = fnsizer
|
225 theshadow 1.4 self.fnsizer2 = fnsizer2
226 self.topboxsizer = topboxsizer
227 colSizer.Add(topboxsizer, 0, wxEXPAND)
|
228 theshadow 1.1
229 self.gauge = wxGauge(panel, -1, range = 1000, style = wxGA_SMOOTH)
230 colSizer.Add(self.gauge, 0, wxEXPAND)
|
231 theshadow 1.4 # self.gauge.SetForegroundColour(wx.wxSystemSettings_GetColour(wxSYS_COLOUR_3DSHADOW))
|
232 theshadow 1.1
|
233 theshadow 1.2 timeSizer = wxFlexGridSizer(cols = 2)
|
234 theshadow 1.11 timeSizer.Add(StaticText('Time elapsed / estimated : '))
235 self.timeText = StaticText(self.activity+' ')
|
236 theshadow 1.2 timeSizer.Add(self.timeText)
237 timeSizer.AddGrowableCol(1)
238 colSizer.Add(timeSizer)
|
239 theshadow 1.1
|
240 theshadow 1.2 destSizer = wxFlexGridSizer(cols = 2, hgap = 8)
|
241 theshadow 1.11 self.fileDestLabel = StaticText('Download to:')
|
242 theshadow 1.4 destSizer.Add(self.fileDestLabel)
|
243 theshadow 1.11 self.fileDestText = StaticText('')
|
244 theshadow 1.2 destSizer.Add(self.fileDestText, flag = wxEXPAND)
245 destSizer.AddGrowableCol(1)
246 colSizer.Add(destSizer, flag = wxEXPAND)
|
247 theshadow 1.4 self.destSizer = destSizer
|
248 theshadow 1.2
249 statSizer = wxFlexGridSizer(cols = 3, hgap = 8)
250
251 self.ratesSizer = wxFlexGridSizer(cols = 2)
252 self.infoSizer = wxFlexGridSizer(cols = 2)
253
|
254 theshadow 1.11 self.ratesSizer.Add(StaticText(' Download rate: '))
|
255 theshadow 1.13 self.downRateText = StaticText('0 kB/s ')
|
256 theshadow 1.2 self.ratesSizer.Add(self.downRateText, flag = wxEXPAND)
257
|
258 theshadow 1.11 self.downTextLabel = StaticText('Downloaded: ')
|
259 theshadow 1.4 self.infoSizer.Add(self.downTextLabel)
|
260 theshadow 1.13 self.downText = StaticText('0.00 MiB ')
|
261 theshadow 1.2 self.infoSizer.Add(self.downText, flag = wxEXPAND)
262
|
263 theshadow 1.11 self.ratesSizer.Add(StaticText(' Upload rate: '))
|
264 theshadow 1.13 self.upRateText = StaticText('0 kB/s ')
|
265 theshadow 1.2 self.ratesSizer.Add(self.upRateText, flag = wxEXPAND)
266
|
267 theshadow 1.11 self.upTextLabel = StaticText('Uploaded: ')
|
268 theshadow 1.4 self.infoSizer.Add(self.upTextLabel)
|
269 theshadow 1.13 self.upText = StaticText('0.00 MiB ')
|
270 theshadow 1.2 self.infoSizer.Add(self.upText, flag = wxEXPAND)
271
272 shareSizer = wxFlexGridSizer(cols = 2, hgap = 8)
|
273 theshadow 1.11 shareSizer.Add(StaticText('Share rating:'))
274 self.shareRatingText = StaticText('')
|
275 theshadow 1.2 shareSizer.AddGrowableCol(1)
276 shareSizer.Add(self.shareRatingText, flag = wxEXPAND)
277
278 statSizer.Add(self.ratesSizer)
279 statSizer.Add(self.infoSizer)
280 statSizer.Add(shareSizer, flag = wxALIGN_CENTER_VERTICAL)
281 colSizer.Add (statSizer)
282
283 torrentSizer = wxFlexGridSizer(cols = 1)
|
284 theshadow 1.11 self.peerStatusText = StaticText('')
|
285 theshadow 1.2 torrentSizer.Add(self.peerStatusText, 0, wxEXPAND)
|
286 theshadow 1.11 self.seedStatusText = StaticText('')
|
287 theshadow 1.2 torrentSizer.Add(self.seedStatusText, 0, wxEXPAND)
288 torrentSizer.AddGrowableCol(0)
289 colSizer.Add(torrentSizer, 0, wxEXPAND)
|
290 theshadow 1.4 self.torrentSizer = torrentSizer
|
291 theshadow 1.1
|
292 theshadow 1.4 self.errorTextSizer = wxFlexGridSizer(cols = 1)
|
293 theshadow 1.13 self.errorText = StaticText('', self.FONT, false, 'Red')
|
294 theshadow 1.4 self.errorTextSizer.Add(self.errorText, 0, wxEXPAND)
295 colSizer.Add(self.errorTextSizer, 0, wxEXPAND)
|
296 theshadow 1.3
|
297 theshadow 1.7 cancelSizer=wxGridSizer(cols = 2, hgap = 40)
298 self.pauseButton = wxButton(panel, -1, 'Pause')
|
299 theshadow 1.15 # self.pauseButton.SetFont(self.default_font)
|
300 theshadow 1.7 cancelSizer.Add(self.pauseButton, 0, wxALIGN_CENTER)
301
|
302 theshadow 1.1 self.cancelButton = wxButton(panel, -1, 'Cancel')
|
303 theshadow 1.15 # self.cancelButton.SetFont(self.default_font)
|
304 theshadow 1.7 cancelSizer.Add(self.cancelButton, 0, wxALIGN_CENTER)
305 colSizer.Add(cancelSizer, 0, wxALIGN_CENTER)
|
306 theshadow 1.2
307 # Setting options
308
|
309 theshadow 1.3 slideSizer = wxFlexGridSizer(cols = 7, hgap = 0, vgap = 5)
|
310 theshadow 1.2
311 # dropdown
312
|
313 theshadow 1.11 self.connChoiceLabel = StaticText('Settings for ')
|
314 theshadow 1.9 slideSizer.Add (self.connChoiceLabel, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
|
315 theshadow 1.15 self.connChoice = wxChoice (panel, -1, (-1, -1), (self.FONT*11, -1),
316 choices = connChoiceList)
|
317 theshadow 1.14 self.connChoice.SetFont(self.default_font)
|
318 theshadow 1.2 self.connChoice.SetSelection(0)
319 slideSizer.Add (self.connChoice, 0, wxALIGN_CENTER)
|
320 theshadow 1.11 self.rateSpinnerLabel = StaticText(' Upload rate (kB/s) ')
|
321 theshadow 1.9 slideSizer.Add (self.rateSpinnerLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
|
322 theshadow 1.2
323 # max upload rate
324
325 self.rateSpinner = wxSpinCtrl (panel, -1, "", (-1,-1), (50, -1))
|
326 theshadow 1.14 self.rateSpinner.SetFont(self.default_font)
|
327 theshadow 1.2 self.rateSpinner.SetRange(0,5000)
328 self.rateSpinner.SetValue(0)
|
329 theshadow 1.9 slideSizer.Add (self.rateSpinner, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
|
330 theshadow 1.2
|
331 theshadow 1.11 self.rateLowerText = StaticText(' %5d' % (0))
332 self.rateUpperText = StaticText('%5d' % (5000))
|
333 theshadow 1.4 self.rateslider = wxSlider(panel, -1, 0, 0, 5000, (-1, -1), (80, -1))
|
334 theshadow 1.2
|
335 theshadow 1.9 slideSizer.Add(self.rateLowerText, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
336 slideSizer.Add(self.rateslider, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
337 slideSizer.Add(self.rateUpperText, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
|
338 theshadow 1.2
|
339 theshadow 1.11 slideSizer.Add(StaticText(''), 0, wxALIGN_LEFT)
|
340 theshadow 1.2
|
341 theshadow 1.13 self.bgallocText = StaticText('', self.FONT+2, false, 'Red')
|
342 theshadow 1.9 slideSizer.Add(self.bgallocText, 0, wxALIGN_LEFT)
|
343 theshadow 1.2
344 # max uploads
345
|
346 theshadow 1.11 self.connSpinnerLabel = StaticText(' Max uploads ')
|
347 theshadow 1.9 slideSizer.Add (self.connSpinnerLabel, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
|
348 theshadow 1.2 self.connSpinner = wxSpinCtrl (panel, -1, "", (-1,-1), (50, -1))
|
349 theshadow 1.14 self.connSpinner.SetFont(self.default_font)
|
350 theshadow 1.2 self.connSpinner.SetRange(4,100)
351 self.connSpinner.SetValue(4)
|
352 theshadow 1.9 slideSizer.Add (self.connSpinner, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
|
353 theshadow 1.2
|
354 theshadow 1.11 self.connLowerText = StaticText(' %5d' % (4))
355 self.connUpperText = StaticText('%5d' % (100))
|
356 theshadow 1.2 self.connslider = wxSlider(panel, -1, 4, 4, 100, (-1, -1), (80, -1))
357
|
358 theshadow 1.9 slideSizer.Add(self.connLowerText, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
359 slideSizer.Add(self.connslider, 0, wxALIGN_CENTER|wxALIGN_CENTER_VERTICAL)
360 slideSizer.Add(self.connUpperText, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
|
361 theshadow 1.2
362 colSizer.Add(slideSizer, 1, wxALL|wxALIGN_CENTER|wxEXPAND, 0)
363
|
364 theshadow 1.13 self.unlimitedLabel = StaticText('0 kB/s means unlimited. Tip: your download rate is proportional to your upload rate', self.FONT-2)
|
365 theshadow 1.4 colSizer.Add(self.unlimitedLabel, 0, wxALIGN_CENTER)
|
366 theshadow 1.2
367 EVT_LEFT_DOWN(aboutText, self.about)
368 EVT_LEFT_DOWN(fileDetails, self.details)
|
369 theshadow 1.4 EVT_LEFT_DOWN(self.statusIconPtr,self.statusIconHelp)
|
370 theshadow 1.3 EVT_LEFT_DOWN(advText, self.advanced)
|
371 theshadow 1.4 EVT_LEFT_DOWN(prefsText, self.openConfigMenu)
|
372 theshadow 1.2 EVT_CLOSE(frame, self.done)
|
373 theshadow 1.7 EVT_BUTTON(frame, self.pauseButton.GetId(), self.pause)
|
374 theshadow 1.2 EVT_BUTTON(frame, self.cancelButton.GetId(), self.done)
375 EVT_INVOKE(frame, self.onInvoke)
376 EVT_SCROLL(self.rateslider, self.onRateScroll)
377 EVT_SCROLL(self.connslider, self.onConnScroll)
378 EVT_CHOICE(self.connChoice, -1, self.onConnChoice)
379 EVT_SPINCTRL(self.connSpinner, -1, self.onConnSpinner)
380 EVT_SPINCTRL(self.rateSpinner, -1, self.onRateSpinner)
381 if (sys.platform == 'win32'):
|
382 theshadow 1.3 EVT_ICONIZE(self.frame, self.onIconify)
|
383 theshadow 1.2
|
384 theshadow 1.11 colSizer.AddGrowableCol (0)
385 colSizer.AddGrowableRow (6)
|
386 theshadow 1.2 self.frame.Show()
387 border.Fit(panel)
388 self.frame.Fit()
|
389 theshadow 1.3 self.panel = panel
390 self.border = border
|
391 theshadow 1.31 self.addwidth = aboutText.GetBestSize().GetWidth() + fileDetails.GetBestSize().GetWidth() + (self.FONT*14)
|
392 theshadow 1.3 self.fnsizer = fnsizer
393 self.colSizer = colSizer
394 minsize = self.colSizer.GetSize()
395 minsize.SetWidth (minsize.GetWidth())
396 minsize.SetHeight (minsize.GetHeight())
397 self.colSizer.SetMinSize (minsize)
398 self.colSizer.Fit(self.frame)
399 colSizer.Fit(frame)
|
400 theshadow 1.16 except:
401 self.exception()
402
403
404 def onInvoke(self, event):
405 if not self.uiflag.isSet():
406 try:
407 apply(event.func, event.args, event.kwargs)
408 except:
409 self.exception()
410
411
412 def invokeLater(self, func, args = [], kwargs = {}):
413 if not self.uiflag.isSet():
414 wxPostEvent(self.frame, InvokeEvent(func, args, kwargs))
|
415 theshadow 1.2
|
416 theshadow 1.4
417 def setStatusIcon(self, name):
418 if name != self.statusIconValue:
419 self.statusIconValue = name;
420 statidata = wxMemoryDC()
421 statidata.SelectObject(self.statusIcon)
422 statidata.BeginDrawing()
423 statidata.DrawIcon(self.statusIcons[name],0,0)
424 statidata.EndDrawing()
425 statidata.SelectObject(wxNullBitmap)
426 self.statusIconPtr.Refresh()
427
428
429 def createStatusIcon(self, name):
430 iconbuffer = wxEmptyBitmap(32,32)
431 bbdata = wxMemoryDC()
432 bbdata.SelectObject(iconbuffer)
433 bbdata.SetPen(wxTRANSPARENT_PEN)
434 bbdata.SetBrush(wxBrush(wx.wxSystemSettings_GetColour(wxSYS_COLOUR_MENU),wxSOLID))
435 bbdata.DrawRectangle(0,0,32,32)
436 bbdata.DrawIcon(self.statusIcons[name],0,0)
437 theshadow 1.4 return iconbuffer
438
439
|
440 theshadow 1.2 def onIconify(self, evt):
|
441 theshadow 1.17 try:
|
442 theshadow 1.4 if self.configfile.configfileargs['win32_taskbar_icon']:
443 if not hasattr(self.frame, "tbicon"):
444 self.frame.tbicon = wxTaskBarIcon()
445 self.frame.tbicon.SetIcon(self.icon, "BitTorrent")
446 # setup a taskbar icon, and catch some events from it
447 EVT_TASKBAR_LEFT_DCLICK(self.frame.tbicon, self.onTaskBarActivate)
448 EVT_TASKBAR_RIGHT_UP(self.frame.tbicon, self.onTaskBarMenu)
449 EVT_MENU(self.frame.tbicon, self.TBMENU_RESTORE, self.onTaskBarActivate)
450 EVT_MENU(self.frame.tbicon, self.TBMENU_CLOSE, self.done)
451 self.frame.Hide()
|
452 theshadow 1.3 else:
|
453 theshadow 1.4 EVT_ICONIZE(self.frame, self.onIconifyDummy)
454 if self.iconized:
455 self.frame.Iconize(false)
456 self.iconized = false
457 else:
458 self.frame.Iconize(true)
459 self.iconized = true
460 EVT_ICONIZE(self.frame, self.onIconify)
461 # rant here -- why in god's name can't a function called by an event
462 # trigger the event without calling itself?
463 # self.frame.Iconize(not self.frame.IsIconized()) should do this job...
|
464 theshadow 1.17 except:
465 self.exception()
|
466 theshadow 1.4
467 def onIconifyDummy(self, evt):
468 return
|
469 theshadow 1.2
470 def onTaskBarActivate(self, evt):
|
471 theshadow 1.17 try:
|
472 theshadow 1.2 if self.frame.IsIconized():
473 self.frame.Iconize(false)
474 if not self.frame.IsShown():
475 self.frame.Show(true)
|
476 theshadow 1.4 self.frame.Raise()
|
477 theshadow 1.2 if hasattr(self.frame, "tbicon"):
478 del self.frame.tbicon
|
479 theshadow 1.17 except:
480 self.exception()
|
481 theshadow 1.2
482 TBMENU_RESTORE = 1000
483 TBMENU_CLOSE = 1001
484
485 def onTaskBarMenu(self, evt):
486 menu = wxMenu()
487 menu.Append(self.TBMENU_RESTORE, "Restore BitTorrent")
488 menu.Append(self.TBMENU_CLOSE, "Close")
489 self.frame.tbicon.PopupMenu(menu)
490 menu.Destroy()
491
|
492 theshadow 1.24
493 def _try_get_config(self):
494 if self.config is None:
495 self.config = self.dow.getConfig()
496 return self.config != None
497
498
|
499 theshadow 1.2 def onRateScroll(self, event):
|
500 theshadow 1.17 try:
|
501 theshadow 1.4 if (self.scrollock == 0):
502 self.scrollock = 1
|
503 theshadow 1.24 if not self._try_get_config():
504 return
|
505 theshadow 1.26 self.updateSpinnerFlag = 1
506 self.dow.setUploadRate(self.rateslider.GetValue() * 1000
|
507 theshadow 1.7 * connChoices[self.connChoice.GetSelection()]['rate'].get('div',1))
|
508 theshadow 1.4 self.scrollock = 0
|
509 theshadow 1.17 except:
510 self.exception()
|
511 theshadow 1.2
512 def onConnScroll(self, event):
|
513 theshadow 1.17 try:
|
514 theshadow 1.24 if not self._try_get_config():
515 return
|
516 theshadow 1.2 self.connSpinner.SetValue (self.connslider.GetValue ())
|
517 theshadow 1.26 self.dow.setConns(self.connslider.GetValue())
|
518 theshadow 1.17 except:
519 self.exception()
|
520 theshadow 1.2
521 def onRateSpinner(self, event):
|
522 theshadow 1.17 try:
|
523 theshadow 1.24 if not self._try_get_config():
524 return
|
525 theshadow 1.2 if (self.spinlock == 0):
526 self.spinlock = 1
|
527 theshadow 1.7 spinnerValue = self.rateSpinner.GetValue()
528 div = connChoices[self.connChoice.GetSelection()]['rate'].get('div',1)
529 if div > 1:
530 if spinnerValue > (self.config['max_upload_rate']/1000):
531 round_up = div - 1
532 else:
533 round_up = 0
534 newValue = int((spinnerValue + round_up) / div) * div
535 if newValue != spinnerValue:
536 self.rateSpinner.SetValue(newValue)
|
537 theshadow 1.2 else:
|
538 theshadow 1.8 newValue = spinnerValue
|
539 theshadow 1.26 self.dow.setUploadRate(newValue * 1000)
|
540 theshadow 1.7 self.updateSliderFlag = 1
|
541 theshadow 1.2 self.spinlock = 0
|
542 theshadow 1.17 except:
543 self.exception()
|
544 theshadow 1.2
545 def onConnSpinner(self, event):
|
546 theshadow 1.17 try:
|
547 theshadow 1.24 if not self._try_get_config():
548 return
|
549 theshadow 1.2 self.connslider.SetValue (self.connSpinner.GetValue())
|
550 theshadow 1.26 self.dow.setConns(self.connslider.GetValue())
|
551 theshadow 1.17 except:
552 self.exception()
|
553 theshadow 1.2
554 def onConnChoice(self, event):
|
555 theshadow 1.17 try:
|
556 theshadow 1.24 if not self._try_get_config():
557 return
|
558 theshadow 1.2 num = self.connChoice.GetSelection()
|
559 theshadow 1.16 if connChoices[num].has_key('super-seed'): # selecting super-seed is now a toggle
560 self.dow.set_super_seed() # one way change, don't go back
561 num = self.lastuploadsettings
562 self.connChoice.SetSelection(num)
563 return
564 self.lastuploadsettings = num
|
565 theshadow 1.2 self.rateSpinner.SetRange (connChoices[num]['rate']['min'],
566 connChoices[num]['rate']['max'])
|
567 theshadow 1.4 self.rateSpinner.SetValue (connChoices[num]['rate']['def'])
|
568 theshadow 1.2 self.rateslider.SetRange (
569 connChoices[num]['rate']['min']/connChoices[num]['rate'].get('div',1),
570 connChoices[num]['rate']['max']/connChoices[num]['rate'].get('div',1))
571 self.rateslider.SetValue (
572 connChoices[num]['rate']['def']/connChoices[num]['rate'].get('div',1))
573 self.rateLowerText.SetLabel (' %d' % (connChoices[num]['rate']['min']))
574 self.rateUpperText.SetLabel ('%d' % (connChoices[num]['rate']['max']))
575 self.connSpinner.SetRange (connChoices[num]['conn']['min'],
576 connChoices[num]['conn']['max'])
|
577 theshadow 1.4 self.connSpinner.SetValue (connChoices[num]['conn']['def'])
|
578 theshadow 1.2 self.connslider.SetRange (connChoices[num]['conn']['min'],
579 connChoices[num]['conn']['max'])
580 self.connslider.SetValue (connChoices[num]['conn']['def'])
581 self.connLowerText.SetLabel (' %d' % (connChoices[num]['conn']['min']))
582 self.connUpperText.SetLabel ('%d' % (connChoices[num]['conn']['max']))
583 self.onConnScroll (0)
584 self.onRateScroll (0)
|
585 theshadow 1.26 self.dow.setInitiate(connChoices[num].get('initiate', 40))
|
586 theshadow 1.17 except:
587 self.exception()
|
588 theshadow 1.2
|
589 theshadow 1.4
|
590 theshadow 1.2 def about(self, event):
|
591 theshadow 1.17 try:
|
592 theshadow 1.2 if (self.aboutBox is not None):
593 try:
594 self.aboutBox.Close ()
595 except wxPyDeadObjectError, e:
596 self.aboutBox = None
597
598 self.aboutBox = wxFrame(None, -1, 'About BitTorrent', size = (1,1))
|
599 theshadow 1.3 if (sys.platform == 'win32'):
600 self.aboutBox.SetIcon(self.icon)
|
601 theshadow 1.2
602 panel = wxPanel(self.aboutBox, -1)
|
603 theshadow 1.11
|
604 theshadow 1.13 def StaticText(text, font = self.FONT, underline = false, color = None, panel = panel):
|
605 theshadow 1.11 x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
606 x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
607 if color is not None:
608 x.SetForegroundColour(color)
609 return x
610
|
611 theshadow 1.2 colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
612
613 titleSizer = wxBoxSizer(wxHORIZONTAL)
|
614 theshadow 1.13 aboutTitle = StaticText('BitTorrent ' + version + ' ', self.FONT+4)
|
615 theshadow 1.2 titleSizer.Add (aboutTitle)
|
616 theshadow 1.13 linkDonate = StaticText('Donate to Bram', self.FONT, true, 'Blue')
|
617 theshadow 1.2 titleSizer.Add (linkDonate, 1, wxALIGN_BOTTOM&wxEXPAND)
618 colSizer.Add(titleSizer, 0, wxEXPAND)
619
|
620 theshadow 1.11 colSizer.Add(StaticText('created by Bram Cohen, Copyright 2001-2003,'))
621 colSizer.Add(StaticText('experimental version maintained by John Hoffman 2003'))
622 colSizer.Add(StaticText('modified from experimental version by Eike Frost 2003'))
|
623 theshadow 1.13 credits = StaticText('full credits\n', self.FONT, true, 'Blue')
|
624 theshadow 1.2 colSizer.Add(credits);
625
|
626 theshadow 1.20 si = ( 'exact Version String: ' + version + '\n' +
627 'Python version: ' + sys.version + '\n' +
628 'wxWindows version: ' + wxVERSION_STRING + '\n' )
629 try:
630 si += 'Psyco version: ' + hex(psyco.__version__)[2:] + '\n'
631 except:
632 pass
633 colSizer.Add(StaticText(si))
|
634 theshadow 1.2
|
635 theshadow 1.11 babble1 = StaticText(
|
636 theshadow 1.2 'This is an experimental, unofficial build of BitTorrent.\n' +
637 'It is Free Software under an MIT-Style license.')
|
638 theshadow 1.13 babble2 = StaticText('BitTorrent Homepage (link)', self.FONT, true, 'Blue')
639 babble3 = StaticText("TheSHAD0W's Client Homepage (link)", self.FONT, true, 'Blue')
640 babble4 = StaticText("Eike Frost's Client Homepage (link)", self.FONT, true, 'Blue')
641 babble6 = StaticText('License Terms (link)', self.FONT, true, 'Blue')
|
642 theshadow 1.2 colSizer.Add (babble1)
643 colSizer.Add (babble2)
|
644 theshadow 1.6 colSizer.Add (babble3)
|
645 theshadow 1.2 colSizer.Add (babble4)
646 colSizer.Add (babble6)
647
648 okButton = wxButton(panel, -1, 'Ok')
|
649 theshadow 1.15 # okButton.SetFont(self.default_font)
|
650 theshadow 1.2 colSizer.Add(okButton, 0, wxALIGN_RIGHT)
|
651 theshadow 1.1 colSizer.AddGrowableCol(0)
652
653 border = wxBoxSizer(wxHORIZONTAL)
654 border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
655 panel.SetSizer(border)
656 panel.SetAutoLayout(true)
|
657 theshadow 1.2
|
658 theshadow 1.3 def donatelink(self):
659 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()
660 EVT_LEFT_DOWN(linkDonate, donatelink)
661 def aboutlink(self):
662 Thread(target = open_new('http://bitconjurer.org/BitTorrent/')).start()
663 EVT_LEFT_DOWN(babble2, aboutlink)
|
664 theshadow 1.6 def shadlink(self):
|
665 theshadow 1.9 Thread(target = open_new('http://bt.degreez.net/')).start()
|
666 theshadow 1.6 EVT_LEFT_DOWN(babble3, shadlink)
|
667 theshadow 1.3 def explink(self):
668 Thread(target = open_new('http://ei.kefro.st/projects/btclient/')).start()
669 EVT_LEFT_DOWN(babble4, explink)
670 def licenselink(self):
671 Thread(target = open_new('http://ei.kefro.st/projects/btclient/LICENSE.TXT')).start()
672 EVT_LEFT_DOWN(babble6, licenselink)
|
673 theshadow 1.2 EVT_LEFT_DOWN(credits, self.credits)
674
|
675 theshadow 1.3 def closeAbout(self, frame = self):
676 frame.aboutBox.Close ()
677 EVT_BUTTON(self.aboutBox, okButton.GetId(), closeAbout)
|
678 theshadow 1.11 def kill(self, frame = self):
679 frame.aboutBox.Destroy()
680 frame.aboutBox = None
681 EVT_CLOSE(self.aboutBox, kill)
|
682 theshadow 1.2
683 self.aboutBox.Show ()
684 border.Fit(panel)
685 self.aboutBox.Fit()
|
686 theshadow 1.17 except:
687 self.exception()
|
688 theshadow 1.2
|
689 theshadow 1.4
|
690 theshadow 1.2 def details(self, event):
|
691 theshadow 1.17 try:
|
692 theshadow 1.2 metainfo = self.dow.getResponse()
|
693 theshadow 1.18 if metainfo is None:
694 return
|
695 theshadow 1.11 if metainfo.has_key('announce'):
696 announce = metainfo['announce']
697 else:
698 announce = None
699 if metainfo.has_key('announce-list'):
700 announce_list = metainfo['announce-list']
701 else:
702 announce_list = None
|
703 theshadow 1.2 info = metainfo['info']
704 info_hash = sha(bencode(info))
705 piece_length = info['piece length']
706
707 if (self.detailBox is not None):
708 try:
709 self.detailBox.Close ()
710 except wxPyDeadObjectError, e:
711 self.detailBox = None
712
713 self.detailBox = wxFrame(None, -1, 'Torrent Details ', size = wxSize(405,230))
|
714 theshadow 1.3 if (sys.platform == 'win32'):
715 self.detailBox.SetIcon(self.icon)
|
716 theshadow 1.2
717 panel = wxPanel(self.detailBox, -1, size = wxSize (400,220))
|
718 theshadow 1.11
|
719 theshadow 1.13 def StaticText(text, font = self.FONT, underline = false, color = None, panel = panel):
|
720 theshadow 1.11 x = wxStaticText(panel, -1, text, style = wxALIGN_CENTER_VERTICAL)
721 x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
722 if color is not None:
723 x.SetForegroundColour(color)
724 return x
725
|
726 theshadow 1.2 colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
|
727 theshadow 1.9 colSizer.AddGrowableCol(0)
|
728 theshadow 1.2
729 titleSizer = wxBoxSizer(wxHORIZONTAL)
|
730 theshadow 1.13 aboutTitle = StaticText('Details about ' + self.filename, self.FONT+4)
|
731 theshadow 1.6
|
732 theshadow 1.2 titleSizer.Add (aboutTitle)
733 colSizer.Add (titleSizer)
734
|
735 theshadow 1.9 detailSizer = wxFlexGridSizer(cols = 2, vgap = 6)
|
736 theshadow 1.2
737 if info.has_key('length'):
|
738 theshadow 1.11 detailSizer.Add(StaticText('file name :'))
739 detailSizer.Add(StaticText(info['name']))
740 if info.has_key('md5sum'):
741 detailSizer.Add(StaticText('MD5 hash :'))
742 detailSizer.Add(StaticText(info['md5sum']))
|
743 theshadow 1.2 file_length = info['length']
|
744 theshadow 1.6 name = "file size"
|
745 theshadow 1.2 else:
|
746 theshadow 1.9 detail1Sizer = wxFlexGridSizer(cols = 1, vgap = 6)
|
747 theshadow 1.11 detail1Sizer.Add(StaticText('directory name : ' + info['name']))
748 colSizer.Add (detail1Sizer)
749 bgallocButton = wxBitmapButton(panel, -1, self.allocbuttonBitmap, size = (52,20))
750 def bgalloc(self, frame = self):
751 if frame.dow.storagewrapper is not None:
752 frame.dow.storagewrapper.bgalloc()
753 EVT_BUTTON(self.detailBox, bgallocButton.GetId(), bgalloc)
754
755 bgallocbuttonSizer = wxFlexGridSizer(cols = 3, hgap = 4, vgap = 0)
756 bgallocbuttonSizer.Add(StaticText('(finish allocation)'), -1, wxALIGN_CENTER_VERTICAL)
757 bgallocbuttonSizer.Add(bgallocButton, -1, wxALIGN_CENTER)
758 colSizer.Add(bgallocbuttonSizer, -1, wxALIGN_RIGHT)
759
|
760 theshadow 1.6 file_length = 0
761
762 fileList = wxListCtrl(panel, -1, wxPoint(-1,-1), (325,100), wxLC_REPORT)
|
763 theshadow 1.11 self.fileList = fileList
764 fileList.SetImageList(self.filestatusIcons, wxIMAGE_LIST_SMALL)
765
|
766 theshadow 1.6 fileList.SetAutoLayout (true)
|
767 theshadow 1.11 fileList.InsertColumn(0, "file")
768 fileList.InsertColumn(1, "", format=wxLIST_FORMAT_RIGHT, width=55)
769 fileList.InsertColumn(2, "")
770
771 for i in range(len(info['files'])):
772 x = wxListItem()
|
773 theshadow 1.15 # x.SetFont(self.default_font)
|
774 theshadow 1.11 fileList.InsertItem(x)
|
775 theshadow 1.6
776 x = 0
|
777 theshadow 1.2 for file in info['files']:
|
778 theshadow 1.11 path = ' '
|
779 theshadow 1.2 for item in file['path']:
780 if (path != ''):
781 path = path + "/"
782 path = path + item
|
783 theshadow 1.11 path += ' (' + str(file['length']) + ')'
784 fileList.SetStringItem(x, 0, path)
785 if file.has_key('md5sum'):
786 fileList.SetStringItem(x, 2, ' [' + str(file['md5sum']) + ']')
|
787 theshadow 1.6 x += 1
|
788 theshadow 1.2 file_length += file['length']
|
789 theshadow 1.9 fileList.SetColumnWidth(0,wxLIST_AUTOSIZE)
|
790 theshadow 1.11 fileList.SetColumnWidth(2,wxLIST_AUTOSIZE)
|
791 theshadow 1.6
|
792 theshadow 1.2 name = 'archive size'
|
793 theshadow 1.11 colSizer.Add(fileList, 1, wxEXPAND)
794 colSizer.AddGrowableRow(3)
|
795 theshadow 1.2
|
796 theshadow 1.11 detailSizer.Add(StaticText('info_hash :'),0,wxALIGN_CENTER_VERTICAL)
|
797 theshadow 1.6 detailSizer.Add(wxTextCtrl(panel, -1, info_hash.hexdigest(), size = (325, -1), style = wxTE_READONLY))
|
798 theshadow 1.10 num_pieces = int((file_length+piece_length-1)/piece_length)
|
799 theshadow 1.11 detailSizer.Add(StaticText(name + ' : '))
800 detailSizer.Add(StaticText('%s (%s bytes)' % (size_format(file_length), comma_format(file_length))))
801 detailSizer.Add(StaticText('pieces : '))
802 if num_pieces > 1:
803 detailSizer.Add(StaticText('%i (%s bytes each)' % (num_pieces, comma_format(piece_length))))
804 else:
805 detailSizer.Add(StaticText('1'))
806
807 if announce_list is None:
808 detailSizer.Add(StaticText('announce url : '),0,wxALIGN_CENTER_VERTICAL)
809 detailSizer.Add(wxTextCtrl(panel, -1, announce, size = (325, -1), style = wxTE_READONLY))
810 else:
811 detailSizer.Add(StaticText(''))
812 trackerList = wxListCtrl(panel, -1, wxPoint(-1,-1), (325,75), wxLC_REPORT)
813 trackerList.SetAutoLayout (true)
814 trackerList.InsertColumn(0, "")
815 trackerList.InsertColumn(1, "announce urls")
816
817 for tier in range(len(announce_list)):
818 for t in range(len(announce_list[tier])):
819 i = wxListItem()
|
820 theshadow 1.15 # i.SetFont(self.default_font)
|
821 theshadow 1.11 trackerList.InsertItem(i)
822 if announce is not None:
823 for l in [1,2]:
824 i = wxListItem()
|
825 theshadow 1.15 # i.SetFont(self.default_font)
|
826 theshadow 1.11 trackerList.InsertItem(i)
827
828 x = 0
829 for tier in range(len(announce_list)):
830 for t in range(len(announce_list[tier])):
831 if t == 0:
832 trackerList.SetStringItem(x, 0, 'tier '+str(tier)+':')
833 trackerList.SetStringItem(x, 1, announce_list[tier][t])
834 x += 1
835 if announce is not None:
836 trackerList.SetStringItem(x+1, 0, 'single:')
837 trackerList.SetStringItem(x+1, 1, announce)
838 trackerList.SetColumnWidth(0,wxLIST_AUTOSIZE)
839 trackerList.SetColumnWidth(1,wxLIST_AUTOSIZE)
840 detailSizer.Add(trackerList)
841
842 if announce is None and announce_list is not None:
843 announce = announce_list[0][0]
844 if announce is not None:
845 detailSizer.Add(StaticText('likely tracker :'))
846 p = re.compile( '(.*/)[^/]+')
847 theshadow 1.11 turl = p.sub (r'\1', announce)
|
848 theshadow 1.14 trackerUrl = StaticText(turl, self.FONT, true, 'Blue')
|
849 theshadow 1.11 detailSizer.Add(trackerUrl)
|
850 theshadow 1.15 if metainfo.has_key('comment'):
|
851 theshadow 1.11 detailSizer.Add(StaticText('comment :'))
|
852 theshadow 1.15 detailSizer.Add(StaticText(metainfo['comment']))
853 if metainfo.has_key('creation date'):
|
854 theshadow 1.11 detailSizer.Add(StaticText('creation date :'))
|
855 theshadow 1.17 try:
856 detailSizer.Add(StaticText(
857 strftime('%x %X',localtime(metainfo['creation date']))))
858 except:
859 try:
860 detailSizer.Add(StaticText(metainfo['creation date']))
861 except:
862 detailSizer.Add(StaticText('<cannot read date>'))
|
863 theshadow 1.2
|
864 theshadow 1.9 detailSizer.AddGrowableCol(1)
865 colSizer.Add (detailSizer, 1, wxEXPAND)
866
|
867 theshadow 1.2 okButton = wxButton(panel, -1, 'Ok')
|
868 theshadow 1.15 # okButton.SetFont(self.default_font)
|
869 theshadow 1.2 colSizer.Add(okButton, 0, wxALIGN_RIGHT)
870 colSizer.AddGrowableCol(0)
871
|
872 theshadow 1.6 if not self.configfile.configfileargs['gui_stretchwindow']:
873 aboutTitle.SetSize((400,-1))
874 else:
875 panel.SetAutoLayout(true)
876
|
877 theshadow 1.2 border = wxBoxSizer(wxHORIZONTAL)
878 border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
879 panel.SetSizer(border)
880 panel.SetAutoLayout(true)
881
|
882 theshadow 1.3 def closeDetail(self, frame = self):
883 frame.detailBox.Close ()
884 EVT_BUTTON(self.detailBox, okButton.GetId(), closeDetail)
|
885 theshadow 1.11 def kill(self, frame = self):
886 frame.detailBox.Destroy()
887 frame.detailBox = None
888 frame.fileList = None
|
889 theshadow 1.25 frame.dow.filedatflag.clear()
|
890 theshadow 1.11 EVT_CLOSE(self.detailBox, kill)
|
891 theshadow 1.2
|
892 theshadow 1.3 def trackerurl(self, turl = turl):
|
893 theshadow 1.2 Thread(target = open_new(turl)).start()
894
895 EVT_LEFT_DOWN(trackerUrl, trackerurl)
896
897 self.detailBox.Show ()
898 border.Fit(panel)
899 self.detailBox.Fit()
900
|
901 theshadow 1.17 self.refresh_details = true
|
902 theshadow 1.25 self.dow.filedatflag.set()
|
903 theshadow 1.17 except:
904 self.exception()
|
905 theshadow 1.15
906
|
907 theshadow 1.2 def credits(self, event):
|
908 theshadow 1.17 try:
|
909 theshadow 1.2 if (self.creditsBox is not None):
910 try:
911 self.creditsBox.Close ()
912 except wxPyDeadObjectError, e:
913 self.creditsBox = None
914
915 self.creditsBox = wxFrame(None, -1, 'Credits', size = (1,1))
|
916 theshadow 1.3 if (sys.platform == 'win32'):
917 self.creditsBox.SetIcon(self.icon)
|
918 theshadow 1.2
|
919 theshadow 1.4 panel = wxPanel(self.creditsBox, -1)
|
920 theshadow 1.11
|
921 theshadow 1.13 def StaticText(text, font = self.FONT, underline = false, color = None, panel = panel):
|
922 theshadow 1.11 x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
923 x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
924 if color is not None:
925 x.SetForegroundColour(color)
926 return x
927
|
928 theshadow 1.2 colSizer = wxFlexGridSizer(cols = 1, vgap = 3)
929
930 titleSizer = wxBoxSizer(wxHORIZONTAL)
|
931 theshadow 1.13 aboutTitle = StaticText('Credits', self.FONT+4)
|
932 theshadow 1.2 titleSizer.Add (aboutTitle)
933 colSizer.Add (titleSizer)
|
934 theshadow 1.11 colSizer.Add (StaticText(
|
935 theshadow 1.2 'The following people have all helped with this\n' +
936 'version of BitTorrent in some way (in no particular order) -\n'));
937 creditSizer = wxFlexGridSizer(cols = 3)
|
938 theshadow 1.11 creditSizer.Add(StaticText(
|
939 theshadow 1.2 'Bill Bumgarner\n' +
940 'David Creswick\n' +
941 'Andrew Loewenstern\n' +
942 'Ross Cohen\n' +
943 'Jeremy Avnet\n' +
944 'Greg Broiles\n' +
945 'Barry Cohen\n' +
946 'Bram Cohen\n' +
947 'sayke\n' +
948 'Steve Jenson\n' +
949 'Myers Carpenter\n' +
950 'Francis Crick\n' +
951 'Petru Paler\n' +
952 'Jeff Darcy\n' +
|
953 theshadow 1.22 'John Gilmore\n' +
|
954 theshadow 1.34 'Xavier Bassery\n' +
955 'Pav Lucistnik'))
|
956 theshadow 1.11 creditSizer.Add(StaticText(' '))
957 creditSizer.Add(StaticText(
|
958 theshadow 1.2 'Yann Vernier\n' +
959 'Pat Mahoney\n' +
960 'Boris Zbarsky\n' +
961 'Eric Tiedemann\n' +
962 'Henry "Pi" James\n' +
963 'Loring Holden\n' +
964 'Robert Stone\n' +
965 'Michael Janssen\n' +
966 'Eike Frost\n' +
967 'Andrew Todd\n' +
968 'otaku\n' +
|
969 theshadow 1.3 'Edward Keyes\n' +
|
970 theshadow 1.14 'John Hoffman\n' +
971 'Uoti Urpala\n' +
|
972 theshadow 1.28 'Jon Wolf\n' +
973 'Christoph Hohmann'))
|
974 theshadow 1.2 colSizer.Add (creditSizer, flag = wxALIGN_CENTER_HORIZONTAL)
975 okButton = wxButton(panel, -1, 'Ok')
|
976 theshadow 1.15 # okButton.SetFont(self.default_font)
|
977 theshadow 1.2 colSizer.Add(okButton, 0, wxALIGN_RIGHT)
978 colSizer.AddGrowableCol(0)
979
980 border = wxBoxSizer(wxHORIZONTAL)
981 border.Add(colSizer, 1, wxEXPAND | wxALL, 4)
982 panel.SetSizer(border)
983 panel.SetAutoLayout(true)
984
|
985 theshadow 1.3 def closeCredits(self, frame = self):
986 frame.creditsBox.Close ()
987 EVT_BUTTON(self.creditsBox, okButton.GetId(), closeCredits)
|
988 theshadow 1.11 def kill(self, frame = self):
989 frame.creditsBox.Destroy()
990 frame.creditsBox = None
991 EVT_CLOSE(self.creditsBox, kill)
|
992 theshadow 1.2
|
993 theshadow 1.22 self.creditsBox.Show()
|
994 theshadow 1.2 border.Fit(panel)
995 self.creditsBox.Fit()
|
996 theshadow 1.22 except:
997 self.exception()
|
998 theshadow 1.2
|
999 theshadow 1.4
1000 def statusIconHelp(self, event):
|
1001 theshadow 1.17 try:
|
1002 theshadow 1.4 if (self.statusIconHelpBox is not None):
1003 try:
1004 self.statusIconHelpBox.Close ()
1005 except wxPyDeadObjectError, e:
1006 self.statusIconHelpBox = None
1007
|
1008 theshadow 1.6 self.statusIconHelpBox = wxFrame(None, -1, 'Help with the BitTorrent Status Light', size = (1,1))
|
1009 theshadow 1.4 if (sys.platform == 'win32'):
1010 self.statusIconHelpBox.SetIcon(self.icon)
1011
1012 panel = wxPanel(self.statusIconHelpBox, -1)
|
1013 theshadow 1.11
|
1014 theshadow 1.13 def StaticText(text, font = self.FONT, underline = false, color = None, panel = panel):
|
1015 theshadow 1.11 x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
1016 x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
1017 if color is not None:
1018 x.SetForegroundColour(color)
1019 return x
1020
|
1021 theshadow 1.6 fullsizer = wxFlexGridSizer(cols = 1, vgap = 13)
1022 colsizer = wxFlexGridSizer(cols = 2, hgap = 13, vgap = 13)
|
1023 theshadow 1.4
1024 disconnectedicon=self.createStatusIcon('disconnected')
1025 colsizer.Add(wxStaticBitmap(panel, -1, disconnectedicon))
|
1026 theshadow 1.11 colsizer.Add(StaticText(
|
1027 theshadow 1.4 'Waiting to connect to the tracker.\n' +
|
1028 theshadow 1.6 'If the status light stays black for a long time the tracker\n' +
|
1029 theshadow 1.4 'you are trying to connect to may not be working. Unless you\n' +
1030 'are receiving a message telling you otherwise, please wait,\n' +
1031 'and BitTorrent will automatically try to reconnect for you.'), 1, wxALIGN_CENTER_VERTICAL)
1032
1033 noconnectionsicon=self.createStatusIcon('noconnections')
1034 colsizer.Add(wxStaticBitmap(panel, -1, noconnectionsicon))
|
1035 theshadow 1.11 colsizer.Add(StaticText(
|
1036 theshadow 1.4 'You have no connections with other clients.\n' +
1037 'Please be patient. If after several minutes the status\n' +
|
1038 theshadow 1.6 'light remains red, this torrent may be old and abandoned.'), 1, wxALIGN_CENTER_VERTICAL)
|
1039 theshadow 1.4
1040 noincomingicon=self.createStatusIcon('noincoming')
1041 colsizer.Add(wxStaticBitmap(panel, -1, noincomingicon))
|
1042 theshadow 1.11 colsizer.Add(StaticText(
|
1043 theshadow 1.6 'You have not received any incoming connections from others.\n' +
|
1044 theshadow 1.4 'It may only be because no one has tried. If you never see\n' +
|
1045 theshadow 1.6 'the status light turn green, it may indicate your system\n' +
|
1046 theshadow 1.4 'is behind a firewall or proxy server. Please look into\n' +
1047 'routing BitTorrent through your firewall in order to receive\n' +
1048 'the best possible download rate.'), 1, wxALIGN_CENTER_VERTICAL)
1049
|
1050 theshadow 1.15 nocompletesicon=self.createStatusIcon('nocompletes')
1051 colsizer.Add(wxStaticBitmap(panel, -1, nocompletesicon))
1052 colsizer.Add(StaticText(
1053 'There are no complete copies among the clients you are\n' +
1054 'connected to. Don\'t panic, other clients in the torrent\n' +
1055 "you can't see may have the missing data.\n" +
1056 'If the status light remains blue, you may have problems\n' +
1057 'completing your download.'), 1, wxALIGN_CENTER_VERTICAL)
1058
|
1059 theshadow 1.4 allgoodicon=self.createStatusIcon('allgood')
1060 colsizer.Add(wxStaticBitmap(panel, -1, allgoodicon))
|
1061 theshadow 1.11 colsizer.Add(StaticText(
|
1062 theshadow 1.4 'The torrent is operating properly.'), 1, wxALIGN_CENTER_VERTICAL)
|
1063 theshadow 1.6
1064 fullsizer.Add(colsizer, 0, wxALIGN_CENTER)
1065 colsizer2 = wxFlexGridSizer(cols = 1, hgap = 13)
1066
|
1067 theshadow 1.11 colsizer2.Add(StaticText(
|
1068 theshadow 1.6 'Please note that the status light is not omniscient, and that it may\n' +
1069 'be wrong in many instances. A torrent with a blue light may complete\n' +
1070 "normally, and an occasional yellow light doesn't mean your computer\n" +
1071 'has suddenly become firewalled.'), 1, wxALIGN_CENTER_VERTICAL)
1072
|
1073 theshadow 1.11 colspacer = StaticText(' ')
|
1074 theshadow 1.6 colsizer2.Add(colspacer)
|
1075 theshadow 1.4
1076 okButton = wxButton(panel, -1, 'Ok')
|
1077 theshadow 1.15 # okButton.SetFont(self.default_font)
|
1078 theshadow 1.6 colsizer2.Add(okButton, 0, wxALIGN_CENTER)
1079 fullsizer.Add(colsizer2, 0, wxALIGN_CENTER)
|
1080 theshadow 1.4
1081 border = wxBoxSizer(wxHORIZONTAL)
|
1082 theshadow 1.6 border.Add(fullsizer, 1, wxEXPAND | wxALL, 4)
|
1083 theshadow 1.4
1084 panel.SetSizer(border)
1085 panel.SetAutoLayout(true)
1086
1087
1088 def closeHelp(self, frame = self):
1089 frame.statusIconHelpBox.Close ()
1090 EVT_BUTTON(self.statusIconHelpBox, okButton.GetId(), closeHelp)
1091
1092 self.statusIconHelpBox.Show ()
1093 border.Fit(panel)
1094 self.statusIconHelpBox.Fit()
|
1095 theshadow 1.17 except:
1096 self.exception()
|
1097 theshadow 1.4
1098
1099 def openConfigMenu(self, event):
|
1100 theshadow 1.17 try:
1101 self.configfile.configMenu(self)
1102 except:
1103 self.exception()
|
1104 theshadow 1.4
1105
|
1106 theshadow 1.3 def advanced(self, event):
|
1107 theshadow 1.17 try:
|
1108 theshadow 1.21 if self.filename is None:
1109 return
|
1110 theshadow 1.3 if (self.advBox is not None):
1111 try:
1112 self.advBox.Close ()
1113 except wxPyDeadObjectError, e:
1114 self.advBox = None
1115
|
1116 theshadow 1.9 self.advBox = wxFrame(None, -1, 'BitTorrent Advanced', size = wxSize(200,200))
|
1117 theshadow 1.3 if (sys.platform == 'win32'):
1118 self.advBox.SetIcon(self.icon)
1119
1120 panel = wxPanel(self.advBox, -1, size = wxSize (200,200))
|
1121 theshadow 1.2
|
1122 theshadow 1.13 def StaticText(text, font = self.FONT, underline = false, color = None, panel = panel):
|
1123 theshadow 1.11 x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
1124 x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
1125 if color is not None:
1126 x.SetForegroundColour(color)
1127 return x
1128
1129 colSizer = wxFlexGridSizer (cols = 1, vgap = 1)
|
1130 theshadow 1.13 colSizer.Add (StaticText('Advanced Info for ' + self.filename, self.FONT+4))
|
1131 theshadow 1.15
1132 try: # get system font width
1133 fw = wxSystemSettings_GetFont(wxSYS_DEFAULT_GUI_FONT).GetPointSize()+1
1134 except:
1135 fw = wxSystemSettings_GetFont(wxSYS_SYSTEM_FONT).GetPointSize()+1
1136
|
1137 theshadow 1.19 spewList = wxListCtrl(panel, -1, wxPoint(-1,-1), (fw*66,350), wxLC_REPORT|wxLC_HRULES|wxLC_VRULES)
|
1138 theshadow 1.15 self.spewList = spewList
|
1139 theshadow 1.3 spewList.SetAutoLayout (true)
|
1140 theshadow 1.1
|
1141 theshadow 1.3 colSizer.Add(spewList, -1, wxEXPAND)
|
1142 theshadow 1.1
|
1143 theshadow 1.11 colSizer.Add(StaticText(''))
1144 self.storagestats1 = StaticText('')
1145 self.storagestats2 = StaticText('')
1146 colSizer.Add(self.storagestats1, -1, wxEXPAND)
1147 colSizer.Add(self.storagestats2, -1, wxEXPAND)
1148 colSizer.Add(StaticText(''))
1149
1150 buttonSizer = wxFlexGridSizer (cols = 5, hgap = 20)
|
1151 theshadow 1.3
|
1152 theshadow 1.11 reannounceButton = wxButton(panel, -1, 'Manual Announce')
|
1153 theshadow 1.15 # reannounceButton.SetFont(self.default_font)
|
1154 theshadow 1.3 buttonSizer.Add (reannounceButton)
1155
|
1156 theshadow 1.11 extannounceButton = wxButton(panel, -1, 'External Announce')
|
1157 theshadow 1.15 # extannounceButton.SetFont(self.default_font)
|
1158 theshadow 1.11 buttonSizer.Add (extannounceButton)
1159
|
1160 theshadow 1.9 bgallocButton = wxButton(panel, -1, 'Finish Allocation')
|
1161 theshadow 1.15 # bgallocButton.SetFont(self.default_font)
|
1162 theshadow 1.9 buttonSizer.Add (bgallocButton)
1163
|
1164 theshadow 1.11 buttonSizer.Add(StaticText(''))
1165
|
1166 theshadow 1.3 okButton = wxButton(panel, -1, 'Ok')
|
1167 theshadow 1.15 # okButton.SetFont(self.default_font)
|
1168 theshadow 1.11 buttonSizer.Add (okButton)
|
1169 theshadow 1.3
|
1170 theshadow 1.11 colSizer.Add (buttonSizer, 0, wxALIGN_CENTER)
1171 # colSizer.SetMinSize ((578,350))
1172 colSizer.AddGrowableCol(0)
1173 colSizer.AddGrowableRow(1)
|
1174 theshadow 1.3
1175 panel.SetSizer(colSizer)
1176 panel.SetAutoLayout(true)
1177
|
1178 theshadow 1.15 spewList.InsertColumn(0, "Optimistic Unchoke", format=wxLIST_FORMAT_CENTER, width=fw*2)
1179 spewList.InsertColumn(1, "IP", width=fw*11)
1180 spewList.InsertColumn(2, "Local/Remote", format=wxLIST_FORMAT_CENTER, width=fw*3)
1181 spewList.InsertColumn(3, "Up", format=wxLIST_FORMAT_RIGHT, width=fw*6)
1182 spewList.InsertColumn(4, "Interested", format=wxLIST_FORMAT_CENTER, width=fw*2)
1183 spewList.InsertColumn(5, "Choking", format=wxLIST_FORMAT_CENTER, width=fw*2)
|
1184 theshadow 1.19 spewList.InsertColumn(6, "Down", format=wxLIST_FORMAT_RIGHT, width=fw*6)
1185 spewList.InsertColumn(7, "Interesting", format=wxLIST_FORMAT_CENTER, width=fw*2)
1186 spewList.InsertColumn(8, "Choked", format=wxLIST_FORMAT_CENTER, width=fw*2)
1187 spewList.InsertColumn(9, "Snubbed", format=wxLIST_FORMAT_CENTER, width=fw*2)
1188 spewList.InsertColumn(10, "Downloaded", format=wxLIST_FORMAT_RIGHT, width=fw*7)
1189 spewList.InsertColumn(11, "Uploaded", format=wxLIST_FORMAT_RIGHT, width=fw*7)
1190 spewList.InsertColumn(12, "Completed", format=wxLIST_FORMAT_RIGHT, width=fw*6)
1191 spewList.InsertColumn(13, "Peer Download Speed", format=wxLIST_FORMAT_RIGHT, width=fw*6)
|
1192 theshadow 1.3
1193 def reannounce(self, frame = self):
1194 if (time () - frame.reannouncelast > 60):
1195 frame.reannouncelast = time ()
1196 frame.dow.reannounce()
1197 EVT_BUTTON(self.advBox, reannounceButton.GetId(), reannounce)
1198
|
1199 theshadow 1.11 self.advextannouncebox = None
1200 def reannounce_external(self, frame = self):
1201 if (frame.advextannouncebox is not None):
1202 try:
1203 frame.advextannouncebox.Close ()
1204 except wxPyDeadObjectError, e:
1205 frame.advextannouncebox = None
1206
1207 frame.advextannouncebox = wxFrame(None, -1, 'External Announce', size = (1,1))
1208 if (sys.platform == 'win32'):
1209 frame.advextannouncebox.SetIcon(frame.icon)
1210
1211 panel = wxPanel(frame.advextannouncebox, -1)
1212
1213 fullsizer = wxFlexGridSizer(cols = 1, vgap = 13)
|
1214 theshadow 1.14 msg = wxStaticText(panel, -1, "Enter tracker anounce URL:")
1215 msg.SetFont(frame.default_font)
1216 fullsizer.Add(msg)
|
1217 theshadow 1.11
1218 frame.advexturl = wxTextCtrl(parent = panel, id = -1, value = '',
1219 size = (255, 20), style = wxTE_PROCESS_TAB)
|
1220 theshadow 1.14 frame.advexturl.SetFont(frame.default_font)
|
1221 theshadow 1.13 frame.advexturl.SetValue(frame.lastexternalannounce)
|
1222 theshadow 1.11 fullsizer.Add(frame.advexturl)
1223
1224 buttonSizer = wxFlexGridSizer (cols = 2, hgap = 10)
1225
1226 okButton = wxButton(panel, -1, 'OK')
|
1227 theshadow 1.15 # okButton.SetFont(frame.default_font)
|
1228 theshadow 1.11 buttonSizer.Add (okButton)
1229
1230 cancelButton = wxButton(panel, -1, 'Cancel')
|
1231 theshadow 1.15 # cancelButton.SetFont(frame.default_font)
|
1232 theshadow 1.11 buttonSizer.Add (cancelButton)
1233
1234 fullsizer.Add (buttonSizer, 0, wxALIGN_CENTER)
1235
1236 border = wxBoxSizer(wxHORIZONTAL)
1237 border.Add(fullsizer, 1, wxEXPAND | wxALL, 4)
1238
1239 panel.SetSizer(border)
1240 panel.SetAutoLayout(true)
1241
1242 def ok(self, frame = frame):
|
1243 theshadow 1.13 special = frame.advexturl.GetValue()
1244 if special:
1245 frame.lastexternalannounce = special
1246 if (time () - frame.reannouncelast > 60):
1247 frame.reannouncelast = time ()
|
1248 theshadow 1.11 frame.dow.reannounce(special)
1249 frame.advextannouncebox.Close()
1250 EVT_BUTTON(frame.advextannouncebox, okButton.GetId(), ok)
1251
1252 def cancel(self, frame = frame):
1253 frame.advextannouncebox.Close()
|
1254 theshadow 1.13 EVT_BUTTON(frame.advextannouncebox, cancelButton.GetId(), cancel)
|
1255 theshadow 1.11
1256 def kill(self, frame = frame):
1257 frame.advextannouncebox.Destroy()
1258 frame.advextannouncebox = None
1259 EVT_CLOSE(frame.advextannouncebox, kill)
1260
1261 frame.advextannouncebox.Show ()
1262 fullsizer.Fit(panel)
1263 frame.advextannouncebox.Fit()
|
1264 theshadow 1.42
|
1265 theshadow 1.11 EVT_BUTTON(self.advBox, extannounceButton.GetId(), reannounce_external)
1266
|
1267 theshadow 1.9 def bgalloc(self, frame = self):
1268 if frame.dow.storagewrapper is not None:
1269 frame.dow.storagewrapper.bgalloc()
1270 EVT_BUTTON(self.advBox, bgallocButton.GetId(), bgalloc)
1271
|
1272 theshadow 1.11 def closeAdv(self, frame = self):
1273 frame.advBox.Close ()
1274 def killAdv(self, frame = self):
|
1275 theshadow 1.42 frame.dow.spewflag.clear()
|
1276 theshadow 1.11 frame.advBox.Destroy()
1277 frame.advBox = None
1278 if (frame.advextannouncebox is not None):
1279 try:
1280 frame.advextannouncebox.Close ()
1281 except wxPyDeadObjectError, e:
1282 pass
1283 frame.advextannouncebox = None
1284 EVT_BUTTON(self.advBox, okButton.GetId(), closeAdv)
1285 EVT_CLOSE(self.advBox, killAdv)
1286
|
1287 theshadow 1.3 self.advBox.Show ()
1288 colSizer.Fit(panel)
1289 self.advBox.Fit()
|
1290 theshadow 1.25 self.dow.spewflag.set()
|
1291 theshadow 1.17 except:
1292 self.exception()
|
1293 theshadow 1.1
|
1294 theshadow 1.6
1295 def displayUsage(self, text):
|
1296 theshadow 1.17 try:
|
1297 theshadow 1.6 start = self.dow.getUsageText()
|
1298 theshadow 1.9 if text[:len(start)] != start:
|
1299 theshadow 1.6 return false
1300
|
1301 theshadow 1.9 self.done(None)
|
1302 theshadow 1.6 self.usageBox = wxFrame(None, -1, 'Usage', size = (480,400))
1303 if (sys.platform == 'win32'):
1304 self.usageBox.SetIcon(self.icon)
1305
1306 panel = wxScrolledWindow(self.usageBox, -1)
1307 colSizer = wxFlexGridSizer(cols = 1)
1308
1309 colSizer.Add (wxStaticText(panel, -1, text))
1310 okButton = wxButton(panel, -1, 'Ok')
|
1311 theshadow 1.15 # okButton.SetFont(self.default_font)
|
1312 theshadow 1.6 colSizer.Add(okButton, 0, wxALIGN_RIGHT)
1313 colSizer.AddGrowableCol(0)
1314
1315
1316 def closeUsage(self, frame = self):
1317 frame.usageBox.Close()
1318 EVT_BUTTON(self.usageBox, okButton.GetId(), closeUsage)
|
1319 theshadow 1.11 def kill(self, frame = self):
1320 frame.usageBox.Destroy()
1321 frame.usageBox = None
1322 EVT_CLOSE(self.usageBox, kill)
|
1323 theshadow 1.6
1324 self.usageBox.Show ()
1325 panel.FitInside()
1326 panel.SetSizer(colSizer)
1327 panel.SetAutoLayout(true)
1328 panel.SetScrollRate(0,1)
1329 self.usageBox.Fit()
1330
1331 return true
|
1332 theshadow 1.17 except:
1333 self.exception()
|
1334 theshadow 1.6
|
1335 theshadow 1.1
1336 def updateStatus(self, fractionDone = None,
1337 timeEst = None, downRate = None, upRate = None,
|
1338 theshadow 1.3 activity = None, statistics = None, spew = None, sizeDone = None,
1339 **kws):
|
1340 theshadow 1.9 if activity is not None:
1341 self.activity = activity
|
1342 theshadow 1.11 if fractionDone is not None:
1343 self.gui_fractiondone = fractionDone
|
1344 theshadow 1.25 if self.gui_lastupdate + 0.05 > time(): # refreshing too fast, skip it
1345 return
|
1346 theshadow 1.9 if not self.ispaused:
1347 self.invokeLater(self.onUpdateStatus,
|
1348 theshadow 1.11 [timeEst, downRate, upRate, statistics, spew, sizeDone])
|
1349 theshadow 1.9
|
1350 theshadow 1.11 def onUpdateStatus(self, timeEst, downRate, upRate, statistics, spew, sizeDone):
|
1351 theshadow 1.23 if self.gui_lastupdate + 0.05 > time(): # refreshing too fast, skip it
|
1352 theshadow 1.9 return
|
1353 theshadow 1.1
|
1354 theshadow 1.6 if self.firstupdate:
1355 self.connChoice.SetStringSelection(self.configfile.configfileargs['gui_ratesettingsdefault'])
1356 self.onConnChoice(0) # force config selection for default value
1357 self.gauge.SetForegroundColour(self.configfile.checkingcolor)
1358 self.firstupdate = false
|
1359 theshadow 1.9
|
1360 theshadow 1.4 if statistics is None:
1361 self.setStatusIcon('startup')
1362 elif statistics.numPeers + statistics.numSeeds + statistics.numOldSeeds == 0:
1363 if statistics.last_failed:
1364 self.setStatusIcon('disconnected')
1365 else:
1366 self.setStatusIcon('noconnections')
|
1367 theshadow 1.14 elif ( not statistics.external_connection_made
1368 and not self.configfile.configfileargs['gui_forcegreenonfirewall'] ):
1369 self.setStatusIcon('noincoming')
1370 elif ( (statistics.numSeeds + statistics.numOldSeeds == 0)
1371 and ( (self.fin and statistics.numCopies < 1)
1372 or (not self.fin and statistics.numCopies2 < 1) ) ):
1373 self.setStatusIcon('nocompletes')
1374 else:
|
1375 theshadow 1.4 self.setStatusIcon('allgood')
1376
1377 if self.updateSliderFlag == 1:
1378 self.updateSliderFlag = 0
|
1379 theshadow 1.7 newValue = (self.rateSpinner.GetValue()
1380 / connChoices[self.connChoice.GetSelection()]['rate'].get('div',1))
1381 if self.rateslider.GetValue() != newValue:
1382 self.rateslider.SetValue(newValue)
1383
|
1384 theshadow 1.4 if self.updateSpinnerFlag == 1:
1385 self.updateSpinnerFlag = 0
|
1386 theshadow 1.40 cc = connChoices[self.connChoice.GetSelection()]
|
1387 theshadow 1.39 if cc.has_key('rate'):
1388 newValue = (self.rateslider.GetValue() * cc['rate'].get('div',1))
1389 if self.rateSpinner.GetValue() != newValue:
1390 self.rateSpinner.SetValue(newValue)
|
1391 theshadow 1.2 if self.fin:
1392 if statistics is not None:
1393 if statistics.numOldSeeds > 0 or statistics.numCopies > 1:
1394 self.gauge.SetValue(1000)
1395 else:
1396 self.gauge.SetValue(int(1000*statistics.numCopies))
|
1397 theshadow 1.11 elif self.gui_fractiondone is not None:
1398 gaugelevel = int(self.gui_fractiondone * 1000)
|
1399 theshadow 1.2 self.gauge.SetValue(gaugelevel)
|
1400 theshadow 1.3 if statistics is not None and statistics.downTotal is not None:
|
1401 theshadow 1.4 if self.configfile.configfileargs['gui_displaymiscstats']:
1402 self.frame.SetTitle('%.1f%% (%.2f MiB) %s - BitTorrent %s' % (float(gaugelevel)/10, float(sizeDone) / (1<<20), self.filename, version))
1403 else:
1404 self.frame.SetTitle('%.1f%% %s - BitTorrent %s' % (float(gaugelevel)/10, self.filename, version))
1405 self.gauge.SetForegroundColour(self.configfile.downloadcolor)
|
1406 theshadow 1.2 else:
1407 self.frame.SetTitle('%.0f%% %s - BitTorrent %s' % (float(gaugelevel)/10, self.filename, version))
|
1408 theshadow 1.1 if timeEst is not None:
|
1409 theshadow 1.2 self.timeText.SetLabel(hours(time () - self.starttime) + ' / ' + hours(timeEst))
|
1410 theshadow 1.6 else:
1411 if self.fin:
1412 self.timeText.SetLabel(self.activity)
1413 else:
1414 self.timeText.SetLabel(hours(time () - self.starttime) + ' / ' + self.activity)
|
1415 theshadow 1.1 if downRate is not None:
|
1416 theshadow 1.3 self.downRateText.SetLabel('%.0f kB/s' % (float(downRate) / 1000))
|
1417 theshadow 1.1 if upRate is not None:
|
1418 theshadow 1.3 self.upRateText.SetLabel('%.0f kB/s' % (float(upRate) / 1000))
|
1419 theshadow 1.2 if hasattr(self.frame, "tbicon"):
|
1420 theshadow 1.3 icontext='BitTorrent '
|
1421 theshadow 1.11 if self.gui_fractiondone is not None and not self.fin:
1422 if statistics is not None and statistics.downTotal is not None:
1423 icontext=icontext+' %.1f%% (%.2f MiB)' % (self.gui_fractiondone*100, float(sizeDone) / (1<<20))
1424 else:
1425 icontext=icontext+' %.0f%%' % (self.gui_fractiondone*100)
|
1426 theshadow 1.2 if upRate is not None:
|
1427 theshadow 1.3 icontext=icontext+' u:%.0f kB/s' % (float(upRate) / 1000)
|
1428 theshadow 1.2 if downRate is not None:
|
1429 theshadow 1.3 icontext=icontext+' d:%.0f kB/s' % (float(downRate) / 1000)
1430 icontext+=' %s' % self.filename
|
1431 theshadow 1.2 self.frame.tbicon.SetIcon(self.icon,icontext)
1432 if statistics is not None:
|
1433 theshadow 1.4 if self.configfile.configfileargs['gui_displaymiscstats']:
1434 self.downText.SetLabel('%.2f MiB' % (float(statistics.downTotal) / (1 << 20)))
1435 self.upText.SetLabel('%.2f MiB' % (float(statistics.upTotal) / (1 << 20)))
|
1436 theshadow 1.3 if (statistics.shareRating < 0) or (statistics.shareRating > 1000):
1437 self.shareRatingText.SetLabel('oo :-D')
1438 self.shareRatingText.SetForegroundColour('Forest Green')
1439 else:
1440 shareSmiley = ''
1441 color = 'Black'
1442 if ((statistics.shareRating >= 0) and (statistics.shareRating < 0.5)):
1443 shareSmiley = ':-('
1444 color = 'Red'
1445 else:
1446 if ((statistics.shareRating >= 0.5) and (statistics.shareRating < 1.0)):
1447 shareSmiley = ':-|'
1448 color = 'Orange'
1449 else:
1450 if (statistics.shareRating >= 1.0):
1451 shareSmiley = ':-)'
1452 color = 'Forest Green'
1453 self.shareRatingText.SetLabel('%.3f %s' % (statistics.shareRating, shareSmiley))
1454 self.shareRatingText.SetForegroundColour(color)
1455
|
1456 theshadow 1.4 if self.configfile.configfileargs['gui_displaystats']:
1457 if not self.fin:
|
1458 theshadow 1.14 self.seedStatusText.SetLabel('connected to %d seeds; also seeing %.3f distributed copies' % (statistics.numSeeds,0.001*int(1000*statistics.numCopies2)))
|
1459 theshadow 1.4 else:
1460 self.seedStatusText.SetLabel('%d seeds seen recently; also seeing %.3f distributed copies' % (statistics.numOldSeeds,0.001*int(1000*statistics.numCopies)))
1461 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)))
|
1462 theshadow 1.3 if ((time () - self.lastError) > 300):
1463 self.errorText.SetLabel('')
|
1464 theshadow 1.9
1465 if ( self.configfile.configfileargs['gui_displaymiscstats']
|
1466 theshadow 1.25 and statistics is not None and statistics.backgroundallocating ):
|
1467 theshadow 1.9 self.bgalloc_periods += 1
1468 if self.bgalloc_periods > 3:
1469 self.bgalloc_periods = 0
|
1470 theshadow 1.11 self.bgallocText.SetLabel('ALLOCATING'+(' .'*self.bgalloc_periods))
|
1471 theshadow 1.27 elif self.dow.superseedflag.isSet():
|
1472 theshadow 1.15 self.bgallocText.SetLabel('SUPER-SEED')
|
1473 theshadow 1.9 else:
1474 self.bgallocText.SetLabel('')
1475
|
1476 theshadow 1.4
|
1477 theshadow 1.3 if spew is not None and (time()-self.spewwait>1):
1478 if (self.advBox is not None):
1479 self.spewwait = time()
1480 spewList = self.spewList
|
1481 theshadow 1.29 spewlen = len(spew)+2
1482 if statistics is not None:
1483 kickbanlen = len(statistics.peers_kicked)+len(statistics.peers_banned)
1484 if kickbanlen:
1485 spewlen += kickbanlen+1
1486 else:
1487 kickbanlen = 0
1488 for x in range(spewlen-spewList.GetItemCount()):
|
1489 theshadow 1.11 i = wxListItem()
|
1490 theshadow 1.15 # i.SetFont(self.default_font)
|
1491 theshadow 1.11 spewList.InsertItem(i)
|
1492 theshadow 1.29 for x in range(spewlen,spewList.GetItemCount()):
|
1493 theshadow 1.13 spewList.DeleteItem(len(spew)+1)
|
1494 theshadow 1.3
|
1495 theshadow 1.9 tot_uprate = 0.0
1496 tot_downrate = 0.0
|
1497 theshadow 1.3 for x in range(len(spew)):
1498 if (spew[x]['optimistic'] == 1):
1499 a = '*'
1500 else:
1501 a = ' '
1502 spewList.SetStringItem(x, 0, a)
1503 spewList.SetStringItem(x, 1, spew[x]['ip'])
1504 spewList.SetStringItem(x, 2, spew[x]['direction'])
1505 if spew[x]['uprate'] > 100:
1506 spewList.SetStringItem(x, 3, '%.0f kB/s' % (float(spew[x]['uprate']) / 1000))
1507 else:
|
1508 theshadow 1.4 spewList.SetStringItem(x, 3, ' ')
|
1509 theshadow 1.9 tot_uprate += spew[x]['uprate']
|
1510 theshadow 1.3 if (spew[x]['uinterested'] == 1):
1511 a = '*'
1512 else:
1513 a = ' '
1514 spewList.SetStringItem(x, 4, a)
1515 if (spew[x]['uchoked'] == 1):
1516 a = '*'
1517 else:
1518 a = ' '
1519 spewList.SetStringItem(x, 5, a)
|
1520 theshadow 1.4
|
1521 theshadow 1.3 if spew[x]['downrate'] > 100:
|
1522 theshadow 1.19 spewList.SetStringItem(x, 6, '%.0f kB/s' % (float(spew[x]['downrate']) / 1000))
|
1523 theshadow 1.3 else:
|
1524 theshadow 1.19 spewList.SetStringItem(x, 6, ' ')
|
1525 theshadow 1.9 tot_downrate += spew[x]['downrate']
|
1526 theshadow 1.4
|
1527 theshadow 1.3 if (spew[x]['dinterested'] == 1):
1528 a = '*'
1529 else:
1530 a = ' '
|
1531 theshadow 1.19 spewList.SetStringItem(x, 7, a)
|
1532 theshadow 1.3 if (spew[x]['dchoked'] == 1):
1533 a = '*'
1534 else:
1535 a = ' '
|
1536 theshadow 1.19 spewList.SetStringItem(x, 8, a)
|
1537 theshadow 1.3 if (spew[x]['snubbed'] == 1):
1538 a = '*'
1539 else:
1540 a = ' '
|
1541 theshadow 1.19 spewList.SetStringItem(x, 9, a)
1542 spewList.SetStringItem(x, 10, '%.2f MiB' % (float(spew[x]['dtotal']) / (1 << 20)))
|
1543 theshadow 1.25 if spew[x]['utotal'] is not None:
1544 a = '%.2f MiB' % (float(spew[x]['utotal']) / (1 << 20))
1545 else:
1546 a = ''
1547 spewList.SetStringItem(x, 11, a)
|
1548 theshadow 1.19 spewList.SetStringItem(x, 12, '%.1f%%' % (float(int(spew[x]['completed']*1000))/10))
|
1549 theshadow 1.25 if spew[x]['speed'] is not None:
1550 a = '%.0f kB/s' % (float(spew[x]['speed']) / 1000)
1551 else:
1552 a = ''
1553 spewList.SetStringItem(x, 13, a)
|
1554 theshadow 1.9
|
1555 theshadow 1.29 x = len(spew)
1556 for i in range(14):
1557 spewList.SetStringItem(x, i, '')
|
1558 theshadow 1.9
|
1559 theshadow 1.29 x += 1
|
1560 theshadow 1.9 spewList.SetStringItem(x, 1, ' TOTALS:')
1561 spewList.SetStringItem(x, 3, '%.0f kB/s' % (float(tot_uprate) / 1000))
|
1562 theshadow 1.19 spewList.SetStringItem(x, 6, '%.0f kB/s' % (float(tot_downrate) / 1000))
|
1563 theshadow 1.9 if statistics is not None:
|
1564 theshadow 1.19 spewList.SetStringItem(x, 10, '%.2f MiB' % (float(statistics.downTotal) / (1 << 20)))
1565 spewList.SetStringItem(x, 11, '%.2f MiB' % (float(statistics.upTotal) / (1 << 20)))
|
1566 theshadow 1.9 else:
|
1567 theshadow 1.19 spewList.SetStringItem(x, 10, '')
|
1568 theshadow 1.9 spewList.SetStringItem(x, 11, '')
|
1569 theshadow 1.29 for i in [0,2,4,5,7,8,9,12,13]:
1570 spewList.SetStringItem(x, i, '')
1571
1572 if kickbanlen:
1573 x += 1
1574 for i in range(14):
1575 spewList.SetStringItem(x, i, '')
1576
1577 for ip in statistics.peers_kicked:
1578 x += 1
1579 spewList.SetStringItem(x, 1, ip)
1580 spewList.SetStringItem(x, 3, 'KICKED')
1581 for i in [0,2,4,5,6,7,8,9,10,11,12,13]:
1582 spewList.SetStringItem(x, i, '')
1583
1584 for ip in statistics.peers_banned:
1585 x += 1
1586 spewList.SetStringItem(x, 1, ip)
1587 spewList.SetStringItem(x, 3, 'BANNED')
1588 for i in [0,2,4,5,6,7,8,9,10,11,12,13]:
1589 spewList.SetStringItem(x, i, '')
|
1590 theshadow 1.9
|
1591 theshadow 1.25 if statistics is not None:
|
1592 theshadow 1.11 self.storagestats1.SetLabel(
|
1593 theshadow 1.22 ' currently downloading %d pieces (%d just started), %d pieces partially retrieved'
|
1594 theshadow 1.25 % ( statistics.storage_active,
1595 statistics.storage_new,
1596 statistics.storage_dirty ) )
|
1597 theshadow 1.11 self.storagestats2.SetLabel(
1598 ' %d of %d pieces complete (%d just downloaded), %d failed hash check'
|
1599 theshadow 1.25 % ( statistics.storage_numcomplete,
1600 statistics.storage_totalpieces,
1601 statistics.storage_justdownloaded,
1602 statistics.storage_numflunked ) )
|
1603 theshadow 1.11
|
1604 theshadow 1.15 if ( self.fileList is not None and statistics is not None
1605 and (statistics.filelistupdated or self.refresh_details) ):
1606 self.refresh_details = false
|
1607 theshadow 1.11 statistics.filelistupdated = false
1608 for i in range(len(statistics.filecomplete)):
1609 if statistics.fileinplace[i]:
1610 self.fileList.SetItemImage(i,2,2)
1611 self.fileList.SetStringItem(i,1,"done")
1612 elif statistics.filecomplete[i]:
1613 self.fileList.SetItemImage(i,1,1)
1614 self.fileList.SetStringItem(i,1,"100%")
1615 else:
1616 frac = int((len(statistics.filepieces2[i])-len(statistics.filepieces[i]))*100
1617 /len(statistics.filepieces2[i]))
1618 if frac > 0:
1619 self.fileList.SetStringItem(i,1,'%d%%' % (frac))
|
1620 theshadow 1.9
|
1621 theshadow 1.4 if self.configfile.configReset: # whoopee! Set everything invisible! :-)
1622 self.configfile.configReset = false
|
1623 theshadow 1.14
1624 self.dow.config['security'] = self.configfile.configfileargs['security']
|
1625 theshadow 1.4
1626 statsdisplayflag = self.configfile.configfileargs['gui_displaymiscstats']
1627 self.downTextLabel.Show(statsdisplayflag)
1628 self.upTextLabel.Show(statsdisplayflag)
1629 self.fileDestLabel.Show(statsdisplayflag)
1630 self.fileDestText.Show(statsdisplayflag)
1631 self.colSizer.Layout()
1632
1633 self.downText.SetLabel('') # blank these to flush them
1634 self.upText.SetLabel('')
1635 self.seedStatusText.SetLabel('')
1636 self.peerStatusText.SetLabel('')
1637
1638 ratesettingsmode = self.configfile.configfileargs['gui_ratesettingsmode']
1639 ratesettingsflag1 = true #\ settings
1640 ratesettingsflag2 = false #/ for 'basic'
1641 if ratesettingsmode == 'none':
1642 ratesettingsflag1 = false
1643 elif ratesettingsmode == 'full':
1644 ratesettingsflag2 = true
1645 self.connChoiceLabel.Show(ratesettingsflag1)
1646 theshadow 1.4 self.connChoice.Show(ratesettingsflag1)
1647 self.rateSpinnerLabel.Show(ratesettingsflag2)
1648 self.rateSpinner.Show(ratesettingsflag2)
1649 self.rateLowerText.Show(ratesettingsflag2)
1650 self.rateUpperText.Show(ratesettingsflag2)
1651 self.rateslider.Show(ratesettingsflag2)
1652 self.connSpinnerLabel.Show(ratesettingsflag2)
1653 self.connSpinner.Show(ratesettingsflag2)
1654 self.connLowerText.Show(ratesettingsflag2)
1655 self.connUpperText.Show(ratesettingsflag2)
1656 self.connslider.Show(ratesettingsflag2)
1657 self.unlimitedLabel.Show(ratesettingsflag2)
1658
1659 if statistics is None or statistics.downTotal is None:
1660 self.gauge.SetForegroundColour(self.configfile.checkingcolor)
1661 self.gauge.SetBackgroundColour(wx.wxSystemSettings_GetColour(wxSYS_COLOUR_MENU))
1662 elif self.fin:
1663 self.gauge.SetForegroundColour(self.configfile.seedingcolor)
1664 self.gauge.SetBackgroundColour(self.configfile.downloadcolor)
1665 else:
1666 self.gauge.SetForegroundColour(self.configfile.downloadcolor)
1667 theshadow 1.4 self.gauge.SetBackgroundColour(wx.wxSystemSettings_GetColour(wxSYS_COLOUR_MENU))
|
1668 theshadow 1.5
|
1669 theshadow 1.4 self.frame.Layout()
1670 self.frame.Refresh()
|
1671 theshadow 1.9
1672 self.gui_lastupdate = time()
|
1673 theshadow 1.11 self.gui_fractiondone = None
|
1674 theshadow 1.4
1675
|
1676 theshadow 1.1 def finished(self):
1677 self.fin = true
1678 self.invokeLater(self.onFinishEvent)
1679
1680 def failed(self):
1681 self.fin = true
1682 self.invokeLater(self.onFailEvent)
1683
1684 def error(self, errormsg):
1685 self.invokeLater(self.onErrorEvent, [errormsg])
1686
1687 def onFinishEvent(self):
|
1688 theshadow 1.6 self.activity = hours(time () - self.starttime) + ' / ' +'Download Succeeded!'
|
1689 theshadow 1.1 self.cancelButton.SetLabel('Finish')
|
1690 theshadow 1.4 self.gauge.SetBackgroundColour(self.configfile.downloadcolor)
|
1691 theshadow 1.2 self.gauge.SetValue(0)
|
1692 theshadow 1.4 self.gauge.SetForegroundColour(self.configfile.seedingcolor)
|
1693 theshadow 1.1 self.frame.SetTitle('%s - Upload - BitTorrent %s' % (self.filename, version))
|
1694 theshadow 1.2 if (sys.platform == 'win32'):
|
1695 theshadow 1.4 self.icon = wxIcon(os.path.join(basepath,'icon_done.ico'), wxBITMAP_TYPE_ICO)
|
1696 theshadow 1.2 self.frame.SetIcon(self.icon)
1697 if hasattr(self.frame, "tbicon"):
1698 self.frame.tbicon.SetIcon(self.icon, "BitTorrent - Finished")
|
1699 theshadow 1.1 self.downRateText.SetLabel('')
1700
1701 def onFailEvent(self):
|
1702 theshadow 1.6 if not self.shuttingdown:
1703 self.timeText.SetLabel(hours(time () - self.starttime) + ' / ' +'Failed!')
1704 self.activity = 'Failed!'
1705 self.cancelButton.SetLabel('Close')
1706 self.gauge.SetValue(0)
1707 self.downRateText.SetLabel('')
|
1708 theshadow 1.30 self.setStatusIcon('startup')
|
1709 theshadow 1.1
1710 def onErrorEvent(self, errormsg):
|
1711 theshadow 1.6 if not self.displayUsage(errormsg):
|
1712 theshadow 1.14 if errormsg[:2] == ' ': # indent at least 2 spaces means a warning message
1713 self.errorText.SetLabel(errormsg)
1714 self.lastError = time ()
1715 else:
1716 self.errorText.SetLabel(strftime('ERROR (%I:%M %p) -\n') + errormsg)
1717 self.lastError = time ()
|
1718 theshadow 1.6
|
1719 theshadow 1.1
1720 def chooseFile(self, default, size, saveas, dir):
1721 f = Event()
1722 bucket = [None]
|
1723 theshadow 1.3 self.invokeLater(self.onChooseFile, [default, bucket, f, size, dir, saveas])
|
1724 theshadow 1.1 f.wait()
1725 return bucket[0]
1726
|
1727 theshadow 1.3 def onChooseFile(self, default, bucket, f, size, dir, saveas):
|
1728 theshadow 1.9 if saveas == '':
1729 if self.configfile.configfileargs['gui_default_savedir'] != '':
1730 start_dir = self.configfile.configfileargs['gui_default_savedir']
1731 else:
1732 start_dir = self.configfile.configfileargs['last_saved']
1733 if not isdir(start_dir): # if it's not set properly
1734 start_dir = '/' # yes, this hack does work in Windows
|
1735 theshadow 1.3 if dir:
|
1736 theshadow 1.9 if isdir(join(start_dir,default)):
1737 start_dir = join(start_dir,default)
1738 dl = wxDirDialog(self.frame,
1739 'Choose a directory to save to, pick a partial download to resume',
1740 defaultPath = start_dir, style = wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON)
|
1741 theshadow 1.3 else:
|
1742 theshadow 1.9 dl = wxFileDialog(self.frame,
1743 'Choose file to save as, pick a partial download to resume',
|
1744 theshadow 1.38 defaultDir = start_dir, defaultFile = default, wildcard = '*',
|
1745 theshadow 1.9 style = wxSAVE)
1746
1747 if dl.ShowModal() != wxID_OK:
1748 f.set()
1749 self.done(None)
1750 return
1751
1752 d = dl.GetPath()
1753 bucket[0] = d
1754 d1,d2 = split(d)
1755 if d2 == default:
1756 d = d1
1757 self.configfile.WriteLastSaved(d)
1758
1759 else:
1760 bucket[0] = saveas
1761 default = basename(saveas)
|
1762 theshadow 1.3
|
1763 theshadow 1.9 self.fileNameText.SetLabel('%s' % (default))
1764 self.fileSizeText.SetLabel('(%.2f MiB)' % (float(size) / (1 << 20)))
1765 self.timeText.SetLabel(hours(time () - self.starttime) + ' / ' + self.activity)
1766 self.fileDestText.SetLabel(bucket[0])
1767 self.filename = default
1768 self.frame.SetTitle(default + '- BitTorrent ' + version)
1769 f.set()
1770
1771 minsize = self.fileNameText.GetBestSize()
1772 if (not self.configfile.configfileargs['gui_stretchwindow'] or
1773 minsize.GetWidth() < self.addwidth):
1774 minsize.SetWidth(self.addwidth)
1775 self.fnsizer.SetMinSize (minsize)
1776 minsize.SetHeight(self.fileSizeText.GetBestSize().GetHeight())
1777 self.fnsizer2.SetMinSize (minsize)
|
1778 theshadow 1.31 minsize.SetWidth(minsize.GetWidth()+(self.FONT*8))
|
1779 theshadow 1.9 minsize.SetHeight(self.fileNameText.GetBestSize().GetHeight()+self.fileSizeText.GetBestSize().GetHeight())
1780 minsize.SetHeight(2*self.errorText.GetBestSize().GetHeight())
1781 self.errorTextSizer.SetMinSize(minsize)
1782 self.topboxsizer.SetMinSize(minsize)
1783
1784 # Kludge to make details and about catch the event
1785 self.frame.SetSize ((self.frame.GetSizeTuple()[0]+1, self.frame.GetSizeTuple()[1]+1))
1786 self.frame.SetSize ((self.frame.GetSizeTuple()[0]-1, self.frame.GetSizeTuple()[1]-1))
1787 self.colSizer.Fit(self.frame)
|
1788 theshadow 1.1
1789 def newpath(self, path):
1790 self.fileDestText.SetLabel(path)
1791
|
1792 theshadow 1.7 def pause(self, event):
1793 self.invokeLater(self.onPause)
1794
1795 def onPause(self):
1796 if self.ispaused:
1797 self.ispaused = false
1798 self.pauseButton.SetLabel('Pause')
1799 self.dow.Unpause()
1800 else:
|
1801 theshadow 1.17 if self.dow.Pause():
1802 self.ispaused = true
1803 self.pauseButton.SetLabel('Resume')
1804 self.downRateText.SetLabel(' ')
1805 self.upRateText.SetLabel(' ')
1806 self.seedStatusText.SetLabel(' ')
1807 self.peerStatusText.SetLabel(' ')
1808 self.setStatusIcon('startup')
|
1809 theshadow 1.7
|
1810 theshadow 1.1 def done(self, event):
|
1811 theshadow 1.6 self.uiflag.set()
1812 self.shuttingdown = true
|
1813 theshadow 1.2 if hasattr(self.frame, "tbicon"):
1814 self.frame.tbicon.Destroy()
1815 del self.frame.tbicon
|
1816 theshadow 1.1 self.flag.set()
|
1817 theshadow 1.7 if self.ispaused:
1818 self.dow.Unpause()
|
1819 theshadow 1.2 if (self.detailBox is not None):
1820 try:
1821 self.detailBox.Close ()
1822 except wxPyDeadObjectError, e:
1823 self.detailBox = None
1824 if (self.aboutBox is not None):
1825 try:
1826 self.aboutBox.Close ()
1827 except wxPyDeadObjectError, e:
1828 self.aboutBox = None
1829 if (self.creditsBox is not None):
1830 try:
1831 self.creditsBox.Close ()
1832 except wxPyDeadObjectError, e:
1833 self.creditsBox = None
|
1834 theshadow 1.3 if (self.advBox is not None):
1835 try:
1836 self.advBox.Close ()
1837 except wxPyDeadObjectError, e:
1838 self.advBox = None
|
1839 theshadow 1.6
1840 if (self.statusIconHelpBox is not None):
1841 try:
1842 self.statusIconHelpBox.Close ()
1843 except wxPyDeadObjectError, e:
1844 self.statusIconHelpBox = None
1845 self.configfile.Close()
|
1846 theshadow 1.1 self.frame.Destroy()
1847
|
1848 theshadow 1.16 def exception(self):
1849 data = StringIO()
1850 print_exc(file = data)
1851 print data.getvalue() # report exception here too
1852 self.on_errorwindow(data.getvalue())
1853
|
1854 theshadow 1.15 def errorwindow(self, err):
1855 self.invokeLater(self.on_errorwindow,[err])
1856
1857 def on_errorwindow(self, err):
1858 if self._errorwindow is None:
1859 w = wxFrame(None, -1, 'BITTORRENT ERROR', size = (1,1))
1860 panel = wxPanel(w, -1)
1861 sizer = wxFlexGridSizer(cols = 1)
1862
|
1863 theshadow 1.20 t = ( 'BitTorrent ' + version + '\n' +
1864 'OS: ' + sys.platform + '\n' +
1865 'Python version: ' + sys.version + '\n' +
1866 'wxWindows version: ' + wxVERSION_STRING + '\n' )
1867
1868 try:
1869 t += 'Psyco version: ' + hex(psyco.__version__)[2:] + '\n'
1870 except:
1871 pass
|
1872 theshadow 1.37 try:
1873 t += 'Allocation method: ' + self.config['alloc_type']
1874 if self.dow.storagewrapper.bgalloc_active:
1875 t += '*'
1876 t += '\n'
1877 except:
1878 pass
|
1879 theshadow 1.20
1880 sizer.Add(wxTextCtrl(panel, -1, t + '\n' + err,
|
1881 theshadow 1.17 size = (500,300), style = wxTE_READONLY|wxTE_MULTILINE))
|
1882 theshadow 1.15
|
1883 theshadow 1.16 sizer.Add(wxStaticText(panel, -1,
1884 '\nHelp us iron out the bugs in the engine!' +
1885 '\nPlease report this error to info@degreez.net'))
|
1886 theshadow 1.15
1887 border = wxBoxSizer(wxHORIZONTAL)
1888 border.Add(sizer, 1, wxEXPAND | wxALL, 4)
1889
1890 panel.SetSizer(border)
1891 panel.SetAutoLayout(true)
1892
1893 w.Show()
1894 border.Fit(panel)
1895 w.Fit()
1896 self._errorwindow = w
1897
|
1898 theshadow 1.2
|
1899 theshadow 1.1 class btWxApp(wxApp):
1900 def __init__(self, x, params):
1901 self.params = params
|
1902 theshadow 1.13 self.configfile = configReader()
|
1903 theshadow 1.1 wxApp.__init__(self, x)
1904
1905 def OnInit(self):
1906 doneflag = Event()
|
1907 theshadow 1.13 d = DownloadInfoFrame(doneflag, self.configfile)
|
1908 theshadow 1.1 self.SetTopWindow(d.frame)
|
1909 theshadow 1.3 if len(self.params) == 0:
|
1910 theshadow 1.9 b = wxFileDialog (d.frame, 'Choose .torrent file to use',
1911 defaultDir = '', defaultFile = '', wildcard = '*.torrent',
1912 style = wxOPEN)
|
1913 theshadow 1.11
|
1914 theshadow 1.6 if b.ShowModal() == wxID_OK:
|
1915 theshadow 1.3 self.params.append (b.GetPath())
1916
|
1917 theshadow 1.13 thread = Thread(target = next, args = [self.params, d, doneflag, self.configfile])
|
1918 theshadow 1.1 thread.setDaemon(false)
1919 thread.start()
1920 return 1
1921
1922 def run(params):
1923 app = btWxApp(0, params)
1924 app.MainLoop()
1925
|
1926 theshadow 1.13 def next(params, d, doneflag, configfile):
|
1927 theshadow 1.11 if PROFILER:
1928 import profile, pstats
1929 p = profile.Profile()
|
1930 theshadow 1.13 p.runcall(_next, params, d, doneflag, configfile)
|
1931 theshadow 1.11 log = open('profile_data.'+strftime('%y%m%d%H%M%S')+'.txt','a')
1932 normalstdout = sys.stdout
1933 sys.stdout = log
1934 pstats.Stats(p).strip_dirs().sort_stats('cumulative').print_stats()
1935 sys.stdout = normalstdout
1936 else:
|
1937 theshadow 1.13 _next(params, d, doneflag, configfile)
|
1938 theshadow 1.11
|
1939 theshadow 1.13 def _next(params, d, doneflag, configfile):
|
1940 theshadow 1.15 dow = Download()
|
1941 theshadow 1.2 d.dow = dow
|
1942 theshadow 1.13 configfile.setDownloadDefaults(dow.getDefaults())
|
1943 theshadow 1.4 d.configfile = configfile
1944 d.configfileargs = d.configfile.configfileargs
|
1945 theshadow 1.15 try:
1946 dow.download(params, d.chooseFile, d.updateStatus, d.finished, d.error, doneflag, 100,
1947 d.newpath, d.configfileargs, d.errorwindow)
1948 except:
1949 data = StringIO()
|
1950 theshadow 1.16 print_exc(file = data)
|
1951 theshadow 1.15 print data.getvalue() # report exception here too
1952 d.errorwindow(data.getvalue())
|
1953 theshadow 1.1 if not d.fin:
1954 d.failed()
|
1955 theshadow 1.11
|
1956 theshadow 1.1
1957 if __name__ == '__main__':
1958 run(argv[1:])
|