(file) Return to bt-t-make.py CVS log (file) (dir) Up to [Development] / bittornado

   1 theshadow 1.1 #!/usr/bin/env python
   2               
   3               # Written by Bram Cohen
   4               # modified for multitracker by John Hoffman
   5               # see LICENSE.txt for license information
   6               
   7 theshadow 1.2 from BitTornado import PSYCO
   8 theshadow 1.1 if PSYCO.psyco:
   9                   try:
  10                       import psyco
  11                       assert psyco.__version__ >= 0x010100f0
  12                       psyco.full()
  13                   except:
  14                       pass
  15               
  16 theshadow 1.6 from sys import argv, platform, version
  17 theshadow 1.5 assert version >= '2', "Install Python 2.0 or greater"
  18               from BitTornado.BT1.makemetafile import make_meta_file
  19 theshadow 1.1 from threading import Event, Thread, Lock
  20 theshadow 1.2 from BitTornado.bencode import bencode,bdecode
  21 theshadow 1.1 import sys, os, shutil
  22 theshadow 1.4 from os import getcwd, listdir
  23 theshadow 1.1 from os.path import join, isdir
  24               from traceback import print_exc
  25 theshadow 1.4 try:
  26                   from wxPython.wx import *
  27               except:
  28                   print 'wxPython is either not installed or has not been installed properly.'
  29                   sys.exit(1)
  30               
  31 theshadow 1.3 try:
  32                   True
  33               except:
  34                   True = 1
  35                   False = 0
  36 theshadow 1.1 
  37               basepath=os.path.abspath(os.path.dirname(sys.argv[0]))
  38               
  39               if platform == 'win32':
  40                   DROP_HERE = '(drop here)'
  41               else:
  42                   DROP_HERE = ''
  43               
  44               
  45               wxEVT_INVOKE = wxNewEventType()
  46               
  47               def EVT_INVOKE(win, func):
  48                   win.Connect(-1, -1, wxEVT_INVOKE, func)
  49               
  50               class InvokeEvent(wxPyEvent):
  51                   def __init__(self, func, args, kwargs):
  52                       wxPyEvent.__init__(self)
  53                       self.SetEventType(wxEVT_INVOKE)
  54                       self.func = func
  55                       self.args = args
  56                       self.kwargs = kwargs
  57 theshadow 1.1 
  58               
  59               class BasicDownloadInfo:
  60                   def __init__(self, config, calls):
  61                       self.config = config
  62                       self.calls = calls
  63                       
  64                       self.uiflag = Event()
  65                       self.cancelflag = Event()
  66                       self.switchlock = Lock()
  67 theshadow 1.3         self.working = False
  68 theshadow 1.1         self.queue = []
  69                       wxInitAllImageHandlers()
  70                       self.thostselection = self.calls['getCurrentTHost']()
  71                       self.thostselectnum = 0
  72                       self.choices = None
  73                       self.choices1 = None
  74                       self.announce = ''
  75                       self.announce_list = None
  76               
  77                       self.windowStyle = wxSYSTEM_MENU|wxCAPTION|wxMINIMIZE_BOX
  78                       if self.config['stayontop']:
  79                           self.windowStyle |= wxSTAY_ON_TOP
  80                       frame = wxFrame(None, -1, 'T-Make',
  81                                       size = wxSize(-1, -1),
  82                                       style = self.windowStyle)
  83                       self.frame = frame
  84                       panel = wxPanel(frame, -1)
  85                       mainSizer = wxBoxSizer(wxVERTICAL)
  86                       groupSizer = wxFlexGridSizer(cols = 1, vgap = 0, hgap = 0)
  87               #        self.dropTarget = self.calls['newDropTarget']((200,200))
  88                       self.dropTarget = self.calls['newDropTarget']()
  89 theshadow 1.1         self.dropTargetPtr = wxStaticBitmap(panel, -1, self.dropTarget)
  90                       self.calls['setDropTargetRefresh'](self.dropTargetPtr.Refresh)
  91                       self.dropTargetWidth = self.dropTarget.GetWidth()
  92                       EVT_LEFT_DOWN(self.dropTargetPtr,self.dropTargetClick)
  93                       EVT_ENTER_WINDOW(self.dropTargetPtr,self.calls['dropTargetHovered'])
  94                       EVT_LEAVE_WINDOW(self.dropTargetPtr,self.calls['dropTargetUnhovered'])
  95                       groupSizer.Add(self.dropTargetPtr,0,wxALIGN_CENTER)        
  96                       lowerSizer1 = wxGridSizer(cols = 6)
  97                       dirlink = wxStaticText(panel, -1, 'dir')
  98 theshadow 1.3         dirlink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, True))
  99 theshadow 1.1         dirlink.SetForegroundColour('blue')
 100                       EVT_LEFT_UP(dirlink,self.selectdir)
 101                       lowerSizer1.Add(dirlink, -1, wxALIGN_LEFT)
 102                       lowerSizer1.Add(wxStaticText(panel, -1, ''), -1, wxALIGN_CENTER)
 103                       lowerSizer1.Add(wxStaticText(panel, -1, ''), -1, wxALIGN_CENTER)
 104                       lowerSizer1.Add(wxStaticText(panel, -1, ''), -1, wxALIGN_CENTER)
 105                       lowerSizer1.Add(wxStaticText(panel, -1, ''), -1, wxALIGN_CENTER)
 106                       filelink = wxStaticText(panel, -1, 'file')
 107 theshadow 1.3         filelink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, True))
 108 theshadow 1.1         filelink.SetForegroundColour('blue')
 109                       EVT_LEFT_UP(filelink,self.selectfile)
 110                       lowerSizer1.Add(filelink, -1, wxALIGN_RIGHT)
 111                       
 112                       groupSizer.Add(lowerSizer1, -1, wxALIGN_CENTER)
 113               
 114                       self.gauge = wxGauge(panel, -1, range = 1000,
 115                                            style = wxGA_HORIZONTAL, size = (-1,15))
 116                       groupSizer.Add(self.gauge, 0, wxEXPAND)
 117                       self.statustext = wxStaticText(panel, -1, 'ready',
 118                                           style = wxALIGN_CENTER|wxST_NO_AUTORESIZE)
 119 theshadow 1.3         self.statustext.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxBOLD, False))
 120 theshadow 1.1         groupSizer.Add(self.statustext, -1, wxEXPAND)
 121                       self.choices = wxChoice(panel, -1, (-1, -1), (self.dropTargetWidth, -1),
 122                                                   choices = [])
 123 theshadow 1.3         self.choices.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, False))
 124 theshadow 1.1         EVT_CHOICE(self.choices, -1, self.set_thost)
 125                       groupSizer.Add(self.choices, 0, wxEXPAND)
 126                       cancellink = wxStaticText(panel, -1, 'cancel')
 127 theshadow 1.3         cancellink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, True))
 128 theshadow 1.1         cancellink.SetForegroundColour('red')
 129                       EVT_LEFT_UP(cancellink,self.cancel)
 130                       groupSizer.Add(cancellink, -1, wxALIGN_CENTER)
 131                       advlink = wxStaticText(panel, -1, 'advanced')
 132 theshadow 1.3         advlink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, True))
 133 theshadow 1.1         advlink.SetForegroundColour('blue')
 134                       EVT_LEFT_UP(advlink,self.calls['switchToAdvanced'])
 135                       groupSizer.Add(advlink, -1, wxALIGN_CENTER)
 136                       mainSizer.Add(groupSizer, 0, wxALIGN_CENTER)
 137               
 138                       self.refresh_thostlist()
 139                       self._set_thost()
 140               
 141                       if platform == 'win32':
 142 theshadow 1.3             self.dropTargetPtr.DragAcceptFiles(True)
 143 theshadow 1.1             EVT_DROP_FILES(self.dropTargetPtr, self.selectdrop)
 144                
 145               #        border = wxBoxSizer(wxHORIZONTAL)
 146               #        border.Add(mainSizer, 1, wxEXPAND | wxALL, 0)
 147                       panel.SetSizer(mainSizer)
 148 theshadow 1.3         panel.SetAutoLayout(True)
 149 theshadow 1.1 #        border.Fit(panel)
 150                       mainSizer.Fit(panel)
 151                       frame.Fit()
 152 theshadow 1.3         frame.Show(True)
 153 theshadow 1.1 
 154                       EVT_INVOKE(frame, self.onInvoke)
 155                       EVT_CLOSE(frame, self._close)
 156               
 157               
 158                   def selectdir(self, x = None):
 159                       self.calls['dropTargetHovered']()
 160                       dl = wxDirDialog(self.frame, style = wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON)
 161                       if dl.ShowModal() == wxID_OK:
 162                           self.calls['dropTargetDropped']()
 163                           self.complete(dl.GetPath())
 164                       else:
 165                           self.calls['dropTargetUnhovered']()
 166               
 167                   def selectfile(self, x = None):
 168                       self.calls['dropTargetHovered']()
 169                       dl = wxFileDialog (self.frame, 'Choose file to use', '', '', '', wxOPEN)
 170                       if dl.ShowModal() == wxID_OK:
 171                           self.calls['dropTargetDropped']()
 172                           self.complete(dl.GetPath())
 173                       else:
 174 theshadow 1.1             self.calls['dropTargetUnhovered']()
 175               
 176                   def selectdrop(self, dat):
 177                       self.calls['dropTargetDropped']()
 178                       for f in dat.GetFiles():
 179                           self.complete(f)
 180               
 181                   def _announcecopy(self, f):
 182                       try:
 183                           h = open(f, 'rb')
 184                           metainfo = bdecode(h.read())
 185                           h.close()
 186                           self.announce = metainfo['announce']
 187                           if metainfo.has_key('announce-list'):
 188                               self.announce_list = metainfo['announce-list']
 189                           else:
 190                               self.announce_list = None
 191                       except:
 192                           return
 193               
 194                   def complete(self, x):
 195 theshadow 1.1         params = {'piece_size_pow2': 0}
 196                       if self.announce_list:
 197                           params['real_announce_list'] = self.announce_list
 198                       self.queue.append((x, self.announce, params))
 199                       self.go_queue()
 200               
 201                   def go_queue(self):
 202                       self.switchlock.acquire()
 203                       if self.queue and not self.working:
 204 theshadow 1.3             self.working = True
 205 theshadow 1.1             self.statustext.SetLabel('working')
 206                           q = self.queue.pop(0)
 207                           MakeMetafile(q[0], q[1], q[2], self)
 208                       self.switchlock.release()
 209               
 210                   def cancel(self, x):
 211                       self.switchlock.acquire()
 212                       if self.working:
 213 theshadow 1.3             self.working = False
 214 theshadow 1.1             self.cancelflag.set()
 215                           self.cancelflag = Event()
 216                           self.queue = []
 217                           self.statustext.SetLabel('CANCELED')
 218                           self.calls['dropTargetError']()
 219                       self.switchlock.release()
 220               
 221                   def dropTargetClick(self, x):
 222                       if x.GetPosition()[0] < int(self.dropTargetWidth*0.4):
 223                           self.selectdir()
 224                       elif x.GetPosition()[0] > int(self.dropTargetWidth*0.6):
 225                           self.selectfile()
 226               
 227                   def refresh_thostlist(self):
 228                       l = []
 229                       d = 0
 230                       for f in listdir(join(basepath,'thosts')):
 231                           if f[-6:].lower() == '.thost':
 232                               l.append(f)
 233                               if f == self.thostselection:
 234                                   d = len(l)
 235 theshadow 1.1         self.choices.Clear()
 236                       if not d:
 237                           if l:
 238                               self.thostselection = l[0]
 239                               d = 1
 240                           else:
 241                               self.thostselection = ''
 242                               d = 1
 243                           self.config['thost'] = self.thostselection
 244                           self.calls['saveConfig']()
 245                       for f in l:
 246                           self.choices.Append(f[:-6])
 247                       self.thostselectnum = d-1
 248                       self.thostlist = l
 249                       self.choices.SetSelection(d-1)
 250                       return
 251               
 252                   def set_thost(self, x):
 253                       n = self.choices.GetSelection()
 254                       if n != self.thostselectnum:
 255                           self.thostselectnum = n
 256 theshadow 1.1             if n:
 257                               self.thostselection = self.thostlist[n-1]
 258               
 259                   def _set_thost(self):
 260                       self._announcecopy(join(join(basepath,'thosts'),self.thostselection))
 261                       self.calls['setCurrentTHost'](self.thostselection)
 262               
 263                   def onInvoke(self, event):
 264                       if not self.uiflag.isSet():
 265                           apply(event.func, event.args, event.kwargs)
 266               
 267                   def invokeLater(self, func, args = [], kwargs = {}):
 268                       if not self.uiflag.isSet():
 269                           wxPostEvent(self.frame, InvokeEvent(func, args, kwargs))
 270               
 271                   def build_setgauge(self, x):
 272                       self.invokeLater(self.on_setgauge, [x])
 273               
 274                   def on_setgauge(self, x):
 275                       self.gauge.SetValue(int(x*1000))
 276               
 277 theshadow 1.1     def build_done(self):
 278                       self.invokeLater(self.on_builddone)
 279               
 280                   def on_builddone(self):
 281                       self.gauge.SetValue(0)
 282                       self.statustext.SetLabel('done!')
 283                       self.calls['dropTargetSuccess']()
 284 theshadow 1.3         self.working = False
 285 theshadow 1.1         self.go_queue()
 286               
 287                   def build_failed(self, e):
 288                       self.invokeLater(self.on_buildfailed, [e])
 289               
 290                   def on_buildfailed(self, e):        
 291                       self.gauge.SetValue(0)
 292                       self.statustext.SetLabel('ERROR')
 293                       self.calls['dropTargetError']()
 294 theshadow 1.3         self.working = False
 295 theshadow 1.1         self.go_queue()
 296               
 297                   def close(self):
 298                       self.cancelflag = None   # this is a planned switch, don't cancel
 299                       self.uiflag.set()
 300                       self.frame.Close()
 301               
 302                   def _close(self, x = None):
 303                       self.uiflag.set()
 304                       try:
 305                           self.cancelflag.set()
 306                       except:
 307                           pass
 308                       self.frame.Destroy()
 309               
 310               
 311               
 312               class AdvancedDownloadInfo:
 313                   def __init__(self, config, calls):
 314                       self.config = config
 315                       self.calls = calls
 316 theshadow 1.1         
 317                       self.uiflag = Event()
 318                       self.cancelflag = Event()
 319                       self.switchlock = Lock()
 320 theshadow 1.3         self.working = False
 321 theshadow 1.1         self.queue = []
 322                       wxInitAllImageHandlers()
 323                       self.thostselection = self.calls['getCurrentTHost']()
 324                       self.thostselectnum = 0
 325                       self.choices = None
 326                       self.choices1 = None
 327               
 328                       self.windowStyle = wxSYSTEM_MENU|wxCAPTION|wxMINIMIZE_BOX
 329                       if self.config['stayontop']:
 330                           self.windowStyle |= wxSTAY_ON_TOP
 331                       frame = wxFrame(None, -1, 'T-Make',
 332                                       size = wxSize(-1, -1),
 333                                       style = self.windowStyle)
 334                       self.frame = frame
 335                       panel = wxPanel(frame, -1)
 336               
 337                       fullSizer = wxFlexGridSizer(cols = 1, vgap = 0, hgap = 8)
 338                       
 339                       colSizer = wxFlexGridSizer(cols = 2, vgap = 0, hgap = 8)
 340                       leftSizer = wxFlexGridSizer(cols = 1, vgap = 3)
 341               
 342 theshadow 1.1         self.stayontop_checkbox = wxCheckBox(panel, -1, "stay on top")
 343                       self.stayontop_checkbox.SetValue(self.config['stayontop'])
 344                       EVT_CHECKBOX(frame, self.stayontop_checkbox.GetId(), self.setstayontop)
 345                       leftSizer.Add(self.stayontop_checkbox, -1, wxALIGN_CENTER)
 346                       leftSizer.Add(wxStaticText(panel, -1, ''))
 347               
 348                       button = wxButton(panel, -1, 'use image...')
 349                       EVT_BUTTON(frame, button.GetId(), self.selectDropTarget)
 350                       leftSizer.Add(button, -1, wxALIGN_CENTER)
 351                       
 352                       self.groupSizer1Box = wxStaticBox(panel, -1, '')
 353                       groupSizer1 = wxStaticBoxSizer(self.groupSizer1Box, wxHORIZONTAL)
 354                       groupSizer = wxFlexGridSizer(cols = 1, vgap = 0)
 355                       self.dropTarget = self.calls['newDropTarget']((200,200))
 356               #        self.dropTarget = self.calls['newDropTarget']()
 357                       self.dropTargetPtr = wxStaticBitmap(panel, -1, self.dropTarget)
 358                       self.calls['setDropTargetRefresh'](self.dropTargetPtr.Refresh)
 359                       self.dropTargetWidth = self.dropTarget.GetWidth()
 360                       EVT_LEFT_DOWN(self.dropTargetPtr,self.dropTargetClick)
 361                       EVT_ENTER_WINDOW(self.dropTargetPtr,self.calls['dropTargetHovered'])
 362                       EVT_LEAVE_WINDOW(self.dropTargetPtr,self.calls['dropTargetUnhovered'])
 363 theshadow 1.1         groupSizer.Add(self.dropTargetPtr,0,wxALIGN_CENTER)        
 364                       lowerSizer1 = wxGridSizer(cols = 3)
 365                       dirlink = wxStaticText(panel, -1, 'dir')
 366 theshadow 1.3         dirlink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, True))
 367 theshadow 1.1         dirlink.SetForegroundColour('blue')
 368                       EVT_LEFT_UP(dirlink,self.selectdir)
 369                       lowerSizer1.Add(dirlink, -1, wxALIGN_LEFT)
 370                       lowerSizer1.Add(wxStaticText(panel, -1, ''), -1, wxALIGN_CENTER)
 371                       filelink = wxStaticText(panel, -1, 'file')
 372 theshadow 1.3         filelink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, True))
 373 theshadow 1.1         filelink.SetForegroundColour('blue')
 374                       EVT_LEFT_UP(filelink,self.selectfile)
 375                       lowerSizer1.Add(filelink, -1, wxALIGN_RIGHT)
 376                       
 377                       groupSizer.Add(lowerSizer1, -1, wxALIGN_CENTER)
 378               
 379                       self.gauge = wxGauge(panel, -1, range = 1000,
 380                                            style = wxGA_HORIZONTAL, size = (-1,15))
 381                       groupSizer.Add(self.gauge, 0, wxEXPAND)
 382                       self.statustext = wxStaticText(panel, -1, 'ready',
 383                                           style = wxALIGN_CENTER|wxST_NO_AUTORESIZE)
 384 theshadow 1.3         self.statustext.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxBOLD, False))
 385 theshadow 1.1         groupSizer.Add(self.statustext, -1, wxEXPAND)
 386                       self.choices = wxChoice(panel, -1, (-1, -1), (self.dropTargetWidth, -1),
 387                                                   choices = [])
 388 theshadow 1.3         self.choices.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, False))
 389 theshadow 1.1         EVT_CHOICE(self.choices, -1, self.set_thost)
 390                       groupSizer.Add(self.choices, 0, wxEXPAND)
 391                       cancellink = wxStaticText(panel, -1, 'cancel')
 392 theshadow 1.3         cancellink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, True))
 393 theshadow 1.1         cancellink.SetForegroundColour('red')
 394                       EVT_LEFT_UP(cancellink,self.cancel)
 395                       groupSizer.Add(cancellink, -1, wxALIGN_CENTER)
 396                       dummyadvlink = wxStaticText(panel, -1, 'advanced')
 397 theshadow 1.3         dummyadvlink.SetFont(wxFont(7, wxDEFAULT, wxNORMAL, wxNORMAL, False))
 398 theshadow 1.1         dummyadvlink.SetForegroundColour('blue')
 399                       EVT_LEFT_UP(dirlink,self.selectdir)
 400                       groupSizer.Add(dummyadvlink, -1, wxALIGN_CENTER)
 401                       groupSizer1.Add(groupSizer)
 402                       leftSizer.Add(groupSizer1, -1, wxALIGN_CENTER)
 403               
 404                       leftSizer.Add(wxStaticText(panel, -1, 'make torrent of:'),0,wxALIGN_CENTER)
 405               
 406                       self.dirCtl = wxTextCtrl(panel, -1, '', size = (250,-1))
 407                       leftSizer.Add(self.dirCtl, 1, wxEXPAND)
 408                       
 409                       b = wxBoxSizer(wxHORIZONTAL)
 410                       button = wxButton(panel, -1, 'dir')
 411                       EVT_BUTTON(frame, button.GetId(), self.selectdir)
 412                       b.Add(button, 0)
 413               
 414                       button2 = wxButton(panel, -1, 'file')
 415                       EVT_BUTTON(frame, button2.GetId(), self.selectfile)
 416                       b.Add(button2, 0)
 417               
 418                       leftSizer.Add(b, 0, wxALIGN_CENTER)
 419 theshadow 1.1 
 420                       leftSizer.Add(wxStaticText(panel, -1, ''))
 421               
 422                       simple_link = wxStaticText(panel, -1, 'back to basic mode')
 423 theshadow 1.3         simple_link.SetFont(wxFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL, True))
 424 theshadow 1.1         simple_link.SetForegroundColour('blue')
 425                       EVT_LEFT_UP(simple_link,self.calls['switchToBasic'])
 426                       leftSizer.Add(simple_link, -1, wxALIGN_CENTER)
 427               
 428                       colSizer.Add(leftSizer, -1, wxALIGN_CENTER_VERTICAL)
 429               
 430                       gridSizer = wxFlexGridSizer(cols = 2, vgap = 6, hgap = 8)
 431               
 432                       gridSizer.Add(wxStaticText(panel, -1, 'Torrent host:'), -1,
 433                                     wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
 434               
 435                       self.choices1 = wxChoice(panel, -1, (-1, -1), (-1, -1),
 436                                                   choices = [])
 437                       EVT_CHOICE(self.choices1, -1, self.set_thost1)
 438                       gridSizer.Add(self.choices1, 0, wxEXPAND)
 439               
 440                       b = wxBoxSizer(wxHORIZONTAL)
 441                       button1 = wxButton(panel, -1, 'set default')
 442                       EVT_BUTTON(frame, button1.GetId(), self.set_default_thost)
 443                       b.Add(button1, 0)
 444                       b.Add(wxStaticText(panel, -1, '       '))
 445 theshadow 1.1         button2 = wxButton(panel, -1, 'delete')
 446                       EVT_BUTTON(frame, button2.GetId(), self.delete_thost)
 447                       b.Add(button2, 0)
 448                       b.Add(wxStaticText(panel, -1, '       '))
 449                       button3 = wxButton(panel, -1, 'save as...')
 450                       EVT_BUTTON(frame, button3.GetId(), self.save_thost)
 451                       b.Add(button3, 0)
 452               
 453                       gridSizer.Add(wxStaticText(panel, -1, ''))
 454                       gridSizer.Add(b, 0, wxALIGN_CENTER)
 455               
 456                       gridSizer.Add(wxStaticText(panel, -1, ''))
 457                       gridSizer.Add(wxStaticText(panel, -1, ''))
 458               
 459                       gridSizer.Add(wxStaticText(panel, -1, 'single tracker url:'),0,
 460                                     wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
 461                       self.annCtl = wxTextCtrl(panel, -1, 'http://my.tracker:6969/announce')
 462                       gridSizer.Add(self.annCtl, 0, wxEXPAND)
 463               
 464                       a = wxFlexGridSizer(cols = 1, vgap = 3)
 465                       a.Add(wxStaticText(panel, -1, 'tracker list:'),0,wxALIGN_RIGHT)
 466 theshadow 1.1         a.Add(wxStaticText(panel, -1, ''))
 467                       abutton = wxButton(panel, -1, 'copy\nannounces\nfrom\ntorrent', size = (70,70))
 468                       EVT_BUTTON(frame, abutton.GetId(), self.announcecopy)
 469                       a.Add(abutton, -1, wxALIGN_CENTER)
 470                       a.Add(wxStaticText(panel, -1, DROP_HERE), -1, wxALIGN_CENTER)
 471                       gridSizer.Add(a, -1, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
 472               
 473               
 474                       self.annListCtl = wxTextCtrl(panel, -1, '\n\n\n\n\n', wxPoint(-1,-1), (300,120),
 475                                                           wxTE_MULTILINE|wxHSCROLL|wxTE_DONTWRAP)
 476                       gridSizer.Add(self.annListCtl, -1, wxEXPAND)
 477               
 478                       gridSizer.Add(wxStaticText(panel, -1, ''))
 479                       exptext = wxStaticText(panel, -1,
 480                               "a list of tracker urls separated by commas or whitespace\n" +
 481                               "and on several lines -trackers on the same line will be\n" +
 482                               "tried randomly, and all the trackers on one line\n" +
 483                               "will be tried before the trackers on the next line.")
 484 theshadow 1.3         exptext.SetFont(wxFont(6, wxDEFAULT, wxNORMAL, wxNORMAL, False))
 485 theshadow 1.1         gridSizer.Add(exptext, -1, wxALIGN_CENTER)
 486               
 487                       self.refresh_thostlist()
 488                       self._set_thost()
 489               
 490                       if platform == 'win32':
 491 theshadow 1.3             self.dropTargetPtr.DragAcceptFiles(True)
 492 theshadow 1.1             EVT_DROP_FILES(self.dropTargetPtr, self.selectdrop)
 493 theshadow 1.3             self.groupSizer1Box.DragAcceptFiles(True)
 494 theshadow 1.1             EVT_DROP_FILES(self.groupSizer1Box, self.selectdrop)
 495 theshadow 1.3             abutton.DragAcceptFiles(True)
 496 theshadow 1.1             EVT_DROP_FILES(abutton, self.announcedrop)
 497 theshadow 1.3             self.annCtl.DragAcceptFiles(True)
 498 theshadow 1.1             EVT_DROP_FILES(self.annCtl, self.announcedrop)
 499 theshadow 1.3             self.annListCtl.DragAcceptFiles(True)
 500 theshadow 1.1             EVT_DROP_FILES(self.annListCtl, self.announcedrop)
 501               
 502                       gridSizer.Add(wxStaticText(panel, -1, ''))
 503                       gridSizer.Add(wxStaticText(panel, -1, ''))
 504               
 505                       gridSizer.Add(wxStaticText(panel, -1, 'piece size:'),0,
 506                                     wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
 507                       self.piece_length = wxChoice(panel, -1,
 508                                choices = ['automatic', '2MiB', '1MiB', '512KiB', '256KiB', '128KiB', '64KiB', '32KiB'])
 509                       self.piece_length_list = [0,       21,     20,      19,       18,       17,      16,      15]
 510                       self.piece_length.SetSelection(0)
 511                       gridSizer.Add(self.piece_length)
 512               
 513                       gridSizer.Add(wxStaticText(panel, -1, 'comment:'),0,
 514                                     wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)
 515                       self.commentCtl = wxTextCtrl(panel, -1, '')
 516                       gridSizer.Add(self.commentCtl, 0, wxEXPAND)
 517               
 518                       gridSizer.Add(wxStaticText(panel, -1, ''))
 519                       gridSizer.Add(wxStaticText(panel, -1, ''))
 520               
 521 theshadow 1.1         b1 = wxButton(panel, -1, 'Cancel', size = (-1, 30))
 522                       EVT_BUTTON(frame, b1.GetId(), self.cancel)
 523                       gridSizer.Add(b1, 0, wxEXPAND)
 524                       b2 = wxButton(panel, -1, 'MAKE TORRENT', size = (-1, 30))
 525                       EVT_BUTTON(frame, b2.GetId(), self.complete)
 526                       gridSizer.Add(b2, 0, wxEXPAND)
 527               
 528                       gridSizer.AddGrowableCol(1)
 529                       colSizer.Add(gridSizer, -1, wxALIGN_CENTER_VERTICAL)
 530                       fullSizer.Add(colSizer)
 531               
 532                
 533                       border = wxBoxSizer(wxHORIZONTAL)
 534                       border.Add(fullSizer, 1, wxEXPAND | wxALL, 15)
 535                       panel.SetSizer(border)
 536 theshadow 1.3         panel.SetAutoLayout(True)
 537 theshadow 1.1         border.Fit(panel)
 538                       frame.Fit()
 539 theshadow 1.3         frame.Show(True)
 540 theshadow 1.1 
 541                       EVT_INVOKE(frame, self.onInvoke)
 542                       EVT_CLOSE(frame, self._close)
 543               
 544                   def setstayontop(self, x):
 545                       if self.stayontop_checkbox.GetValue():
 546                           self.windowStyle |= wxSTAY_ON_TOP
 547                       else:
 548                           self.windowStyle &= ~wxSTAY_ON_TOP
 549                       self.frame.SetWindowStyle(self.windowStyle)
 550                       self.config['stayontop'] = self.stayontop_checkbox.GetValue()
 551               
 552                   def selectdir(self, x = None):
 553                       self.calls['dropTargetHovered']()
 554                       dl = wxDirDialog(self.frame, style = wxDD_DEFAULT_STYLE | wxDD_NEW_DIR_BUTTON)
 555                       if dl.ShowModal() == wxID_OK:
 556                           self.dirCtl.SetValue(dl.GetPath())
 557                           self.calls['dropTargetDropped']()
 558                       else:
 559                           self.calls['dropTargetUnhovered']()
 560               
 561 theshadow 1.1     def selectfile(self, x = None):
 562                       self.calls['dropTargetHovered']()
 563                       dl = wxFileDialog (self.frame, 'Choose file to use', '', '', '', wxOPEN)
 564                       if dl.ShowModal() == wxID_OK:
 565                           self.dirCtl.SetValue(dl.GetPath())
 566                           self.calls['dropTargetDropped']()
 567                       else:
 568                           self.calls['dropTargetUnhovered']()
 569               
 570                   def selectdrop(self, dat):
 571                       self.calls['dropTargetDropped']()
 572                       for f in dat.GetFiles():
 573                           self.complete(f)
 574               
 575                   def announcecopy(self, x):
 576                       dl = wxFileDialog (self.frame, 'Choose .torrent file to use', '', '', '*.torrent', wxOPEN)
 577                       if dl.ShowModal() == wxID_OK:
 578 theshadow 1.3             self._announcecopy(dl.GetPath(), True)
 579 theshadow 1.1 
 580                   def announcedrop(self, dat):
 581 theshadow 1.3         self._announcecopy(dat.GetFiles()[0], True)
 582 theshadow 1.1 
 583 theshadow 1.3     def _announcecopy(self, f, external = False):
 584 theshadow 1.1         try:
 585                           h = open(f, 'rb')
 586                           metainfo = bdecode(h.read())
 587                           h.close()
 588                           self.annCtl.SetValue(metainfo['announce'])
 589                           if metainfo.has_key('announce-list'):
 590                               list = []
 591                               for tier in metainfo['announce-list']:
 592                                   for tracker in tier:
 593                                       list += [tracker, ', ']
 594                                   del list[-1]
 595                                   list += ['\n']
 596                               liststring = ''
 597                               for i in list:
 598                                   liststring += i
 599                               self.annListCtl.SetValue(liststring+'\n\n')
 600                           else:
 601                               self.annListCtl.SetValue('')
 602                           if external:
 603                               self.choices.SetSelection(0)
 604                               self.choices1.SetSelection(0)
 605 theshadow 1.1         except:
 606                           return
 607               
 608                   def getannouncelist(self):
 609                       list = []
 610                       for t in self.annListCtl.GetValue().split('\n'):
 611                           tier = []
 612                           t = t.replace(',',' ')
 613                           for tr in t.split(' '):
 614                               if tr != '':
 615                                   tier += [tr]
 616                           if len(tier)>0:
 617                               list.append(tier)
 618                       return list
 619                   
 620                   def complete(self, x):
 621                       if not self.dirCtl.GetValue():
 622                           dlg = wxMessageDialog(self.frame, message = 'You must select a\nfile or directory', 
 623                               caption = 'Error', style = wxOK | wxICON_ERROR)
 624                           dlg.ShowModal()
 625                           dlg.Destroy()
 626 theshadow 1.1             return
 627                       if not self.annCtl.GetValue():
 628                           dlg = wxMessageDialog(self.frame, message = 'You must specify a\nsingle tracker url', 
 629                               caption = 'Error', style = wxOK | wxICON_ERROR)
 630                           dlg.ShowModal()
 631                           dlg.Destroy()
 632                           return
 633                       params = {'piece_size_pow2': self.piece_length_list[self.piece_length.GetSelection()]}
 634                       annlist = self.getannouncelist()
 635                       if len(annlist)>0:
 636                           warnings = ''
 637                           for tier in annlist:
 638                               if len(tier) > 1:
 639                                   warnings += (
 640                                       'WARNING: You should not specify multiple trackers\n' +
 641                                       '     on the same line of the tracker list unless\n' +
 642                                       '     you are certain they share peer data.\n')
 643                                   break
 644                           if not self.annCtl.GetValue() in annlist[0]:
 645                                   warnings += (
 646                                       'WARNING: The single tracker url is not present in\n' +
 647 theshadow 1.1                         '     the first line of the tracker list.  This\n' +
 648                                       '     may produce a dysfunctional torrent.\n')
 649                           if warnings:
 650                               warnings += ('Are you sure you wish to produce a .torrent\n' +
 651                                            'with these parameters?')
 652                               dlg = wxMessageDialog(self.frame,
 653                                       message = warnings,
 654                                       caption = 'Warning', style = wxYES_NO | wxICON_QUESTION)
 655                               if dlg.ShowModal() != wxID_YES:
 656                                   dlg.Destroy()
 657                                   return
 658                           params['real_announce_list'] = annlist
 659                       comment = self.commentCtl.GetValue()
 660                       if comment != '':
 661                           params['comment'] = comment
 662                       self.statustext.SetLabel('working')
 663                       self.queue.append((self.dirCtl.GetValue(), self.annCtl.GetValue(), params))
 664                       self.go_queue()
 665               
 666                   def go_queue(self):
 667                       self.switchlock.acquire()
 668 theshadow 1.1         if self.queue and not self.working:
 669 theshadow 1.3             self.working = True
 670 theshadow 1.1             self.statustext.SetLabel('working')
 671                           q = self.queue.pop(0)
 672                           MakeMetafile(q[0], q[1], q[2], self)
 673                       self.switchlock.release()
 674               
 675                   def cancel(self, x):
 676                       self.switchlock.acquire()
 677                       if self.working:
 678 theshadow 1.3             self.working = False
 679 theshadow 1.1             self.cancelflag.set()
 680                           self.cancelflag = Event()
 681                           self.queue = []
 682                           self.statustext.SetLabel('CANCELED')
 683                           self.calls['dropTargetError']()
 684                       self.switchlock.release()
 685               
 686                   def selectDropTarget(self, x):
 687                       dl = wxFileDialog (self.frame, 'Choose image to use', join(basepath,'targets'),
 688                                       join(join(basepath,'targets'), self.config['target']),
 689                                       'Supported images (*.bmp,*.gif)|*.*', wxOPEN|wxHIDE_READONLY)
 690                       if dl.ShowModal() == wxID_OK:
 691                           try:
 692                               self.calls['changeDropTarget'](dl.GetPath())
 693                               self.config['target'] = dl.GetPath()
 694                           except:
 695                               pass
 696               
 697                   def dropTargetClick(self, x):
 698                       if x.GetPosition()[0] < int(self.dropTargetWidth*0.4):
 699                           self.selectdir()
 700 theshadow 1.1         elif x.GetPosition()[0] > int(self.dropTargetWidth*0.6):
 701                           self.selectfile()
 702               
 703                   def refresh_thostlist(self):
 704                       l = []
 705                       d = 0
 706                       for f in listdir(join(basepath,'thosts')):
 707                           if f[-6:].lower() == '.thost':
 708                               l.append(f)
 709                               if f == self.thostselection:
 710                                   d = len(l)
 711                       self.choices.Clear()
 712                       self.choices.Append(' ')
 713                       self.choices1.Clear()
 714                       self.choices1.Append('---')
 715                       if not d:
 716                           if l:
 717                               self.thostselection = l[0]
 718                               d = 1
 719                           else:
 720                               self.thostselection = ''
 721 theshadow 1.1                 d = 0
 722                           self.config['thost'] = self.thostselection
 723                       for f in l:
 724                           f1 = f[:-6]
 725                           self.choices.Append(f1)
 726                           if f == self.config['thost']:
 727                               f1 += ' (default)'
 728                           self.choices1.Append(f1)
 729                       self.thostselectnum = d
 730                       self.thostlist = l
 731                       self.choices.SetSelection(d)
 732                       self.choices1.SetSelection(d)
 733               
 734                   def set_thost(self, x):
 735                       n = self.choices.GetSelection()
 736                       if n != self.thostselectnum:
 737                           self.thostselectnum = n
 738                           self.choices1.SetSelection(n)
 739                           if n:
 740                               self.thostselection = self.thostlist[n-1]
 741                               self._set_thost()
 742 theshadow 1.1 
 743                   def set_thost1(self, x):
 744                       n = self.choices1.GetSelection()
 745                       if n != self.thostselectnum:
 746                           self.thostselectnum = n
 747                           self.choices.SetSelection(n)
 748                           if n:
 749                               self.thostselection = self.thostlist[n-1]
 750                               self._set_thost()
 751               
 752                   def _set_thost(self):
 753                       self._announcecopy(join(join(basepath,'thosts'),self.thostselection))
 754                       self.calls['setCurrentTHost'](self.thostselection)
 755               
 756                   def set_default_thost(self, x):
 757                       if self.thostlist:
 758                           self.config['thost'] = self.thostselection
 759                           self.refresh_thostlist()
 760               
 761                   def save_thost(self, x):
 762                       if not self.annCtl.GetValue():
 763 theshadow 1.1             dlg = wxMessageDialog(self.frame, message = 'You must specify a\nsingle tracker url', 
 764                               caption = 'Error', style = wxOK | wxICON_ERROR)
 765                           dlg.ShowModal()
 766                           dlg.Destroy()
 767                           return
 768                       try:
 769                           metainfo = {}
 770                           metainfo['announce'] = self.annCtl.GetValue()
 771                           annlist = self.getannouncelist()
 772                           if len(annlist)>0:
 773                               warnings = ''
 774                               for tier in annlist:
 775                                   if len(tier) > 1:
 776                                       warnings += (
 777                                           'WARNING: You should not specify multiple trackers\n' +
 778                                           '     on the same line of the tracker list unless\n' +
 779                                           '     you are certain they share peer data.\n')
 780                                       break
 781                               if not self.annCtl.GetValue() in annlist[0]:
 782                                       warnings += (
 783                                           'WARNING: The single tracker url is not present in\n' +
 784 theshadow 1.1                             '     the first line of the tracker list.  This\n' +
 785                                           '     may produce a dysfunctional torrent.\n')
 786                               if warnings:
 787                                   warnings += ('Are you sure you wish to save a torrent host\n' +
 788                                                'with these parameters?')
 789                                   dlg = wxMessageDialog(self.frame,
 790                                           message = warnings,
 791                                           caption = 'Warning', style = wxYES_NO | wxICON_QUESTION)
 792                                   if dlg.ShowModal() != wxID_YES:
 793                                       dlg.Destroy()
 794                                       return
 795                               metainfo['announce-list'] = annlist
 796                           metainfo = bencode(metainfo)
 797                       except:
 798                           return
 799                       
 800                       if self.thostselectnum:
 801                           d = self.thostselection
 802                       else:
 803                           d = '.thost'
 804                       dl = wxFileDialog (self.frame, 'Save tracker data as',
 805 theshadow 1.1                            join(basepath,'thosts'), d, '*.thost',
 806                                          wxSAVE|wxOVERWRITE_PROMPT)
 807                       if dl.ShowModal() != wxID_OK:
 808                           return
 809                       d = dl.GetPath()
 810               
 811                       try:
 812                           f = open(d,'wb')
 813                           f.write(metainfo)
 814                           f.close()
 815                           garbage, self.thostselection = os.path.split(d)
 816                       except:
 817                           pass
 818                       self.refresh_thostlist()
 819               
 820                   def delete_thost(self, x):
 821                       dlg = wxMessageDialog(self.frame,
 822                               message = 'Are you sure you want to delete\n'+self.thostselection[:-6]+'?', 
 823                               caption = 'Warning', style = wxYES_NO | wxICON_EXCLAMATION)
 824                       if dlg.ShowModal() != wxID_YES:
 825                           dlg.Destroy()
 826 theshadow 1.1             return
 827                       dlg.Destroy()
 828                       os.remove(join(join(basepath,'thosts'),self.thostselection))
 829                       self.thostselection = None
 830                       self.refresh_thostlist()
 831               
 832                   def onInvoke(self, event):
 833                       if not self.uiflag.isSet():
 834                           apply(event.func, event.args, event.kwargs)
 835               
 836                   def invokeLater(self, func, args = [], kwargs = {}):
 837                       if not self.uiflag.isSet():
 838                           wxPostEvent(self.frame, InvokeEvent(func, args, kwargs))
 839               
 840                   def build_setgauge(self, x):
 841                       self.invokeLater(self.on_setgauge, [x])
 842               
 843                   def on_setgauge(self, x):
 844                       self.gauge.SetValue(int(x*1000))
 845               
 846                   def build_done(self):
 847 theshadow 1.1         self.invokeLater(self.on_builddone)
 848               
 849                   def on_builddone(self):
 850                       self.gauge.SetValue(0)
 851                       self.statustext.SetLabel('done!')
 852                       self.calls['dropTargetSuccess']()
 853 theshadow 1.3         self.working = False
 854 theshadow 1.1         self.go_queue()
 855               
 856                   def build_failed(self, e):
 857                       self.invokeLater(self.on_buildfailed, [e])
 858               
 859                   def on_buildfailed(self, e):        
 860                       self.gauge.SetValue(0)
 861                       self.statustext.SetLabel('ERROR')
 862                       self.calls['dropTargetError']()
 863 theshadow 1.3         self.working = False
 864 theshadow 1.1         self.go_queue()
 865               
 866                   def close(self):
 867                       self.cancelflag = None   # this is a planned switch, don't cancel
 868                       self.uiflag.set()
 869                       self.frame.Close()
 870               
 871                   def _close(self, x = None):
 872                       self.uiflag.set()
 873                       try:
 874                           self.cancelflag.set()
 875                       except:
 876                           pass
 877                       self.calls['saveConfig']()
 878                       self.frame.Destroy()
 879               
 880                       
 881               class MakeMetafile:
 882                   def __init__(self, d, a, params, external = None):
 883                       self.d = d
 884                       self.a = a
 885 theshadow 1.1         self.params = params
 886               
 887                       self.call = external
 888               #        self.uiflag = external.uiflag
 889                       self.uiflag = external.cancelflag
 890                       Thread(target = self.complete).start()
 891               
 892                   def complete(self):
 893                       try:
 894                           make_meta_file(self.d, self.a, self.params, self.uiflag,
 895                                           self.call.build_setgauge, progress_percent = 1)
 896                           if not self.uiflag.isSet():
 897                               self.call.build_done()
 898                       except (OSError, IOError), e:
 899                           self.failed(e)
 900                       except Exception, e:
 901                           print_exc()
 902                           self.failed(e)
 903               
 904                   def failed(self, e):
 905                       e = str(e)
 906 theshadow 1.1         self.call.build_failed(e)
 907                       dlg = wxMessageDialog(self.frame, message = 'Error - ' + e, 
 908                           caption = 'Error', style = wxOK | wxICON_ERROR)
 909                       dlg.ShowModal()
 910                       dlg.Destroy()
 911               
 912               
 913               class T_make:
 914                   def __init__(self):
 915                       self.configobj = wxConfig('BitTorrent_T-make',style=wxCONFIG_USE_LOCAL_FILE)
 916                       self.getConfig()
 917                       self.currentTHost = self.config['thost']
 918               #        self.d = AdvancedDownloadInfo(self.config, self.getCalls())
 919                       self.d = BasicDownloadInfo(self.config, self.getCalls())
 920               
 921                   def getConfig(self):
 922                       config = {}
 923                       try:
 924 theshadow 1.3             config['stayontop'] = self.configobj.ReadInt('stayontop',True)
 925 theshadow 1.1         except:
 926 theshadow 1.3             config['stayontop'] = True
 927                           self.configobj.WriteInt('stayontop',True)
 928 theshadow 1.1         try:
 929                           config['target'] = self.configobj.Read('target','default.gif')
 930                       except:
 931                           config['target'] = 'default.gif'
 932                           self.configobj.Write('target','default.gif')
 933                       try:
 934                           config['thost'] = self.configobj.Read('thost','')
 935                       except:
 936                           config['thost'] = ''
 937                           self.configobj.Write('thost','')
 938                       self.configobj.Flush()
 939                       self.config = config
 940               
 941                   def saveConfig(self):
 942                       self.configobj.WriteInt('stayontop',self.config['stayontop'])
 943                       self.configobj.Write('target',self.config['target'])
 944                       self.configobj.Write('thost',self.config['thost'])
 945                       self.configobj.Flush()
 946               
 947                   def getCalls(self):
 948                       calls = {}
 949 theshadow 1.1         calls['saveConfig'] = self.saveConfig
 950                       calls['newDropTarget'] = self.newDropTarget
 951                       calls['setDropTargetRefresh'] = self.setDropTargetRefresh
 952                       calls['changeDropTarget'] = self.changeDropTarget
 953                       calls['setCurrentTHost'] = self.setCurrentTHost
 954                       calls['getCurrentTHost'] = self.getCurrentTHost
 955                       calls['dropTargetHovered'] = self.dropTargetHovered
 956                       calls['dropTargetUnhovered'] = self.dropTargetUnhovered
 957                       calls['dropTargetDropped'] = self.dropTargetDropped
 958                       calls['dropTargetSuccess'] = self.dropTargetSuccess
 959                       calls['dropTargetError'] = self.dropTargetError
 960                       calls['switchToBasic'] = self.switchToBasic
 961                       calls['switchToAdvanced'] = self.switchToAdvanced
 962                       return calls
 963               
 964                   def setCurrentTHost(self, x):
 965                       self.currentTHost = x
 966               
 967                   def getCurrentTHost(self):
 968                       return self.currentTHost
 969               
 970 theshadow 1.1     def newDropTarget(self, wh = None):
 971                       if wh:
 972                           self.dropTarget = wxEmptyBitmap(wh[0],wh[1])
 973                           try:
 974                               self.changeDropTarget(self.config['target'])
 975                           except:
 976                               pass
 977                       else:
 978                           try:
 979                               self.dropTarget = self._dropTargetRead(self.config['target'])
 980                           except:
 981                               try:
 982                                   self.dropTarget = self._dropTargetRead('default.gif')
 983                                   self.config['target'] = 'default.gif'
 984                                   self.saveConfig()
 985                               except:
 986                                   self.dropTarget = wxEmptyBitmap(100,100)
 987                       return self.dropTarget
 988               
 989                   def setDropTargetRefresh(self, refreshfunc):
 990                       self.dropTargetRefresh = refreshfunc
 991 theshadow 1.1 
 992                   def changeDropTarget(self, new):
 993                       bmp = self._dropTargetRead(new)
 994                       w1,h1 = self.dropTarget.GetWidth(),self.dropTarget.GetHeight()
 995                       w,h = bmp.GetWidth(),bmp.GetHeight()
 996                       x1,y1 = int((w1-w)/2.0),int((h1-h)/2.0)
 997                       bbdata = wxMemoryDC()
 998                       bbdata.SelectObject(self.dropTarget)
 999                       bbdata.SetPen(wxTRANSPARENT_PEN)
1000                       bbdata.SetBrush(wxBrush(wx.wxSystemSettings_GetColour(wxSYS_COLOUR_MENU),wxSOLID))
1001                       bbdata.DrawRectangle(0,0,w1,h1)
1002                       bbdata.SetPen(wxBLACK_PEN)
1003                       bbdata.SetBrush(wxTRANSPARENT_BRUSH)
1004                       bbdata.DrawRectangle(x1-1,y1-1,w+2,h+2)
1005 theshadow 1.3         bbdata.DrawBitmap(bmp,x1,y1,True)
1006 theshadow 1.1         try:
1007                           self.dropTargetRefresh()
1008                       except:
1009                           pass
1010               
1011                   def _dropTargetRead(self, new):
1012                       a,b = os.path.split(new)
1013                       if a and a != join(basepath,'targets'):
1014                           if a != join(basepath,'targets'):
1015                               b1,b2 = os.path.splitext(b)
1016                               z = 0
1017                               while os.path.isfile(join(join(basepath,'targets'),b)):
1018                                   z += 1
1019                                   b = b1+'('+str(z)+')'+b2
1020                               shutil.copyfile(newname,join(join(basepath,'targets'),b))
1021                           new = b
1022                       name = join(join(basepath,'targets'),new)
1023                       garbage, e = os.path.splitext(new.lower())
1024                       if e == '.gif':
1025                           bmp = wxBitmap(name, wxBITMAP_TYPE_GIF)
1026                       elif e == '.bmp':
1027 theshadow 1.1             bmp = wxBitmap(name, wxBITMAP_TYPE_BMP)
1028                       else:
1029 theshadow 1.3             assert False
1030 theshadow 1.1         return bmp
1031               
1032                   def dropTargetHovered(self, x = None):
1033                       pass
1034               
1035                   def dropTargetUnhovered(self, x = None):
1036                       pass
1037               
1038                   def dropTargetDropped(self, x = None):
1039                       pass
1040               
1041                   def dropTargetSuccess(self, x = None):
1042                       pass
1043               
1044                   def dropTargetError(self, x = None):
1045                       pass
1046               
1047                   def switchToBasic(self, x = None):
1048                       self.d.close()
1049                       self.d = BasicDownloadInfo(self.config, self.getCalls())
1050                       
1051 theshadow 1.1     def switchToAdvanced(self, x = None):
1052                       self.d.close()
1053                       self.d = AdvancedDownloadInfo(self.config, self.getCalls())
1054                       
1055               
1056               
1057               class btWxApp(wxApp):
1058                   def OnInit(self):
1059                       self.APP = T_make()
1060 theshadow 1.3         return True
1061 theshadow 1.1 
1062               if __name__ == '__main__':
1063                   btWxApp().MainLoop()

No CVS admin address has been configured
Powered by
ViewCVS 0.9.3