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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.3