(file) Return to btdownloadgui.py CVS log (file) (dir) Up to [Development] / shadowsclient

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.3