murder 0.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.gitignore +1 -0
  2. data/LICENSE +17 -0
  3. data/README +224 -0
  4. data/Rakefile +52 -0
  5. data/VERSION +1 -0
  6. data/dist/BitTornado/BT1/Choker.py +128 -0
  7. data/dist/BitTornado/BT1/Connecter.py +288 -0
  8. data/dist/BitTornado/BT1/Downloader.py +594 -0
  9. data/dist/BitTornado/BT1/DownloaderFeedback.py +155 -0
  10. data/dist/BitTornado/BT1/Encrypter.py +333 -0
  11. data/dist/BitTornado/BT1/FileSelector.py +245 -0
  12. data/dist/BitTornado/BT1/Filter.py +12 -0
  13. data/dist/BitTornado/BT1/HTTPDownloader.py +251 -0
  14. data/dist/BitTornado/BT1/NatCheck.py +95 -0
  15. data/dist/BitTornado/BT1/PiecePicker.py +320 -0
  16. data/dist/BitTornado/BT1/Rerequester.py +426 -0
  17. data/dist/BitTornado/BT1/Statistics.py +177 -0
  18. data/dist/BitTornado/BT1/Storage.py +584 -0
  19. data/dist/BitTornado/BT1/StorageWrapper.py +1045 -0
  20. data/dist/BitTornado/BT1/StreamCheck.py +135 -0
  21. data/dist/BitTornado/BT1/T2T.py +193 -0
  22. data/dist/BitTornado/BT1/Uploader.py +145 -0
  23. data/dist/BitTornado/BT1/__init__.py +1 -0
  24. data/dist/BitTornado/BT1/btformats.py +100 -0
  25. data/dist/BitTornado/BT1/fakeopen.py +89 -0
  26. data/dist/BitTornado/BT1/makemetafile.py +263 -0
  27. data/dist/BitTornado/BT1/track.py +1067 -0
  28. data/dist/BitTornado/ConfigDir.py +401 -0
  29. data/dist/BitTornado/ConfigReader.py +1068 -0
  30. data/dist/BitTornado/ConnChoice.py +31 -0
  31. data/dist/BitTornado/CreateIcons.py +105 -0
  32. data/dist/BitTornado/CurrentRateMeasure.py +37 -0
  33. data/dist/BitTornado/HTTPHandler.py +167 -0
  34. data/dist/BitTornado/PSYCO.py +5 -0
  35. data/dist/BitTornado/RateLimiter.py +153 -0
  36. data/dist/BitTornado/RateMeasure.py +75 -0
  37. data/dist/BitTornado/RawServer.py +195 -0
  38. data/dist/BitTornado/ServerPortHandler.py +188 -0
  39. data/dist/BitTornado/SocketHandler.py +375 -0
  40. data/dist/BitTornado/__init__.py +63 -0
  41. data/dist/BitTornado/bencode.py +319 -0
  42. data/dist/BitTornado/bitfield.py +162 -0
  43. data/dist/BitTornado/clock.py +27 -0
  44. data/dist/BitTornado/download_bt1.py +882 -0
  45. data/dist/BitTornado/inifile.py +169 -0
  46. data/dist/BitTornado/iprangeparse.py +194 -0
  47. data/dist/BitTornado/launchmanycore.py +381 -0
  48. data/dist/BitTornado/natpunch.py +254 -0
  49. data/dist/BitTornado/parseargs.py +137 -0
  50. data/dist/BitTornado/parsedir.py +150 -0
  51. data/dist/BitTornado/piecebuffer.py +86 -0
  52. data/dist/BitTornado/selectpoll.py +109 -0
  53. data/dist/BitTornado/subnetparse.py +218 -0
  54. data/dist/BitTornado/torrentlistparse.py +38 -0
  55. data/dist/BitTornado/zurllib.py +100 -0
  56. data/dist/murder_client.py +291 -0
  57. data/dist/murder_make_torrent.py +46 -0
  58. data/dist/murder_tracker.py +28 -0
  59. data/doc/examples/Capfile +28 -0
  60. data/lib/capistrano/recipes/deploy/strategy/murder.rb +52 -0
  61. data/lib/murder.rb +43 -0
  62. data/lib/murder/admin.rb +47 -0
  63. data/lib/murder/murder.rb +121 -0
  64. data/murder.gemspec +101 -0
  65. 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
+