murder 0.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/LICENSE +17 -0
- data/README +224 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/dist/BitTornado/BT1/Choker.py +128 -0
- data/dist/BitTornado/BT1/Connecter.py +288 -0
- data/dist/BitTornado/BT1/Downloader.py +594 -0
- data/dist/BitTornado/BT1/DownloaderFeedback.py +155 -0
- data/dist/BitTornado/BT1/Encrypter.py +333 -0
- data/dist/BitTornado/BT1/FileSelector.py +245 -0
- data/dist/BitTornado/BT1/Filter.py +12 -0
- data/dist/BitTornado/BT1/HTTPDownloader.py +251 -0
- data/dist/BitTornado/BT1/NatCheck.py +95 -0
- data/dist/BitTornado/BT1/PiecePicker.py +320 -0
- data/dist/BitTornado/BT1/Rerequester.py +426 -0
- data/dist/BitTornado/BT1/Statistics.py +177 -0
- data/dist/BitTornado/BT1/Storage.py +584 -0
- data/dist/BitTornado/BT1/StorageWrapper.py +1045 -0
- data/dist/BitTornado/BT1/StreamCheck.py +135 -0
- data/dist/BitTornado/BT1/T2T.py +193 -0
- data/dist/BitTornado/BT1/Uploader.py +145 -0
- data/dist/BitTornado/BT1/__init__.py +1 -0
- data/dist/BitTornado/BT1/btformats.py +100 -0
- data/dist/BitTornado/BT1/fakeopen.py +89 -0
- data/dist/BitTornado/BT1/makemetafile.py +263 -0
- data/dist/BitTornado/BT1/track.py +1067 -0
- data/dist/BitTornado/ConfigDir.py +401 -0
- data/dist/BitTornado/ConfigReader.py +1068 -0
- data/dist/BitTornado/ConnChoice.py +31 -0
- data/dist/BitTornado/CreateIcons.py +105 -0
- data/dist/BitTornado/CurrentRateMeasure.py +37 -0
- data/dist/BitTornado/HTTPHandler.py +167 -0
- data/dist/BitTornado/PSYCO.py +5 -0
- data/dist/BitTornado/RateLimiter.py +153 -0
- data/dist/BitTornado/RateMeasure.py +75 -0
- data/dist/BitTornado/RawServer.py +195 -0
- data/dist/BitTornado/ServerPortHandler.py +188 -0
- data/dist/BitTornado/SocketHandler.py +375 -0
- data/dist/BitTornado/__init__.py +63 -0
- data/dist/BitTornado/bencode.py +319 -0
- data/dist/BitTornado/bitfield.py +162 -0
- data/dist/BitTornado/clock.py +27 -0
- data/dist/BitTornado/download_bt1.py +882 -0
- data/dist/BitTornado/inifile.py +169 -0
- data/dist/BitTornado/iprangeparse.py +194 -0
- data/dist/BitTornado/launchmanycore.py +381 -0
- data/dist/BitTornado/natpunch.py +254 -0
- data/dist/BitTornado/parseargs.py +137 -0
- data/dist/BitTornado/parsedir.py +150 -0
- data/dist/BitTornado/piecebuffer.py +86 -0
- data/dist/BitTornado/selectpoll.py +109 -0
- data/dist/BitTornado/subnetparse.py +218 -0
- data/dist/BitTornado/torrentlistparse.py +38 -0
- data/dist/BitTornado/zurllib.py +100 -0
- data/dist/murder_client.py +291 -0
- data/dist/murder_make_torrent.py +46 -0
- data/dist/murder_tracker.py +28 -0
- data/doc/examples/Capfile +28 -0
- data/lib/capistrano/recipes/deploy/strategy/murder.rb +52 -0
- data/lib/murder.rb +43 -0
- data/lib/murder/admin.rb +47 -0
- data/lib/murder/murder.rb +121 -0
- data/murder.gemspec +101 -0
- metadata +129 -0
@@ -0,0 +1,401 @@
|
|
1
|
+
#written by John Hoffman
|
2
|
+
|
3
|
+
from inifile import ini_write, ini_read
|
4
|
+
from bencode import bencode, bdecode
|
5
|
+
from types import IntType, LongType, StringType, FloatType
|
6
|
+
from CreateIcons import GetIcons, CreateIcon
|
7
|
+
from parseargs import defaultargs
|
8
|
+
from __init__ import product_name, version_short
|
9
|
+
import sys,os
|
10
|
+
from time import time, strftime
|
11
|
+
|
12
|
+
try:
|
13
|
+
True
|
14
|
+
except:
|
15
|
+
True = 1
|
16
|
+
False = 0
|
17
|
+
|
18
|
+
try:
|
19
|
+
realpath = os.path.realpath
|
20
|
+
except:
|
21
|
+
realpath = lambda x:x
|
22
|
+
OLDICONPATH = os.path.abspath(os.path.dirname(realpath(sys.argv[0])))
|
23
|
+
|
24
|
+
DIRNAME = '.'+product_name
|
25
|
+
|
26
|
+
hexchars = '0123456789abcdef'
|
27
|
+
hexmap = []
|
28
|
+
revmap = {}
|
29
|
+
for i in xrange(256):
|
30
|
+
x = hexchars[(i&0xF0)/16]+hexchars[i&0x0F]
|
31
|
+
hexmap.append(x)
|
32
|
+
revmap[x] = chr(i)
|
33
|
+
|
34
|
+
def tohex(s):
|
35
|
+
r = []
|
36
|
+
for c in s:
|
37
|
+
r.append(hexmap[ord(c)])
|
38
|
+
return ''.join(r)
|
39
|
+
|
40
|
+
def unhex(s):
|
41
|
+
r = [ revmap[s[x:x+2]] for x in xrange(0, len(s), 2) ]
|
42
|
+
return ''.join(r)
|
43
|
+
|
44
|
+
def copyfile(oldpath, newpath): # simple file copy, all in RAM
|
45
|
+
try:
|
46
|
+
f = open(oldpath,'rb')
|
47
|
+
r = f.read()
|
48
|
+
success = True
|
49
|
+
except:
|
50
|
+
success = False
|
51
|
+
try:
|
52
|
+
f.close()
|
53
|
+
except:
|
54
|
+
pass
|
55
|
+
if not success:
|
56
|
+
return False
|
57
|
+
try:
|
58
|
+
f = open(newpath,'wb')
|
59
|
+
f.write(r)
|
60
|
+
except:
|
61
|
+
success = False
|
62
|
+
try:
|
63
|
+
f.close()
|
64
|
+
except:
|
65
|
+
pass
|
66
|
+
return success
|
67
|
+
|
68
|
+
|
69
|
+
class ConfigDir:
|
70
|
+
|
71
|
+
###### INITIALIZATION TASKS ######
|
72
|
+
|
73
|
+
def __init__(self, config_type = None):
|
74
|
+
self.config_type = config_type
|
75
|
+
if config_type:
|
76
|
+
config_ext = '.'+config_type
|
77
|
+
else:
|
78
|
+
config_ext = ''
|
79
|
+
|
80
|
+
def check_sysvars(x):
|
81
|
+
y = os.path.expandvars(x)
|
82
|
+
if y != x and os.path.isdir(y):
|
83
|
+
return y
|
84
|
+
return None
|
85
|
+
|
86
|
+
for d in ['${APPDATA}', '${HOME}', '${HOMEPATH}', '${USERPROFILE}']:
|
87
|
+
dir_root = check_sysvars(d)
|
88
|
+
if dir_root:
|
89
|
+
break
|
90
|
+
else:
|
91
|
+
dir_root = os.path.expanduser('~')
|
92
|
+
if not os.path.isdir(dir_root):
|
93
|
+
dir_root = os.path.abspath(os.path.dirname(sys.argv[0]))
|
94
|
+
|
95
|
+
dir_root = os.path.join(dir_root,DIRNAME)
|
96
|
+
self.dir_root = dir_root
|
97
|
+
|
98
|
+
if not os.path.isdir(self.dir_root):
|
99
|
+
os.mkdir(self.dir_root,0700) # exception if failed
|
100
|
+
|
101
|
+
self.dir_icons = os.path.join(dir_root,'icons')
|
102
|
+
if not os.path.isdir(self.dir_icons):
|
103
|
+
os.mkdir(self.dir_icons)
|
104
|
+
for icon in GetIcons():
|
105
|
+
i = os.path.join(self.dir_icons,icon)
|
106
|
+
if not os.path.exists(i):
|
107
|
+
if not copyfile(os.path.join(OLDICONPATH,icon),i):
|
108
|
+
CreateIcon(icon,self.dir_icons)
|
109
|
+
|
110
|
+
self.dir_torrentcache = os.path.join(dir_root,'torrentcache')
|
111
|
+
if not os.path.isdir(self.dir_torrentcache):
|
112
|
+
os.mkdir(self.dir_torrentcache)
|
113
|
+
|
114
|
+
self.dir_datacache = os.path.join(dir_root,'datacache')
|
115
|
+
if not os.path.isdir(self.dir_datacache):
|
116
|
+
os.mkdir(self.dir_datacache)
|
117
|
+
|
118
|
+
self.dir_piececache = os.path.join(dir_root,'piececache')
|
119
|
+
if not os.path.isdir(self.dir_piececache):
|
120
|
+
os.mkdir(self.dir_piececache)
|
121
|
+
|
122
|
+
self.configfile = os.path.join(dir_root,'config'+config_ext+'.ini')
|
123
|
+
self.statefile = os.path.join(dir_root,'state'+config_ext)
|
124
|
+
|
125
|
+
self.TorrentDataBuffer = {}
|
126
|
+
|
127
|
+
|
128
|
+
###### CONFIG HANDLING ######
|
129
|
+
|
130
|
+
def setDefaults(self, defaults, ignore=[]):
|
131
|
+
self.config = defaultargs(defaults)
|
132
|
+
for k in ignore:
|
133
|
+
if self.config.has_key(k):
|
134
|
+
del self.config[k]
|
135
|
+
|
136
|
+
def checkConfig(self):
|
137
|
+
return os.path.exists(self.configfile)
|
138
|
+
|
139
|
+
def loadConfig(self):
|
140
|
+
try:
|
141
|
+
r = ini_read(self.configfile)['']
|
142
|
+
except:
|
143
|
+
return self.config
|
144
|
+
l = self.config.keys()
|
145
|
+
for k,v in r.items():
|
146
|
+
if self.config.has_key(k):
|
147
|
+
t = type(self.config[k])
|
148
|
+
try:
|
149
|
+
if t == StringType:
|
150
|
+
self.config[k] = v
|
151
|
+
elif t == IntType or t == LongType:
|
152
|
+
self.config[k] = long(v)
|
153
|
+
elif t == FloatType:
|
154
|
+
self.config[k] = float(v)
|
155
|
+
l.remove(k)
|
156
|
+
except:
|
157
|
+
pass
|
158
|
+
if l: # new default values since last save
|
159
|
+
self.saveConfig()
|
160
|
+
return self.config
|
161
|
+
|
162
|
+
def saveConfig(self, new_config = None):
|
163
|
+
if new_config:
|
164
|
+
for k,v in new_config.items():
|
165
|
+
if self.config.has_key(k):
|
166
|
+
self.config[k] = v
|
167
|
+
try:
|
168
|
+
ini_write( self.configfile, self.config,
|
169
|
+
'Generated by '+product_name+'/'+version_short+'\n'
|
170
|
+
+ strftime('%x %X') )
|
171
|
+
return True
|
172
|
+
except:
|
173
|
+
return False
|
174
|
+
|
175
|
+
def getConfig(self):
|
176
|
+
return self.config
|
177
|
+
|
178
|
+
|
179
|
+
###### STATE HANDLING ######
|
180
|
+
|
181
|
+
def getState(self):
|
182
|
+
try:
|
183
|
+
f = open(self.statefile,'rb')
|
184
|
+
r = f.read()
|
185
|
+
except:
|
186
|
+
r = None
|
187
|
+
try:
|
188
|
+
f.close()
|
189
|
+
except:
|
190
|
+
pass
|
191
|
+
try:
|
192
|
+
r = bdecode(r)
|
193
|
+
except:
|
194
|
+
r = None
|
195
|
+
return r
|
196
|
+
|
197
|
+
def saveState(self, state):
|
198
|
+
try:
|
199
|
+
f = open(self.statefile,'wb')
|
200
|
+
f.write(bencode(state))
|
201
|
+
success = True
|
202
|
+
except:
|
203
|
+
success = False
|
204
|
+
try:
|
205
|
+
f.close()
|
206
|
+
except:
|
207
|
+
pass
|
208
|
+
return success
|
209
|
+
|
210
|
+
|
211
|
+
###### TORRENT HANDLING ######
|
212
|
+
|
213
|
+
def getTorrents(self):
|
214
|
+
d = {}
|
215
|
+
for f in os.listdir(self.dir_torrentcache):
|
216
|
+
f = os.path.basename(f)
|
217
|
+
try:
|
218
|
+
f, garbage = f.split('.')
|
219
|
+
except:
|
220
|
+
pass
|
221
|
+
d[unhex(f)] = 1
|
222
|
+
return d.keys()
|
223
|
+
|
224
|
+
def getTorrentVariations(self, t):
|
225
|
+
t = tohex(t)
|
226
|
+
d = []
|
227
|
+
for f in os.listdir(self.dir_torrentcache):
|
228
|
+
f = os.path.basename(f)
|
229
|
+
if f[:len(t)] == t:
|
230
|
+
try:
|
231
|
+
garbage, ver = f.split('.')
|
232
|
+
except:
|
233
|
+
ver = '0'
|
234
|
+
d.append(int(ver))
|
235
|
+
d.sort()
|
236
|
+
return d
|
237
|
+
|
238
|
+
def getTorrent(self, t, v = -1):
|
239
|
+
t = tohex(t)
|
240
|
+
if v == -1:
|
241
|
+
v = max(self.getTorrentVariations(t)) # potential exception
|
242
|
+
if v:
|
243
|
+
t += '.'+str(v)
|
244
|
+
try:
|
245
|
+
f = open(os.path.join(self.dir_torrentcache,t),'rb')
|
246
|
+
r = bdecode(f.read())
|
247
|
+
except:
|
248
|
+
r = None
|
249
|
+
try:
|
250
|
+
f.close()
|
251
|
+
except:
|
252
|
+
pass
|
253
|
+
return r
|
254
|
+
|
255
|
+
def writeTorrent(self, data, t, v = -1):
|
256
|
+
t = tohex(t)
|
257
|
+
if v == -1:
|
258
|
+
try:
|
259
|
+
v = max(self.getTorrentVariations(t))+1
|
260
|
+
except:
|
261
|
+
v = 0
|
262
|
+
if v:
|
263
|
+
t += '.'+str(v)
|
264
|
+
try:
|
265
|
+
f = open(os.path.join(self.dir_torrentcache,t),'wb')
|
266
|
+
f.write(bencode(data))
|
267
|
+
except:
|
268
|
+
v = None
|
269
|
+
try:
|
270
|
+
f.close()
|
271
|
+
except:
|
272
|
+
pass
|
273
|
+
return v
|
274
|
+
|
275
|
+
|
276
|
+
###### TORRENT DATA HANDLING ######
|
277
|
+
|
278
|
+
def getTorrentData(self, t):
|
279
|
+
if self.TorrentDataBuffer.has_key(t):
|
280
|
+
return self.TorrentDataBuffer[t]
|
281
|
+
t = os.path.join(self.dir_datacache,tohex(t))
|
282
|
+
if not os.path.exists(t):
|
283
|
+
return None
|
284
|
+
try:
|
285
|
+
f = open(t,'rb')
|
286
|
+
r = bdecode(f.read())
|
287
|
+
except:
|
288
|
+
r = None
|
289
|
+
try:
|
290
|
+
f.close()
|
291
|
+
except:
|
292
|
+
pass
|
293
|
+
self.TorrentDataBuffer[t] = r
|
294
|
+
return r
|
295
|
+
|
296
|
+
def writeTorrentData(self, t, data):
|
297
|
+
self.TorrentDataBuffer[t] = data
|
298
|
+
try:
|
299
|
+
f = open(os.path.join(self.dir_datacache,tohex(t)),'wb')
|
300
|
+
f.write(bencode(data))
|
301
|
+
success = True
|
302
|
+
except:
|
303
|
+
success = False
|
304
|
+
try:
|
305
|
+
f.close()
|
306
|
+
except:
|
307
|
+
pass
|
308
|
+
if not success:
|
309
|
+
self.deleteTorrentData(t)
|
310
|
+
return success
|
311
|
+
|
312
|
+
def deleteTorrentData(self, t):
|
313
|
+
try:
|
314
|
+
os.remove(os.path.join(self.dir_datacache,tohex(t)))
|
315
|
+
except:
|
316
|
+
pass
|
317
|
+
|
318
|
+
def getPieceDir(self, t):
|
319
|
+
return os.path.join(self.dir_piececache,tohex(t))
|
320
|
+
|
321
|
+
|
322
|
+
###### EXPIRATION HANDLING ######
|
323
|
+
|
324
|
+
def deleteOldCacheData(self, days, still_active = [], delete_torrents = False):
|
325
|
+
if not days:
|
326
|
+
return
|
327
|
+
exptime = time() - (days*24*3600)
|
328
|
+
names = {}
|
329
|
+
times = {}
|
330
|
+
|
331
|
+
for f in os.listdir(self.dir_torrentcache):
|
332
|
+
p = os.path.join(self.dir_torrentcache,f)
|
333
|
+
f = os.path.basename(f)
|
334
|
+
try:
|
335
|
+
f, garbage = f.split('.')
|
336
|
+
except:
|
337
|
+
pass
|
338
|
+
try:
|
339
|
+
f = unhex(f)
|
340
|
+
assert len(f) == 20
|
341
|
+
except:
|
342
|
+
continue
|
343
|
+
if delete_torrents:
|
344
|
+
names.setdefault(f,[]).append(p)
|
345
|
+
try:
|
346
|
+
t = os.path.getmtime(p)
|
347
|
+
except:
|
348
|
+
t = time()
|
349
|
+
times.setdefault(f,[]).append(t)
|
350
|
+
|
351
|
+
for f in os.listdir(self.dir_datacache):
|
352
|
+
p = os.path.join(self.dir_datacache,f)
|
353
|
+
try:
|
354
|
+
f = unhex(os.path.basename(f))
|
355
|
+
assert len(f) == 20
|
356
|
+
except:
|
357
|
+
continue
|
358
|
+
names.setdefault(f,[]).append(p)
|
359
|
+
try:
|
360
|
+
t = os.path.getmtime(p)
|
361
|
+
except:
|
362
|
+
t = time()
|
363
|
+
times.setdefault(f,[]).append(t)
|
364
|
+
|
365
|
+
for f in os.listdir(self.dir_piececache):
|
366
|
+
p = os.path.join(self.dir_piececache,f)
|
367
|
+
try:
|
368
|
+
f = unhex(os.path.basename(f))
|
369
|
+
assert len(f) == 20
|
370
|
+
except:
|
371
|
+
continue
|
372
|
+
for f2 in os.listdir(p):
|
373
|
+
p2 = os.path.join(p,f2)
|
374
|
+
names.setdefault(f,[]).append(p2)
|
375
|
+
try:
|
376
|
+
t = os.path.getmtime(p2)
|
377
|
+
except:
|
378
|
+
t = time()
|
379
|
+
times.setdefault(f,[]).append(t)
|
380
|
+
names.setdefault(f,[]).append(p)
|
381
|
+
|
382
|
+
for k,v in times.items():
|
383
|
+
if max(v) < exptime and not k in still_active:
|
384
|
+
for f in names[k]:
|
385
|
+
try:
|
386
|
+
os.remove(f)
|
387
|
+
except:
|
388
|
+
try:
|
389
|
+
os.removedirs(f)
|
390
|
+
except:
|
391
|
+
pass
|
392
|
+
|
393
|
+
|
394
|
+
def deleteOldTorrents(self, days, still_active = []):
|
395
|
+
self.deleteOldCacheData(days, still_active, True)
|
396
|
+
|
397
|
+
|
398
|
+
###### OTHER ######
|
399
|
+
|
400
|
+
def getIconDir(self):
|
401
|
+
return self.dir_icons
|
@@ -0,0 +1,1068 @@
|
|
1
|
+
#written by John Hoffman
|
2
|
+
|
3
|
+
from ConnChoice import *
|
4
|
+
from wxPython.wx import *
|
5
|
+
from types import IntType, FloatType, StringType
|
6
|
+
from download_bt1 import defaults
|
7
|
+
from ConfigDir import ConfigDir
|
8
|
+
import sys,os
|
9
|
+
import socket
|
10
|
+
from parseargs import defaultargs
|
11
|
+
|
12
|
+
try:
|
13
|
+
True
|
14
|
+
except:
|
15
|
+
True = 1
|
16
|
+
False = 0
|
17
|
+
|
18
|
+
try:
|
19
|
+
wxFULL_REPAINT_ON_RESIZE
|
20
|
+
except:
|
21
|
+
wxFULL_REPAINT_ON_RESIZE = 0 # fix for wx pre-2.5
|
22
|
+
|
23
|
+
if (sys.platform == 'win32'):
|
24
|
+
_FONT = 9
|
25
|
+
else:
|
26
|
+
_FONT = 10
|
27
|
+
|
28
|
+
def HexToColor(s):
|
29
|
+
r,g,b = s.split(' ')
|
30
|
+
return wxColour(red=int(r,16), green=int(g,16), blue=int(b,16))
|
31
|
+
|
32
|
+
def hex2(c):
|
33
|
+
h = hex(c)[2:]
|
34
|
+
if len(h) == 1:
|
35
|
+
h = '0'+h
|
36
|
+
return h
|
37
|
+
def ColorToHex(c):
|
38
|
+
return hex2(c.Red()) + ' ' + hex2(c.Green()) + ' ' + hex2(c.Blue())
|
39
|
+
|
40
|
+
ratesettingslist = []
|
41
|
+
for x in connChoices:
|
42
|
+
if not x.has_key('super-seed'):
|
43
|
+
ratesettingslist.append(x['name'])
|
44
|
+
|
45
|
+
|
46
|
+
configFileDefaults = [
|
47
|
+
#args only available for the gui client
|
48
|
+
('win32_taskbar_icon', 1,
|
49
|
+
"whether to iconize do system try or not on win32"),
|
50
|
+
('gui_stretchwindow', 0,
|
51
|
+
"whether to stretch the download status window to fit the torrent name"),
|
52
|
+
('gui_displaystats', 1,
|
53
|
+
"whether to display statistics on peers and seeds"),
|
54
|
+
('gui_displaymiscstats', 1,
|
55
|
+
"whether to display miscellaneous other statistics"),
|
56
|
+
('gui_ratesettingsdefault', ratesettingslist[0],
|
57
|
+
"the default setting for maximum upload rate and users"),
|
58
|
+
('gui_ratesettingsmode', 'full',
|
59
|
+
"what rate setting controls to display; options are 'none', 'basic', and 'full'"),
|
60
|
+
('gui_forcegreenonfirewall', 0,
|
61
|
+
"forces the status icon to be green even if the client seems to be firewalled"),
|
62
|
+
('gui_default_savedir', '',
|
63
|
+
"default save directory"),
|
64
|
+
('last_saved', '', # hidden; not set in config
|
65
|
+
"where the last torrent was saved"),
|
66
|
+
('gui_font', _FONT,
|
67
|
+
"the font size to use"),
|
68
|
+
('gui_saveas_ask', -1,
|
69
|
+
"whether to ask where to download to (0 = never, 1 = always, -1 = automatic resume"),
|
70
|
+
]
|
71
|
+
|
72
|
+
def setwxconfigfiledefaults():
|
73
|
+
CHECKINGCOLOR = ColorToHex(wxSystemSettings_GetColour(wxSYS_COLOUR_3DSHADOW))
|
74
|
+
DOWNLOADCOLOR = ColorToHex(wxSystemSettings_GetColour(wxSYS_COLOUR_ACTIVECAPTION))
|
75
|
+
|
76
|
+
configFileDefaults.extend([
|
77
|
+
('gui_checkingcolor', CHECKINGCOLOR,
|
78
|
+
"progress bar checking color"),
|
79
|
+
('gui_downloadcolor', DOWNLOADCOLOR,
|
80
|
+
"progress bar downloading color"),
|
81
|
+
('gui_seedingcolor', '00 FF 00',
|
82
|
+
"progress bar seeding color"),
|
83
|
+
])
|
84
|
+
|
85
|
+
defaultsToIgnore = ['responsefile', 'url', 'priority']
|
86
|
+
|
87
|
+
|
88
|
+
class configReader:
|
89
|
+
|
90
|
+
def __init__(self):
|
91
|
+
self.configfile = wxConfig("BitTorrent",style=wxCONFIG_USE_LOCAL_FILE)
|
92
|
+
self.configMenuBox = None
|
93
|
+
self.advancedMenuBox = None
|
94
|
+
self._configReset = True # run reset for the first time
|
95
|
+
|
96
|
+
setwxconfigfiledefaults()
|
97
|
+
|
98
|
+
defaults.extend(configFileDefaults)
|
99
|
+
self.defaults = defaultargs(defaults)
|
100
|
+
|
101
|
+
self.configDir = ConfigDir('gui')
|
102
|
+
self.configDir.setDefaults(defaults,defaultsToIgnore)
|
103
|
+
if self.configDir.checkConfig():
|
104
|
+
self.config = self.configDir.loadConfig()
|
105
|
+
else:
|
106
|
+
self.config = self.configDir.getConfig()
|
107
|
+
self.importOldGUIConfig()
|
108
|
+
self.configDir.saveConfig()
|
109
|
+
|
110
|
+
updated = False # make all config default changes here
|
111
|
+
|
112
|
+
if self.config['gui_ratesettingsdefault'] not in ratesettingslist:
|
113
|
+
self.config['gui_ratesettingsdefault'] = (
|
114
|
+
self.defaults['gui_ratesettingsdefault'] )
|
115
|
+
updated = True
|
116
|
+
if self.config['ipv6_enabled'] and (
|
117
|
+
sys.version_info < (2,3) or not socket.has_ipv6 ):
|
118
|
+
self.config['ipv6_enabled'] = 0
|
119
|
+
updated = True
|
120
|
+
for c in ['gui_checkingcolor','gui_downloadcolor','gui_seedingcolor']:
|
121
|
+
try:
|
122
|
+
HexToColor(self.config[c])
|
123
|
+
except:
|
124
|
+
self.config[c] = self.defaults[c]
|
125
|
+
updated = True
|
126
|
+
|
127
|
+
if updated:
|
128
|
+
self.configDir.saveConfig()
|
129
|
+
|
130
|
+
self.configDir.deleteOldCacheData(self.config['expire_cache_data'])
|
131
|
+
|
132
|
+
|
133
|
+
def importOldGUIConfig(self):
|
134
|
+
oldconfig = wxConfig("BitTorrent",style=wxCONFIG_USE_LOCAL_FILE)
|
135
|
+
cont, s, i = oldconfig.GetFirstEntry()
|
136
|
+
if not cont:
|
137
|
+
oldconfig.DeleteAll()
|
138
|
+
return False
|
139
|
+
while cont: # import old config data
|
140
|
+
if self.config.has_key(s):
|
141
|
+
t = oldconfig.GetEntryType(s)
|
142
|
+
try:
|
143
|
+
if t == 1:
|
144
|
+
assert type(self.config[s]) == type('')
|
145
|
+
self.config[s] = oldconfig.Read(s)
|
146
|
+
elif t == 2 or t == 3:
|
147
|
+
assert type(self.config[s]) == type(1)
|
148
|
+
self.config[s] = int(oldconfig.ReadInt(s))
|
149
|
+
elif t == 4:
|
150
|
+
assert type(self.config[s]) == type(1.0)
|
151
|
+
self.config[s] = oldconfig.ReadFloat(s)
|
152
|
+
except:
|
153
|
+
pass
|
154
|
+
cont, s, i = oldconfig.GetNextEntry(i)
|
155
|
+
|
156
|
+
# oldconfig.DeleteAll()
|
157
|
+
return True
|
158
|
+
|
159
|
+
|
160
|
+
def resetConfigDefaults(self):
|
161
|
+
for p,v in self.defaults.items():
|
162
|
+
if not p in defaultsToIgnore:
|
163
|
+
self.config[p] = v
|
164
|
+
self.configDir.saveConfig()
|
165
|
+
|
166
|
+
def writeConfigFile(self):
|
167
|
+
self.configDir.saveConfig()
|
168
|
+
|
169
|
+
def WriteLastSaved(self, l):
|
170
|
+
self.config['last_saved'] = l
|
171
|
+
self.configDir.saveConfig()
|
172
|
+
|
173
|
+
|
174
|
+
def getcheckingcolor(self):
|
175
|
+
return HexToColor(self.config['gui_checkingcolor'])
|
176
|
+
def getdownloadcolor(self):
|
177
|
+
return HexToColor(self.config['gui_downloadcolor'])
|
178
|
+
def getseedingcolor(self):
|
179
|
+
return HexToColor(self.config['gui_seedingcolor'])
|
180
|
+
|
181
|
+
def configReset(self):
|
182
|
+
r = self._configReset
|
183
|
+
self._configReset = False
|
184
|
+
return r
|
185
|
+
|
186
|
+
def getConfigDir(self):
|
187
|
+
return self.configDir
|
188
|
+
|
189
|
+
def getIconDir(self):
|
190
|
+
return self.configDir.getIconDir()
|
191
|
+
|
192
|
+
def getTorrentData(self,t):
|
193
|
+
return self.configDir.getTorrentData(t)
|
194
|
+
|
195
|
+
def setColorIcon(self, xxicon, xxiconptr, xxcolor):
|
196
|
+
idata = wxMemoryDC()
|
197
|
+
idata.SelectObject(xxicon)
|
198
|
+
idata.SetBrush(wxBrush(xxcolor,wxSOLID))
|
199
|
+
idata.DrawRectangle(0,0,16,16)
|
200
|
+
idata.SelectObject(wxNullBitmap)
|
201
|
+
xxiconptr.Refresh()
|
202
|
+
|
203
|
+
|
204
|
+
def getColorFromUser(self, parent, colInit):
|
205
|
+
data = wxColourData()
|
206
|
+
if colInit.Ok():
|
207
|
+
data.SetColour(colInit)
|
208
|
+
data.SetCustomColour(0, self.checkingcolor)
|
209
|
+
data.SetCustomColour(1, self.downloadcolor)
|
210
|
+
data.SetCustomColour(2, self.seedingcolor)
|
211
|
+
dlg = wxColourDialog(parent,data)
|
212
|
+
if not dlg.ShowModal():
|
213
|
+
return colInit
|
214
|
+
return dlg.GetColourData().GetColour()
|
215
|
+
|
216
|
+
|
217
|
+
def configMenu(self, parent):
|
218
|
+
self.parent = parent
|
219
|
+
try:
|
220
|
+
self.FONT = self.config['gui_font']
|
221
|
+
self.default_font = wxFont(self.FONT, wxDEFAULT, wxNORMAL, wxNORMAL, False)
|
222
|
+
self.checkingcolor = HexToColor(self.config['gui_checkingcolor'])
|
223
|
+
self.downloadcolor = HexToColor(self.config['gui_downloadcolor'])
|
224
|
+
self.seedingcolor = HexToColor(self.config['gui_seedingcolor'])
|
225
|
+
|
226
|
+
if (self.configMenuBox is not None):
|
227
|
+
try:
|
228
|
+
self.configMenuBox.Close()
|
229
|
+
except wxPyDeadObjectError, e:
|
230
|
+
self.configMenuBox = None
|
231
|
+
|
232
|
+
self.configMenuBox = wxFrame(None, -1, 'BitTorrent Preferences', size = (1,1),
|
233
|
+
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
|
234
|
+
if (sys.platform == 'win32'):
|
235
|
+
self.icon = self.parent.icon
|
236
|
+
self.configMenuBox.SetIcon(self.icon)
|
237
|
+
|
238
|
+
panel = wxPanel(self.configMenuBox, -1)
|
239
|
+
self.panel = panel
|
240
|
+
|
241
|
+
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
|
242
|
+
x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
|
243
|
+
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
|
244
|
+
if color is not None:
|
245
|
+
x.SetForegroundColour(color)
|
246
|
+
return x
|
247
|
+
|
248
|
+
colsizer = wxFlexGridSizer(cols = 1, vgap = 8)
|
249
|
+
|
250
|
+
self.gui_stretchwindow_checkbox = wxCheckBox(panel, -1, "Stretch window to fit torrent name *")
|
251
|
+
self.gui_stretchwindow_checkbox.SetFont(self.default_font)
|
252
|
+
self.gui_stretchwindow_checkbox.SetValue(self.config['gui_stretchwindow'])
|
253
|
+
|
254
|
+
self.gui_displaystats_checkbox = wxCheckBox(panel, -1, "Display peer and seed statistics")
|
255
|
+
self.gui_displaystats_checkbox.SetFont(self.default_font)
|
256
|
+
self.gui_displaystats_checkbox.SetValue(self.config['gui_displaystats'])
|
257
|
+
|
258
|
+
self.gui_displaymiscstats_checkbox = wxCheckBox(panel, -1, "Display miscellaneous other statistics")
|
259
|
+
self.gui_displaymiscstats_checkbox.SetFont(self.default_font)
|
260
|
+
self.gui_displaymiscstats_checkbox.SetValue(self.config['gui_displaymiscstats'])
|
261
|
+
|
262
|
+
self.security_checkbox = wxCheckBox(panel, -1, "Don't allow multiple connections from the same IP")
|
263
|
+
self.security_checkbox.SetFont(self.default_font)
|
264
|
+
self.security_checkbox.SetValue(self.config['security'])
|
265
|
+
|
266
|
+
self.autokick_checkbox = wxCheckBox(panel, -1, "Kick/ban clients that send you bad data *")
|
267
|
+
self.autokick_checkbox.SetFont(self.default_font)
|
268
|
+
self.autokick_checkbox.SetValue(self.config['auto_kick'])
|
269
|
+
|
270
|
+
self.buffering_checkbox = wxCheckBox(panel, -1, "Enable read/write buffering *")
|
271
|
+
self.buffering_checkbox.SetFont(self.default_font)
|
272
|
+
self.buffering_checkbox.SetValue(self.config['buffer_reads'])
|
273
|
+
|
274
|
+
self.breakup_checkbox = wxCheckBox(panel, -1, "Break-up seed bitfield to foil ISP manipulation")
|
275
|
+
self.breakup_checkbox.SetFont(self.default_font)
|
276
|
+
self.breakup_checkbox.SetValue(self.config['breakup_seed_bitfield'])
|
277
|
+
|
278
|
+
self.autoflush_checkbox = wxCheckBox(panel, -1, "Flush data to disk every 5 minutes")
|
279
|
+
self.autoflush_checkbox.SetFont(self.default_font)
|
280
|
+
self.autoflush_checkbox.SetValue(self.config['auto_flush'])
|
281
|
+
|
282
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
283
|
+
self.ipv6enabled_checkbox = wxCheckBox(panel, -1, "Initiate and receive connections via IPv6 *")
|
284
|
+
self.ipv6enabled_checkbox.SetFont(self.default_font)
|
285
|
+
self.ipv6enabled_checkbox.SetValue(self.config['ipv6_enabled'])
|
286
|
+
|
287
|
+
self.gui_forcegreenonfirewall_checkbox = wxCheckBox(panel, -1,
|
288
|
+
"Force icon to display green when firewalled")
|
289
|
+
self.gui_forcegreenonfirewall_checkbox.SetFont(self.default_font)
|
290
|
+
self.gui_forcegreenonfirewall_checkbox.SetValue(self.config['gui_forcegreenonfirewall'])
|
291
|
+
|
292
|
+
|
293
|
+
self.minport_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*8, -1))
|
294
|
+
self.minport_data.SetFont(self.default_font)
|
295
|
+
self.minport_data.SetRange(1,65535)
|
296
|
+
self.minport_data.SetValue(self.config['minport'])
|
297
|
+
|
298
|
+
self.maxport_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*8, -1))
|
299
|
+
self.maxport_data.SetFont(self.default_font)
|
300
|
+
self.maxport_data.SetRange(1,65535)
|
301
|
+
self.maxport_data.SetValue(self.config['maxport'])
|
302
|
+
|
303
|
+
self.randomport_checkbox = wxCheckBox(panel, -1, "randomize")
|
304
|
+
self.randomport_checkbox.SetFont(self.default_font)
|
305
|
+
self.randomport_checkbox.SetValue(self.config['random_port'])
|
306
|
+
|
307
|
+
self.gui_font_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*5, -1))
|
308
|
+
self.gui_font_data.SetFont(self.default_font)
|
309
|
+
self.gui_font_data.SetRange(8,16)
|
310
|
+
self.gui_font_data.SetValue(self.config['gui_font'])
|
311
|
+
|
312
|
+
self.gui_ratesettingsdefault_data=wxChoice(panel, -1, choices = ratesettingslist)
|
313
|
+
self.gui_ratesettingsdefault_data.SetFont(self.default_font)
|
314
|
+
self.gui_ratesettingsdefault_data.SetStringSelection(self.config['gui_ratesettingsdefault'])
|
315
|
+
|
316
|
+
self.maxdownload_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7, -1))
|
317
|
+
self.maxdownload_data.SetFont(self.default_font)
|
318
|
+
self.maxdownload_data.SetRange(0,5000)
|
319
|
+
self.maxdownload_data.SetValue(self.config['max_download_rate'])
|
320
|
+
|
321
|
+
self.gui_ratesettingsmode_data=wxRadioBox(panel, -1, 'Rate Settings Mode',
|
322
|
+
choices = [ 'none', 'basic', 'full' ] )
|
323
|
+
self.gui_ratesettingsmode_data.SetFont(self.default_font)
|
324
|
+
self.gui_ratesettingsmode_data.SetStringSelection(self.config['gui_ratesettingsmode'])
|
325
|
+
|
326
|
+
if (sys.platform == 'win32'):
|
327
|
+
self.win32_taskbar_icon_checkbox = wxCheckBox(panel, -1, "Minimize to system tray")
|
328
|
+
self.win32_taskbar_icon_checkbox.SetFont(self.default_font)
|
329
|
+
self.win32_taskbar_icon_checkbox.SetValue(self.config['win32_taskbar_icon'])
|
330
|
+
|
331
|
+
# self.upnp_checkbox = wxCheckBox(panel, -1, "Enable automatic UPnP port forwarding")
|
332
|
+
# self.upnp_checkbox.SetFont(self.default_font)
|
333
|
+
# self.upnp_checkbox.SetValue(self.config['upnp_nat_access'])
|
334
|
+
self.upnp_data=wxChoice(panel, -1,
|
335
|
+
choices = ['disabled', 'type 1 (fast)', 'type 2 (slow)'])
|
336
|
+
self.upnp_data.SetFont(self.default_font)
|
337
|
+
self.upnp_data.SetSelection(self.config['upnp_nat_access'])
|
338
|
+
|
339
|
+
self.gui_default_savedir_ctrl = wxTextCtrl(parent = panel, id = -1,
|
340
|
+
value = self.config['gui_default_savedir'],
|
341
|
+
size = (26*self.FONT, -1), style = wxTE_PROCESS_TAB)
|
342
|
+
self.gui_default_savedir_ctrl.SetFont(self.default_font)
|
343
|
+
|
344
|
+
self.gui_savemode_data=wxRadioBox(panel, -1, 'Ask where to save: *',
|
345
|
+
choices = [ 'always', 'never', 'auto-resume' ] )
|
346
|
+
self.gui_savemode_data.SetFont(self.default_font)
|
347
|
+
self.gui_savemode_data.SetSelection(1-self.config['gui_saveas_ask'])
|
348
|
+
|
349
|
+
self.checkingcolor_icon = wxEmptyBitmap(16,16)
|
350
|
+
self.checkingcolor_iconptr = wxStaticBitmap(panel, -1, self.checkingcolor_icon)
|
351
|
+
self.setColorIcon(self.checkingcolor_icon, self.checkingcolor_iconptr, self.checkingcolor)
|
352
|
+
|
353
|
+
self.downloadcolor_icon = wxEmptyBitmap(16,16)
|
354
|
+
self.downloadcolor_iconptr = wxStaticBitmap(panel, -1, self.downloadcolor_icon)
|
355
|
+
self.setColorIcon(self.downloadcolor_icon, self.downloadcolor_iconptr, self.downloadcolor)
|
356
|
+
|
357
|
+
self.seedingcolor_icon = wxEmptyBitmap(16,16)
|
358
|
+
self.seedingcolor_iconptr = wxStaticBitmap(panel, -1, self.seedingcolor_icon)
|
359
|
+
self.setColorIcon(self.seedingcolor_icon, self.downloadcolor_iconptr, self.seedingcolor)
|
360
|
+
|
361
|
+
rowsizer = wxFlexGridSizer(cols = 2, hgap = 20)
|
362
|
+
|
363
|
+
block12sizer = wxFlexGridSizer(cols = 1, vgap = 7)
|
364
|
+
|
365
|
+
block1sizer = wxFlexGridSizer(cols = 1, vgap = 2)
|
366
|
+
if (sys.platform == 'win32'):
|
367
|
+
block1sizer.Add(self.win32_taskbar_icon_checkbox)
|
368
|
+
# block1sizer.Add(self.upnp_checkbox)
|
369
|
+
block1sizer.Add(self.gui_stretchwindow_checkbox)
|
370
|
+
block1sizer.Add(self.gui_displaystats_checkbox)
|
371
|
+
block1sizer.Add(self.gui_displaymiscstats_checkbox)
|
372
|
+
block1sizer.Add(self.security_checkbox)
|
373
|
+
block1sizer.Add(self.autokick_checkbox)
|
374
|
+
block1sizer.Add(self.buffering_checkbox)
|
375
|
+
block1sizer.Add(self.breakup_checkbox)
|
376
|
+
block1sizer.Add(self.autoflush_checkbox)
|
377
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
378
|
+
block1sizer.Add(self.ipv6enabled_checkbox)
|
379
|
+
block1sizer.Add(self.gui_forcegreenonfirewall_checkbox)
|
380
|
+
|
381
|
+
block12sizer.Add(block1sizer)
|
382
|
+
|
383
|
+
colorsizer = wxStaticBoxSizer(wxStaticBox(panel, -1, "Gauge Colors:"), wxVERTICAL)
|
384
|
+
colorsizer1 = wxFlexGridSizer(cols = 7)
|
385
|
+
colorsizer1.Add(StaticText(' Checking: '), 1, wxALIGN_BOTTOM)
|
386
|
+
colorsizer1.Add(self.checkingcolor_iconptr, 1, wxALIGN_BOTTOM)
|
387
|
+
colorsizer1.Add(StaticText(' Downloading: '), 1, wxALIGN_BOTTOM)
|
388
|
+
colorsizer1.Add(self.downloadcolor_iconptr, 1, wxALIGN_BOTTOM)
|
389
|
+
colorsizer1.Add(StaticText(' Seeding: '), 1, wxALIGN_BOTTOM)
|
390
|
+
colorsizer1.Add(self.seedingcolor_iconptr, 1, wxALIGN_BOTTOM)
|
391
|
+
colorsizer1.Add(StaticText(' '))
|
392
|
+
minsize = self.checkingcolor_iconptr.GetBestSize()
|
393
|
+
minsize.SetHeight(minsize.GetHeight()+5)
|
394
|
+
colorsizer1.SetMinSize(minsize)
|
395
|
+
colorsizer.Add(colorsizer1)
|
396
|
+
|
397
|
+
block12sizer.Add(colorsizer, 1, wxALIGN_LEFT)
|
398
|
+
|
399
|
+
rowsizer.Add(block12sizer)
|
400
|
+
|
401
|
+
block3sizer = wxFlexGridSizer(cols = 1)
|
402
|
+
|
403
|
+
portsettingsSizer = wxStaticBoxSizer(wxStaticBox(panel, -1, "Port Range:*"), wxVERTICAL)
|
404
|
+
portsettingsSizer1 = wxGridSizer(cols = 2, vgap = 1)
|
405
|
+
portsettingsSizer1.Add(StaticText('From: '), 1, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT)
|
406
|
+
portsettingsSizer1.Add(self.minport_data, 1, wxALIGN_BOTTOM)
|
407
|
+
portsettingsSizer1.Add(StaticText('To: '), 1, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT)
|
408
|
+
portsettingsSizer1.Add(self.maxport_data, 1, wxALIGN_BOTTOM)
|
409
|
+
portsettingsSizer.Add(portsettingsSizer1)
|
410
|
+
portsettingsSizer.Add(self.randomport_checkbox, 1, wxALIGN_CENTER)
|
411
|
+
block3sizer.Add(portsettingsSizer, 1, wxALIGN_CENTER)
|
412
|
+
block3sizer.Add(StaticText(' '))
|
413
|
+
block3sizer.Add(self.gui_ratesettingsmode_data, 1, wxALIGN_CENTER)
|
414
|
+
block3sizer.Add(StaticText(' '))
|
415
|
+
ratesettingsSizer = wxFlexGridSizer(cols = 1, vgap = 2)
|
416
|
+
ratesettingsSizer.Add(StaticText('Default Rate Setting: *'), 1, wxALIGN_CENTER)
|
417
|
+
ratesettingsSizer.Add(self.gui_ratesettingsdefault_data, 1, wxALIGN_CENTER)
|
418
|
+
block3sizer.Add(ratesettingsSizer, 1, wxALIGN_CENTER)
|
419
|
+
if (sys.platform == 'win32'):
|
420
|
+
block3sizer.Add(StaticText(' '))
|
421
|
+
upnpSizer = wxFlexGridSizer(cols = 1, vgap = 2)
|
422
|
+
upnpSizer.Add(StaticText('UPnP Port Forwarding: *'), 1, wxALIGN_CENTER)
|
423
|
+
upnpSizer.Add(self.upnp_data, 1, wxALIGN_CENTER)
|
424
|
+
block3sizer.Add(upnpSizer, 1, wxALIGN_CENTER)
|
425
|
+
|
426
|
+
rowsizer.Add(block3sizer)
|
427
|
+
colsizer.Add(rowsizer)
|
428
|
+
|
429
|
+
block4sizer = wxFlexGridSizer(cols = 3, hgap = 15)
|
430
|
+
savepathsizer = wxFlexGridSizer(cols = 2, vgap = 1)
|
431
|
+
savepathsizer.Add(StaticText('Default Save Path: *'))
|
432
|
+
savepathsizer.Add(StaticText(' '))
|
433
|
+
savepathsizer.Add(self.gui_default_savedir_ctrl, 1, wxEXPAND)
|
434
|
+
savepathButton = wxButton(panel, -1, '...', size = (18,18))
|
435
|
+
# savepathButton.SetFont(self.default_font)
|
436
|
+
savepathsizer.Add(savepathButton, 0, wxALIGN_CENTER)
|
437
|
+
savepathsizer.Add(self.gui_savemode_data, 0, wxALIGN_CENTER)
|
438
|
+
block4sizer.Add(savepathsizer, -1, wxALIGN_BOTTOM)
|
439
|
+
|
440
|
+
fontsizer = wxFlexGridSizer(cols = 1, vgap = 2)
|
441
|
+
fontsizer.Add(StaticText(''))
|
442
|
+
fontsizer.Add(StaticText('Font: *'), 1, wxALIGN_CENTER)
|
443
|
+
fontsizer.Add(self.gui_font_data, 1, wxALIGN_CENTER)
|
444
|
+
block4sizer.Add(fontsizer, 1, wxALIGN_CENTER_VERTICAL)
|
445
|
+
|
446
|
+
dratesettingsSizer = wxFlexGridSizer(cols = 1, vgap = 2)
|
447
|
+
dratesettingsSizer.Add(StaticText('Default Max'), 1, wxALIGN_CENTER)
|
448
|
+
dratesettingsSizer.Add(StaticText('Download Rate'), 1, wxALIGN_CENTER)
|
449
|
+
dratesettingsSizer.Add(StaticText('(kB/s): *'), 1, wxALIGN_CENTER)
|
450
|
+
dratesettingsSizer.Add(self.maxdownload_data, 1, wxALIGN_CENTER)
|
451
|
+
dratesettingsSizer.Add(StaticText('(0 = disabled)'), 1, wxALIGN_CENTER)
|
452
|
+
|
453
|
+
block4sizer.Add(dratesettingsSizer, 1, wxALIGN_CENTER_VERTICAL)
|
454
|
+
|
455
|
+
colsizer.Add(block4sizer, 0, wxALIGN_CENTER)
|
456
|
+
# colsizer.Add(StaticText(' '))
|
457
|
+
|
458
|
+
savesizer = wxGridSizer(cols = 4, hgap = 10)
|
459
|
+
saveButton = wxButton(panel, -1, 'Save')
|
460
|
+
# saveButton.SetFont(self.default_font)
|
461
|
+
savesizer.Add(saveButton, 0, wxALIGN_CENTER)
|
462
|
+
|
463
|
+
cancelButton = wxButton(panel, -1, 'Cancel')
|
464
|
+
# cancelButton.SetFont(self.default_font)
|
465
|
+
savesizer.Add(cancelButton, 0, wxALIGN_CENTER)
|
466
|
+
|
467
|
+
defaultsButton = wxButton(panel, -1, 'Revert to Defaults')
|
468
|
+
# defaultsButton.SetFont(self.default_font)
|
469
|
+
savesizer.Add(defaultsButton, 0, wxALIGN_CENTER)
|
470
|
+
|
471
|
+
advancedButton = wxButton(panel, -1, 'Advanced...')
|
472
|
+
# advancedButton.SetFont(self.default_font)
|
473
|
+
savesizer.Add(advancedButton, 0, wxALIGN_CENTER)
|
474
|
+
colsizer.Add(savesizer, 1, wxALIGN_CENTER)
|
475
|
+
|
476
|
+
resizewarningtext=StaticText('* These settings will not take effect until the next time you start BitTorrent', self.FONT-2)
|
477
|
+
colsizer.Add(resizewarningtext, 1, wxALIGN_CENTER)
|
478
|
+
|
479
|
+
border = wxBoxSizer(wxHORIZONTAL)
|
480
|
+
border.Add(colsizer, 1, wxEXPAND | wxALL, 4)
|
481
|
+
|
482
|
+
panel.SetSizer(border)
|
483
|
+
panel.SetAutoLayout(True)
|
484
|
+
|
485
|
+
self.advancedConfig = {}
|
486
|
+
|
487
|
+
def setDefaults(evt, self = self):
|
488
|
+
try:
|
489
|
+
self.minport_data.SetValue(self.defaults['minport'])
|
490
|
+
self.maxport_data.SetValue(self.defaults['maxport'])
|
491
|
+
self.randomport_checkbox.SetValue(self.defaults['random_port'])
|
492
|
+
self.gui_stretchwindow_checkbox.SetValue(self.defaults['gui_stretchwindow'])
|
493
|
+
self.gui_displaystats_checkbox.SetValue(self.defaults['gui_displaystats'])
|
494
|
+
self.gui_displaymiscstats_checkbox.SetValue(self.defaults['gui_displaymiscstats'])
|
495
|
+
self.security_checkbox.SetValue(self.defaults['security'])
|
496
|
+
self.autokick_checkbox.SetValue(self.defaults['auto_kick'])
|
497
|
+
self.buffering_checkbox.SetValue(self.defaults['buffer_reads'])
|
498
|
+
self.breakup_checkbox.SetValue(self.defaults['breakup_seed_bitfield'])
|
499
|
+
self.autoflush_checkbox.SetValue(self.defaults['auto_flush'])
|
500
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
501
|
+
self.ipv6enabled_checkbox.SetValue(self.defaults['ipv6_enabled'])
|
502
|
+
self.gui_forcegreenonfirewall_checkbox.SetValue(self.defaults['gui_forcegreenonfirewall'])
|
503
|
+
self.gui_font_data.SetValue(self.defaults['gui_font'])
|
504
|
+
self.gui_ratesettingsdefault_data.SetStringSelection(self.defaults['gui_ratesettingsdefault'])
|
505
|
+
self.maxdownload_data.SetValue(self.defaults['max_download_rate'])
|
506
|
+
self.gui_ratesettingsmode_data.SetStringSelection(self.defaults['gui_ratesettingsmode'])
|
507
|
+
self.gui_default_savedir_ctrl.SetValue(self.defaults['gui_default_savedir'])
|
508
|
+
self.gui_savemode_data.SetSelection(1-self.defaults['gui_saveas_ask'])
|
509
|
+
|
510
|
+
self.checkingcolor = HexToColor(self.defaults['gui_checkingcolor'])
|
511
|
+
self.setColorIcon(self.checkingcolor_icon, self.checkingcolor_iconptr, self.checkingcolor)
|
512
|
+
self.downloadcolor = HexToColor(self.defaults['gui_downloadcolor'])
|
513
|
+
self.setColorIcon(self.downloadcolor_icon, self.downloadcolor_iconptr, self.downloadcolor)
|
514
|
+
self.seedingcolor = HexToColor(self.defaults['gui_seedingcolor'])
|
515
|
+
self.setColorIcon(self.seedingcolor_icon, self.seedingcolor_iconptr, self.seedingcolor)
|
516
|
+
|
517
|
+
if (sys.platform == 'win32'):
|
518
|
+
self.win32_taskbar_icon_checkbox.SetValue(self.defaults['win32_taskbar_icon'])
|
519
|
+
# self.upnp_checkbox.SetValue(self.defaults['upnp_nat_access'])
|
520
|
+
self.upnp_data.SetSelection(self.defaults['upnp_nat_access'])
|
521
|
+
|
522
|
+
# reset advanced too
|
523
|
+
self.advancedConfig = {}
|
524
|
+
for key in ['ip', 'bind', 'min_peers', 'max_initiate', 'display_interval',
|
525
|
+
'alloc_type', 'alloc_rate', 'max_files_open', 'max_connections', 'super_seeder',
|
526
|
+
'ipv6_binds_v4', 'double_check', 'triple_check', 'lock_files', 'lock_while_reading',
|
527
|
+
'expire_cache_data']:
|
528
|
+
self.advancedConfig[key] = self.defaults[key]
|
529
|
+
self.CloseAdvanced()
|
530
|
+
except:
|
531
|
+
self.parent.exception()
|
532
|
+
|
533
|
+
|
534
|
+
def saveConfigs(evt, self = self):
|
535
|
+
try:
|
536
|
+
self.config['gui_stretchwindow']=int(self.gui_stretchwindow_checkbox.GetValue())
|
537
|
+
self.config['gui_displaystats']=int(self.gui_displaystats_checkbox.GetValue())
|
538
|
+
self.config['gui_displaymiscstats']=int(self.gui_displaymiscstats_checkbox.GetValue())
|
539
|
+
self.config['security']=int(self.security_checkbox.GetValue())
|
540
|
+
self.config['auto_kick']=int(self.autokick_checkbox.GetValue())
|
541
|
+
buffering=int(self.buffering_checkbox.GetValue())
|
542
|
+
self.config['buffer_reads']=buffering
|
543
|
+
if buffering:
|
544
|
+
self.config['write_buffer_size']=self.defaults['write_buffer_size']
|
545
|
+
else:
|
546
|
+
self.config['write_buffer_size']=0
|
547
|
+
self.config['breakup_seed_bitfield']=int(self.breakup_checkbox.GetValue())
|
548
|
+
if self.autoflush_checkbox.GetValue():
|
549
|
+
self.config['auto_flush']=5
|
550
|
+
else:
|
551
|
+
self.config['auto_flush']=0
|
552
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
553
|
+
self.config['ipv6_enabled']=int(self.ipv6enabled_checkbox.GetValue())
|
554
|
+
self.config['gui_forcegreenonfirewall']=int(self.gui_forcegreenonfirewall_checkbox.GetValue())
|
555
|
+
self.config['minport']=self.minport_data.GetValue()
|
556
|
+
self.config['maxport']=self.maxport_data.GetValue()
|
557
|
+
self.config['random_port']=int(self.randomport_checkbox.GetValue())
|
558
|
+
self.config['gui_font']=self.gui_font_data.GetValue()
|
559
|
+
self.config['gui_ratesettingsdefault']=self.gui_ratesettingsdefault_data.GetStringSelection()
|
560
|
+
self.config['max_download_rate']=self.maxdownload_data.GetValue()
|
561
|
+
self.config['gui_ratesettingsmode']=self.gui_ratesettingsmode_data.GetStringSelection()
|
562
|
+
self.config['gui_default_savedir']=self.gui_default_savedir_ctrl.GetValue()
|
563
|
+
self.config['gui_saveas_ask']=1-self.gui_savemode_data.GetSelection()
|
564
|
+
self.config['gui_checkingcolor']=ColorToHex(self.checkingcolor)
|
565
|
+
self.config['gui_downloadcolor']=ColorToHex(self.downloadcolor)
|
566
|
+
self.config['gui_seedingcolor']=ColorToHex(self.seedingcolor)
|
567
|
+
|
568
|
+
if (sys.platform == 'win32'):
|
569
|
+
self.config['win32_taskbar_icon']=int(self.win32_taskbar_icon_checkbox.GetValue())
|
570
|
+
# self.config['upnp_nat_access']=int(self.upnp_checkbox.GetValue())
|
571
|
+
self.config['upnp_nat_access']=self.upnp_data.GetSelection()
|
572
|
+
|
573
|
+
if self.advancedConfig:
|
574
|
+
for key,val in self.advancedConfig.items():
|
575
|
+
self.config[key] = val
|
576
|
+
|
577
|
+
self.writeConfigFile()
|
578
|
+
self._configReset = True
|
579
|
+
self.Close()
|
580
|
+
except:
|
581
|
+
self.parent.exception()
|
582
|
+
|
583
|
+
def cancelConfigs(evt, self = self):
|
584
|
+
self.Close()
|
585
|
+
|
586
|
+
def savepath_set(evt, self = self):
|
587
|
+
try:
|
588
|
+
d = self.gui_default_savedir_ctrl.GetValue()
|
589
|
+
if d == '':
|
590
|
+
d = self.config['last_saved']
|
591
|
+
dl = wxDirDialog(self.panel, 'Choose a default directory to save to',
|
592
|
+
d, style = wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON)
|
593
|
+
if dl.ShowModal() == wxID_OK:
|
594
|
+
self.gui_default_savedir_ctrl.SetValue(dl.GetPath())
|
595
|
+
except:
|
596
|
+
self.parent.exception()
|
597
|
+
|
598
|
+
def checkingcoloricon_set(evt, self = self):
|
599
|
+
try:
|
600
|
+
newcolor = self.getColorFromUser(self.panel,self.checkingcolor)
|
601
|
+
self.setColorIcon(self.checkingcolor_icon, self.checkingcolor_iconptr, newcolor)
|
602
|
+
self.checkingcolor = newcolor
|
603
|
+
except:
|
604
|
+
self.parent.exception()
|
605
|
+
|
606
|
+
def downloadcoloricon_set(evt, self = self):
|
607
|
+
try:
|
608
|
+
newcolor = self.getColorFromUser(self.panel,self.downloadcolor)
|
609
|
+
self.setColorIcon(self.downloadcolor_icon, self.downloadcolor_iconptr, newcolor)
|
610
|
+
self.downloadcolor = newcolor
|
611
|
+
except:
|
612
|
+
self.parent.exception()
|
613
|
+
|
614
|
+
def seedingcoloricon_set(evt, self = self):
|
615
|
+
try:
|
616
|
+
newcolor = self.getColorFromUser(self.panel,self.seedingcolor)
|
617
|
+
self.setColorIcon(self.seedingcolor_icon, self.seedingcolor_iconptr, newcolor)
|
618
|
+
self.seedingcolor = newcolor
|
619
|
+
except:
|
620
|
+
self.parent.exception()
|
621
|
+
|
622
|
+
EVT_BUTTON(self.configMenuBox, saveButton.GetId(), saveConfigs)
|
623
|
+
EVT_BUTTON(self.configMenuBox, cancelButton.GetId(), cancelConfigs)
|
624
|
+
EVT_BUTTON(self.configMenuBox, defaultsButton.GetId(), setDefaults)
|
625
|
+
EVT_BUTTON(self.configMenuBox, advancedButton.GetId(), self.advancedMenu)
|
626
|
+
EVT_BUTTON(self.configMenuBox, savepathButton.GetId(), savepath_set)
|
627
|
+
EVT_LEFT_DOWN(self.checkingcolor_iconptr, checkingcoloricon_set)
|
628
|
+
EVT_LEFT_DOWN(self.downloadcolor_iconptr, downloadcoloricon_set)
|
629
|
+
EVT_LEFT_DOWN(self.seedingcolor_iconptr, seedingcoloricon_set)
|
630
|
+
|
631
|
+
self.configMenuBox.Show ()
|
632
|
+
border.Fit(panel)
|
633
|
+
self.configMenuBox.Fit()
|
634
|
+
except:
|
635
|
+
self.parent.exception()
|
636
|
+
|
637
|
+
|
638
|
+
def Close(self):
|
639
|
+
self.CloseAdvanced()
|
640
|
+
if self.configMenuBox is not None:
|
641
|
+
try:
|
642
|
+
self.configMenuBox.Close ()
|
643
|
+
except wxPyDeadObjectError, e:
|
644
|
+
pass
|
645
|
+
self.configMenuBox = None
|
646
|
+
|
647
|
+
def advancedMenu(self, event = None):
|
648
|
+
try:
|
649
|
+
if not self.advancedConfig:
|
650
|
+
for key in ['ip', 'bind', 'min_peers', 'max_initiate', 'display_interval',
|
651
|
+
'alloc_type', 'alloc_rate', 'max_files_open', 'max_connections', 'super_seeder',
|
652
|
+
'ipv6_binds_v4', 'double_check', 'triple_check', 'lock_files', 'lock_while_reading',
|
653
|
+
'expire_cache_data']:
|
654
|
+
self.advancedConfig[key] = self.config[key]
|
655
|
+
|
656
|
+
if (self.advancedMenuBox is not None):
|
657
|
+
try:
|
658
|
+
self.advancedMenuBox.Close ()
|
659
|
+
except wxPyDeadObjectError, e:
|
660
|
+
self.advancedMenuBox = None
|
661
|
+
|
662
|
+
self.advancedMenuBox = wxFrame(None, -1, 'BitTorrent Advanced Preferences', size = (1,1),
|
663
|
+
style = wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
|
664
|
+
if (sys.platform == 'win32'):
|
665
|
+
self.advancedMenuBox.SetIcon(self.icon)
|
666
|
+
|
667
|
+
panel = wxPanel(self.advancedMenuBox, -1)
|
668
|
+
# self.panel = panel
|
669
|
+
|
670
|
+
def StaticText(text, font = self.FONT, underline = False, color = None, panel = panel):
|
671
|
+
x = wxStaticText(panel, -1, text, style = wxALIGN_LEFT)
|
672
|
+
x.SetFont(wxFont(font, wxDEFAULT, wxNORMAL, wxNORMAL, underline))
|
673
|
+
if color is not None:
|
674
|
+
x.SetForegroundColour(color)
|
675
|
+
return x
|
676
|
+
|
677
|
+
colsizer = wxFlexGridSizer(cols = 1, hgap = 13, vgap = 13)
|
678
|
+
warningtext = StaticText('CHANGE THESE SETTINGS AT YOUR OWN RISK', self.FONT+4, True, 'Red')
|
679
|
+
colsizer.Add(warningtext, 1, wxALIGN_CENTER)
|
680
|
+
|
681
|
+
self.ip_data = wxTextCtrl(parent = panel, id = -1,
|
682
|
+
value = self.advancedConfig['ip'],
|
683
|
+
size = (self.FONT*13, int(self.FONT*2.2)), style = wxTE_PROCESS_TAB)
|
684
|
+
self.ip_data.SetFont(self.default_font)
|
685
|
+
|
686
|
+
self.bind_data = wxTextCtrl(parent = panel, id = -1,
|
687
|
+
value = self.advancedConfig['bind'],
|
688
|
+
size = (self.FONT*13, int(self.FONT*2.2)), style = wxTE_PROCESS_TAB)
|
689
|
+
self.bind_data.SetFont(self.default_font)
|
690
|
+
|
691
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
692
|
+
self.ipv6bindsv4_data=wxChoice(panel, -1,
|
693
|
+
choices = ['separate sockets', 'single socket'])
|
694
|
+
self.ipv6bindsv4_data.SetFont(self.default_font)
|
695
|
+
self.ipv6bindsv4_data.SetSelection(self.advancedConfig['ipv6_binds_v4'])
|
696
|
+
|
697
|
+
self.minpeers_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7, -1))
|
698
|
+
self.minpeers_data.SetFont(self.default_font)
|
699
|
+
self.minpeers_data.SetRange(10,100)
|
700
|
+
self.minpeers_data.SetValue(self.advancedConfig['min_peers'])
|
701
|
+
# max_initiate = 2*minpeers
|
702
|
+
|
703
|
+
self.displayinterval_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7, -1))
|
704
|
+
self.displayinterval_data.SetFont(self.default_font)
|
705
|
+
self.displayinterval_data.SetRange(100,2000)
|
706
|
+
self.displayinterval_data.SetValue(int(self.advancedConfig['display_interval']*1000))
|
707
|
+
|
708
|
+
self.alloctype_data=wxChoice(panel, -1,
|
709
|
+
choices = ['normal', 'background', 'pre-allocate', 'sparse'])
|
710
|
+
self.alloctype_data.SetFont(self.default_font)
|
711
|
+
self.alloctype_data.SetStringSelection(self.advancedConfig['alloc_type'])
|
712
|
+
|
713
|
+
self.allocrate_data = wxSpinCtrl(panel, -1, '', (-1,-1), (self.FONT*7,-1))
|
714
|
+
self.allocrate_data.SetFont(self.default_font)
|
715
|
+
self.allocrate_data.SetRange(1,100)
|
716
|
+
self.allocrate_data.SetValue(int(self.advancedConfig['alloc_rate']))
|
717
|
+
|
718
|
+
self.locking_data=wxChoice(panel, -1,
|
719
|
+
choices = ['no locking', 'lock while writing', 'lock always'])
|
720
|
+
self.locking_data.SetFont(self.default_font)
|
721
|
+
if self.advancedConfig['lock_files']:
|
722
|
+
if self.advancedConfig['lock_while_reading']:
|
723
|
+
self.locking_data.SetSelection(2)
|
724
|
+
else:
|
725
|
+
self.locking_data.SetSelection(1)
|
726
|
+
else:
|
727
|
+
self.locking_data.SetSelection(0)
|
728
|
+
|
729
|
+
self.doublecheck_data=wxChoice(panel, -1,
|
730
|
+
choices = ['no extra checking', 'double-check', 'triple-check'])
|
731
|
+
self.doublecheck_data.SetFont(self.default_font)
|
732
|
+
if self.advancedConfig['double_check']:
|
733
|
+
if self.advancedConfig['triple_check']:
|
734
|
+
self.doublecheck_data.SetSelection(2)
|
735
|
+
else:
|
736
|
+
self.doublecheck_data.SetSelection(1)
|
737
|
+
else:
|
738
|
+
self.doublecheck_data.SetSelection(0)
|
739
|
+
|
740
|
+
self.maxfilesopen_choices = ['50', '100', '200', 'no limit ']
|
741
|
+
self.maxfilesopen_data=wxChoice(panel, -1, choices = self.maxfilesopen_choices)
|
742
|
+
self.maxfilesopen_data.SetFont(self.default_font)
|
743
|
+
setval = self.advancedConfig['max_files_open']
|
744
|
+
if setval == 0:
|
745
|
+
setval = 'no limit '
|
746
|
+
else:
|
747
|
+
setval = str(setval)
|
748
|
+
if not setval in self.maxfilesopen_choices:
|
749
|
+
setval = self.maxfilesopen_choices[0]
|
750
|
+
self.maxfilesopen_data.SetStringSelection(setval)
|
751
|
+
|
752
|
+
self.maxconnections_choices = ['no limit ', '20', '30', '40', '50', '60', '100', '200']
|
753
|
+
self.maxconnections_data=wxChoice(panel, -1, choices = self.maxconnections_choices)
|
754
|
+
self.maxconnections_data.SetFont(self.default_font)
|
755
|
+
setval = self.advancedConfig['max_connections']
|
756
|
+
if setval == 0:
|
757
|
+
setval = 'no limit '
|
758
|
+
else:
|
759
|
+
setval = str(setval)
|
760
|
+
if not setval in self.maxconnections_choices:
|
761
|
+
setval = self.maxconnections_choices[0]
|
762
|
+
self.maxconnections_data.SetStringSelection(setval)
|
763
|
+
|
764
|
+
self.superseeder_data=wxChoice(panel, -1,
|
765
|
+
choices = ['normal', 'super-seed'])
|
766
|
+
self.superseeder_data.SetFont(self.default_font)
|
767
|
+
self.superseeder_data.SetSelection(self.advancedConfig['super_seeder'])
|
768
|
+
|
769
|
+
self.expirecache_choices = ['never ', '3', '5', '7', '10', '15', '30', '60', '90']
|
770
|
+
self.expirecache_data=wxChoice(panel, -1, choices = self.expirecache_choices)
|
771
|
+
setval = self.advancedConfig['expire_cache_data']
|
772
|
+
if setval == 0:
|
773
|
+
setval = 'never '
|
774
|
+
else:
|
775
|
+
setval = str(setval)
|
776
|
+
if not setval in self.expirecache_choices:
|
777
|
+
setval = self.expirecache_choices[0]
|
778
|
+
self.expirecache_data.SetFont(self.default_font)
|
779
|
+
self.expirecache_data.SetStringSelection(setval)
|
780
|
+
|
781
|
+
|
782
|
+
twocolsizer = wxFlexGridSizer(cols = 2, hgap = 20)
|
783
|
+
datasizer = wxFlexGridSizer(cols = 2, vgap = 2)
|
784
|
+
datasizer.Add(StaticText('Local IP: '), 1, wxALIGN_CENTER_VERTICAL)
|
785
|
+
datasizer.Add(self.ip_data)
|
786
|
+
datasizer.Add(StaticText('IP to bind to: '), 1, wxALIGN_CENTER_VERTICAL)
|
787
|
+
datasizer.Add(self.bind_data)
|
788
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
789
|
+
datasizer.Add(StaticText('IPv6 socket handling: '), 1, wxALIGN_CENTER_VERTICAL)
|
790
|
+
datasizer.Add(self.ipv6bindsv4_data)
|
791
|
+
datasizer.Add(StaticText('Minimum number of peers: '), 1, wxALIGN_CENTER_VERTICAL)
|
792
|
+
datasizer.Add(self.minpeers_data)
|
793
|
+
datasizer.Add(StaticText('Display interval (ms): '), 1, wxALIGN_CENTER_VERTICAL)
|
794
|
+
datasizer.Add(self.displayinterval_data)
|
795
|
+
datasizer.Add(StaticText('Disk allocation type:'), 1, wxALIGN_CENTER_VERTICAL)
|
796
|
+
datasizer.Add(self.alloctype_data)
|
797
|
+
datasizer.Add(StaticText('Allocation rate (MiB/s):'), 1, wxALIGN_CENTER_VERTICAL)
|
798
|
+
datasizer.Add(self.allocrate_data)
|
799
|
+
datasizer.Add(StaticText('File locking:'), 1, wxALIGN_CENTER_VERTICAL)
|
800
|
+
datasizer.Add(self.locking_data)
|
801
|
+
datasizer.Add(StaticText('Extra data checking:'), 1, wxALIGN_CENTER_VERTICAL)
|
802
|
+
datasizer.Add(self.doublecheck_data)
|
803
|
+
datasizer.Add(StaticText('Max files open:'), 1, wxALIGN_CENTER_VERTICAL)
|
804
|
+
datasizer.Add(self.maxfilesopen_data)
|
805
|
+
datasizer.Add(StaticText('Max peer connections:'), 1, wxALIGN_CENTER_VERTICAL)
|
806
|
+
datasizer.Add(self.maxconnections_data)
|
807
|
+
datasizer.Add(StaticText('Default seeding mode:'), 1, wxALIGN_CENTER_VERTICAL)
|
808
|
+
datasizer.Add(self.superseeder_data)
|
809
|
+
datasizer.Add(StaticText('Expire resume data(days):'), 1, wxALIGN_CENTER_VERTICAL)
|
810
|
+
datasizer.Add(self.expirecache_data)
|
811
|
+
|
812
|
+
twocolsizer.Add(datasizer)
|
813
|
+
|
814
|
+
infosizer = wxFlexGridSizer(cols = 1)
|
815
|
+
self.hinttext = StaticText('', self.FONT, False, 'Blue')
|
816
|
+
infosizer.Add(self.hinttext, 1, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL)
|
817
|
+
infosizer.SetMinSize((180,100))
|
818
|
+
twocolsizer.Add(infosizer, 1, wxEXPAND)
|
819
|
+
|
820
|
+
colsizer.Add(twocolsizer)
|
821
|
+
|
822
|
+
savesizer = wxGridSizer(cols = 3, hgap = 20)
|
823
|
+
okButton = wxButton(panel, -1, 'OK')
|
824
|
+
# okButton.SetFont(self.default_font)
|
825
|
+
savesizer.Add(okButton, 0, wxALIGN_CENTER)
|
826
|
+
|
827
|
+
cancelButton = wxButton(panel, -1, 'Cancel')
|
828
|
+
# cancelButton.SetFont(self.default_font)
|
829
|
+
savesizer.Add(cancelButton, 0, wxALIGN_CENTER)
|
830
|
+
|
831
|
+
defaultsButton = wxButton(panel, -1, 'Revert to Defaults')
|
832
|
+
# defaultsButton.SetFont(self.default_font)
|
833
|
+
savesizer.Add(defaultsButton, 0, wxALIGN_CENTER)
|
834
|
+
colsizer.Add(savesizer, 1, wxALIGN_CENTER)
|
835
|
+
|
836
|
+
resizewarningtext=StaticText('None of these settings will take effect until the next time you start BitTorrent', self.FONT-2)
|
837
|
+
colsizer.Add(resizewarningtext, 1, wxALIGN_CENTER)
|
838
|
+
|
839
|
+
border = wxBoxSizer(wxHORIZONTAL)
|
840
|
+
border.Add(colsizer, 1, wxEXPAND | wxALL, 4)
|
841
|
+
|
842
|
+
panel.SetSizer(border)
|
843
|
+
panel.SetAutoLayout(True)
|
844
|
+
|
845
|
+
def setDefaults(evt, self = self):
|
846
|
+
try:
|
847
|
+
self.ip_data.SetValue(self.defaults['ip'])
|
848
|
+
self.bind_data.SetValue(self.defaults['bind'])
|
849
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
850
|
+
self.ipv6bindsv4_data.SetSelection(self.defaults['ipv6_binds_v4'])
|
851
|
+
self.minpeers_data.SetValue(self.defaults['min_peers'])
|
852
|
+
self.displayinterval_data.SetValue(int(self.defaults['display_interval']*1000))
|
853
|
+
self.alloctype_data.SetStringSelection(self.defaults['alloc_type'])
|
854
|
+
self.allocrate_data.SetValue(int(self.defaults['alloc_rate']))
|
855
|
+
if self.defaults['lock_files']:
|
856
|
+
if self.defaults['lock_while_reading']:
|
857
|
+
self.locking_data.SetSelection(2)
|
858
|
+
else:
|
859
|
+
self.locking_data.SetSelection(1)
|
860
|
+
else:
|
861
|
+
self.locking_data.SetSelection(0)
|
862
|
+
if self.defaults['double_check']:
|
863
|
+
if self.defaults['triple_check']:
|
864
|
+
self.doublecheck_data.SetSelection(2)
|
865
|
+
else:
|
866
|
+
self.doublecheck_data.SetSelection(1)
|
867
|
+
else:
|
868
|
+
self.doublecheck_data.SetSelection(0)
|
869
|
+
setval = self.defaults['max_files_open']
|
870
|
+
if setval == 0:
|
871
|
+
setval = 'no limit '
|
872
|
+
else:
|
873
|
+
setval = str(setval)
|
874
|
+
if not setval in self.maxfilesopen_choices:
|
875
|
+
setval = self.maxfilesopen_choices[0]
|
876
|
+
self.maxfilesopen_data.SetStringSelection(setval)
|
877
|
+
setval = self.defaults['max_connections']
|
878
|
+
if setval == 0:
|
879
|
+
setval = 'no limit '
|
880
|
+
else:
|
881
|
+
setval = str(setval)
|
882
|
+
if not setval in self.maxconnections_choices:
|
883
|
+
setval = self.maxconnections_choices[0]
|
884
|
+
self.maxconnections_data.SetStringSelection(setval)
|
885
|
+
self.superseeder_data.SetSelection(int(self.defaults['super_seeder']))
|
886
|
+
setval = self.defaults['expire_cache_data']
|
887
|
+
if setval == 0:
|
888
|
+
setval = 'never '
|
889
|
+
else:
|
890
|
+
setval = str(setval)
|
891
|
+
if not setval in self.expirecache_choices:
|
892
|
+
setval = self.expirecache_choices[0]
|
893
|
+
self.expirecache_data.SetStringSelection(setval)
|
894
|
+
except:
|
895
|
+
self.parent.exception()
|
896
|
+
|
897
|
+
def saveConfigs(evt, self = self):
|
898
|
+
try:
|
899
|
+
self.advancedConfig['ip'] = self.ip_data.GetValue()
|
900
|
+
self.advancedConfig['bind'] = self.bind_data.GetValue()
|
901
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
902
|
+
self.advancedConfig['ipv6_binds_v4'] = self.ipv6bindsv4_data.GetSelection()
|
903
|
+
self.advancedConfig['min_peers'] = self.minpeers_data.GetValue()
|
904
|
+
self.advancedConfig['display_interval'] = float(self.displayinterval_data.GetValue())/1000
|
905
|
+
self.advancedConfig['alloc_type'] = self.alloctype_data.GetStringSelection()
|
906
|
+
self.advancedConfig['alloc_rate'] = float(self.allocrate_data.GetValue())
|
907
|
+
self.advancedConfig['lock_files'] = int(self.locking_data.GetSelection() >= 1)
|
908
|
+
self.advancedConfig['lock_while_reading'] = int(self.locking_data.GetSelection() > 1)
|
909
|
+
self.advancedConfig['double_check'] = int(self.doublecheck_data.GetSelection() >= 1)
|
910
|
+
self.advancedConfig['triple_check'] = int(self.doublecheck_data.GetSelection() > 1)
|
911
|
+
try:
|
912
|
+
self.advancedConfig['max_files_open'] = int(self.maxfilesopen_data.GetStringSelection())
|
913
|
+
except: # if it ain't a number, it must be "no limit"
|
914
|
+
self.advancedConfig['max_files_open'] = 0
|
915
|
+
try:
|
916
|
+
self.advancedConfig['max_connections'] = int(self.maxconnections_data.GetStringSelection())
|
917
|
+
self.advancedConfig['max_initiate'] = min(
|
918
|
+
2*self.advancedConfig['min_peers'], self.advancedConfig['max_connections'])
|
919
|
+
except: # if it ain't a number, it must be "no limit"
|
920
|
+
self.advancedConfig['max_connections'] = 0
|
921
|
+
self.advancedConfig['max_initiate'] = 2*self.advancedConfig['min_peers']
|
922
|
+
self.advancedConfig['super_seeder']=int(self.superseeder_data.GetSelection())
|
923
|
+
try:
|
924
|
+
self.advancedConfig['expire_cache_data'] = int(self.expirecache_data.GetStringSelection())
|
925
|
+
except:
|
926
|
+
self.advancedConfig['expire_cache_data'] = 0
|
927
|
+
self.advancedMenuBox.Close()
|
928
|
+
except:
|
929
|
+
self.parent.exception()
|
930
|
+
|
931
|
+
def cancelConfigs(evt, self = self):
|
932
|
+
self.advancedMenuBox.Close()
|
933
|
+
|
934
|
+
def ip_hint(evt, self = self):
|
935
|
+
self.hinttext.SetLabel('\n\n\nThe IP reported to the tracker.\n' +
|
936
|
+
'unless the tracker is on the\n' +
|
937
|
+
'same intranet as this client,\n' +
|
938
|
+
'the tracker will autodetect the\n' +
|
939
|
+
"client's IP and ignore this\n" +
|
940
|
+
"value.")
|
941
|
+
|
942
|
+
def bind_hint(evt, self = self):
|
943
|
+
self.hinttext.SetLabel('\n\n\nThe IP the client will bind to.\n' +
|
944
|
+
'Only useful if your machine is\n' +
|
945
|
+
'directly handling multiple IPs.\n' +
|
946
|
+
"If you don't know what this is,\n" +
|
947
|
+
"leave it blank.")
|
948
|
+
|
949
|
+
def ipv6bindsv4_hint(evt, self = self):
|
950
|
+
self.hinttext.SetLabel('\n\n\nCertain operating systems will\n' +
|
951
|
+
'open IPv4 protocol connections on\n' +
|
952
|
+
'an IPv6 socket; others require you\n' +
|
953
|
+
"to open two sockets on the same\n" +
|
954
|
+
"port, one IPv4 and one IPv6.")
|
955
|
+
|
956
|
+
def minpeers_hint(evt, self = self):
|
957
|
+
self.hinttext.SetLabel('\n\n\nThe minimum number of peers the\n' +
|
958
|
+
'client tries to stay connected\n' +
|
959
|
+
'with. Do not set this higher\n' +
|
960
|
+
'unless you have a very fast\n' +
|
961
|
+
"connection and a lot of system\n" +
|
962
|
+
"resources.")
|
963
|
+
|
964
|
+
def displayinterval_hint(evt, self = self):
|
965
|
+
self.hinttext.SetLabel('\n\n\nHow often to update the\n' +
|
966
|
+
'graphical display, in 1/1000s\n' +
|
967
|
+
'of a second. Setting this too low\n' +
|
968
|
+
"will strain your computer's\n" +
|
969
|
+
"processor and video access.")
|
970
|
+
|
971
|
+
def alloctype_hint(evt, self = self):
|
972
|
+
self.hinttext.SetLabel('\n\nHow to allocate disk space.\n' +
|
973
|
+
'normal allocates space as data is\n' +
|
974
|
+
'received, background also adds\n' +
|
975
|
+
"space in the background, pre-\n" +
|
976
|
+
"allocate reserves up front, and\n" +
|
977
|
+
'sparse is only for filesystems\n' +
|
978
|
+
'that support it by default.')
|
979
|
+
|
980
|
+
def allocrate_hint(evt, self = self):
|
981
|
+
self.hinttext.SetLabel('\n\n\nAt what rate to allocate disk\n' +
|
982
|
+
'space when allocating in the\n' +
|
983
|
+
'background. Set this too high on a\n' +
|
984
|
+
"slow filesystem and your download\n" +
|
985
|
+
"will slow to a crawl.")
|
986
|
+
|
987
|
+
def locking_hint(evt, self = self):
|
988
|
+
self.hinttext.SetLabel('\n\n\n\nFile locking prevents other\n' +
|
989
|
+
'programs (including other instances\n' +
|
990
|
+
'of BitTorrent) from accessing files\n' +
|
991
|
+
"you are downloading.")
|
992
|
+
|
993
|
+
def doublecheck_hint(evt, self = self):
|
994
|
+
self.hinttext.SetLabel('\n\n\nHow much extra checking to do\n' +
|
995
|
+
'making sure no data is corrupted.\n' +
|
996
|
+
'Double-check mode uses more CPU,\n' +
|
997
|
+
"while triple-check mode increases\n" +
|
998
|
+
"disk accesses.")
|
999
|
+
|
1000
|
+
def maxfilesopen_hint(evt, self = self):
|
1001
|
+
self.hinttext.SetLabel('\n\n\nThe maximum number of files to\n' +
|
1002
|
+
'keep open at the same time. Zero\n' +
|
1003
|
+
'means no limit. Please note that\n' +
|
1004
|
+
"if this option is in effect,\n" +
|
1005
|
+
"files are not guaranteed to be\n" +
|
1006
|
+
"locked.")
|
1007
|
+
|
1008
|
+
def maxconnections_hint(evt, self = self):
|
1009
|
+
self.hinttext.SetLabel('\n\nSome operating systems, most\n' +
|
1010
|
+
'notably Windows 9x/ME combined\n' +
|
1011
|
+
'with certain network drivers,\n' +
|
1012
|
+
"cannot handle more than a certain\n" +
|
1013
|
+
"number of open ports. If the\n" +
|
1014
|
+
"client freezes, try setting this\n" +
|
1015
|
+
"to 60 or below.")
|
1016
|
+
|
1017
|
+
def superseeder_hint(evt, self = self):
|
1018
|
+
self.hinttext.SetLabel('\n\nThe "super-seed" method allows\n' +
|
1019
|
+
'a single source to more efficiently\n' +
|
1020
|
+
'seed a large torrent, but is not\n' +
|
1021
|
+
"necessary in a well-seeded torrent,\n" +
|
1022
|
+
"and causes problems with statistics.\n" +
|
1023
|
+
"Unless you routinely seed torrents\n" +
|
1024
|
+
"you can enable this by selecting\n" +
|
1025
|
+
'"SUPER-SEED" for connection type.\n' +
|
1026
|
+
'(once enabled it does not turn off.)')
|
1027
|
+
|
1028
|
+
def expirecache_hint(evt, self = self):
|
1029
|
+
self.hinttext.SetLabel('\n\nThe client stores temporary data\n' +
|
1030
|
+
'in order to handle downloading only\n' +
|
1031
|
+
'specific files from the torrent and\n' +
|
1032
|
+
"so it can resume downloads more\n" +
|
1033
|
+
"quickly. This sets how long the\n" +
|
1034
|
+
"client will keep this data before\n" +
|
1035
|
+
"deleting it to free disk space.")
|
1036
|
+
|
1037
|
+
EVT_BUTTON(self.advancedMenuBox, okButton.GetId(), saveConfigs)
|
1038
|
+
EVT_BUTTON(self.advancedMenuBox, cancelButton.GetId(), cancelConfigs)
|
1039
|
+
EVT_BUTTON(self.advancedMenuBox, defaultsButton.GetId(), setDefaults)
|
1040
|
+
EVT_ENTER_WINDOW(self.ip_data, ip_hint)
|
1041
|
+
EVT_ENTER_WINDOW(self.bind_data, bind_hint)
|
1042
|
+
if sys.version_info >= (2,3) and socket.has_ipv6:
|
1043
|
+
EVT_ENTER_WINDOW(self.ipv6bindsv4_data, ipv6bindsv4_hint)
|
1044
|
+
EVT_ENTER_WINDOW(self.minpeers_data, minpeers_hint)
|
1045
|
+
EVT_ENTER_WINDOW(self.displayinterval_data, displayinterval_hint)
|
1046
|
+
EVT_ENTER_WINDOW(self.alloctype_data, alloctype_hint)
|
1047
|
+
EVT_ENTER_WINDOW(self.allocrate_data, allocrate_hint)
|
1048
|
+
EVT_ENTER_WINDOW(self.locking_data, locking_hint)
|
1049
|
+
EVT_ENTER_WINDOW(self.doublecheck_data, doublecheck_hint)
|
1050
|
+
EVT_ENTER_WINDOW(self.maxfilesopen_data, maxfilesopen_hint)
|
1051
|
+
EVT_ENTER_WINDOW(self.maxconnections_data, maxconnections_hint)
|
1052
|
+
EVT_ENTER_WINDOW(self.superseeder_data, superseeder_hint)
|
1053
|
+
EVT_ENTER_WINDOW(self.expirecache_data, expirecache_hint)
|
1054
|
+
|
1055
|
+
self.advancedMenuBox.Show ()
|
1056
|
+
border.Fit(panel)
|
1057
|
+
self.advancedMenuBox.Fit()
|
1058
|
+
except:
|
1059
|
+
self.parent.exception()
|
1060
|
+
|
1061
|
+
|
1062
|
+
def CloseAdvanced(self):
|
1063
|
+
if self.advancedMenuBox is not None:
|
1064
|
+
try:
|
1065
|
+
self.advancedMenuBox.Close()
|
1066
|
+
except wxPyDeadObjectError, e:
|
1067
|
+
self.advancedMenuBox = None
|
1068
|
+
|