Beispiel #1
0
    def __init__(self, queue, src = None, dest = None, forceasklocation = False, caller = ""):
        self.queue = queue
        self.utility = self.queue.utility
        self.list = self.utility.list
        self.listindex = len(self.utility.torrents["all"])

        self.src = src

        self.status = TorrentStatus(self)
        self.actions = TorrentActions(self)
        self.dialogs = TorrentDialogs(self)
        self.connection = TorrentConnections(self)

        #########
        self.metainfo = self.getResponse()
        if self.metainfo is None:
            return

        # Get infohash first before doing anything else
        self.infohash = sha(bencode(self.metainfo['info'])).hexdigest()

        self.torrentconfig = TorrentConfig(self)
             
        # Check for valid windows filename
        if sys.platform == 'win32':
            fixedname = self.utility.fixWindowsName(self.metainfo['info']['name'])
            if fixedname:
                self.metainfo['info']['name'] = fixedname
        
        self.info = self.metainfo['info']

        self.title = None
                      
        # Initialize values to defaults

        self.files = TorrentFiles(self)
        
        # Setup the destination
        self.files.setupDest(dest, forceasklocation, caller)
        
        if self.files.dest is None:
            return
       
        #########

        # Priority "Normal"
        priorities = [ self.utility.lang.get('highest'), 
                       self.utility.lang.get('high'), 
                       self.utility.lang.get('normal'), 
                       self.utility.lang.get('low'), 
                       self.utility.lang.get('lowest') ]
        currentprio = self.utility.config.Read('defaultpriority', "int")
        if currentprio < 0:
            currentprio = 0
        elif currentprio >= len(priorities):
            currentprio = len(priorities) - 1
        self.prio = currentprio
       
        self.color = { 'text': None, 
                       'bgcolor': None } 
        
        # Done flag
        self.messages = { "current": "", 
                          "log": [], 
                          "timer": None }

        self.checkedonce = False
        
        self.totalpeers = "?"
        self.totalseeds = "?"
Beispiel #2
0
    def __init__(self,
                 queue,
                 src=None,
                 dest=None,
                 forceasklocation=False,
                 caller=""):
        self.queue = queue
        self.utility = self.queue.utility
        self.list = self.utility.list
        self.listindex = len(self.utility.torrents["all"])

        self.src = src

        self.status = TorrentStatus(self)
        self.actions = TorrentActions(self)
        self.dialogs = TorrentDialogs(self)
        self.connection = TorrentConnections(self)

        #########
        self.metainfo = self.getResponse()
        if self.metainfo is None:
            return

        # Get infohash first before doing anything else
        self.infohash = sha(bencode(self.metainfo['info'])).hexdigest()

        self.torrentconfig = TorrentConfig(self)

        # Check for valid windows filename
        if sys.platform == 'win32':
            fixedname = self.utility.fixWindowsName(
                self.metainfo['info']['name'])
            if fixedname:
                self.metainfo['info']['name'] = fixedname

        self.info = self.metainfo['info']

        self.title = None

        # Initialize values to defaults

        self.files = TorrentFiles(self)

        # Setup the destination
        self.files.setupDest(dest, forceasklocation, caller)

        if self.files.dest is None:
            return

        #########

        # Priority "Normal"
        priorities = [
            self.utility.lang.get('highest'),
            self.utility.lang.get('high'),
            self.utility.lang.get('normal'),
            self.utility.lang.get('low'),
            self.utility.lang.get('lowest')
        ]
        currentprio = self.utility.config.Read('defaultpriority', "int")
        if currentprio < 0:
            currentprio = 0
        elif currentprio >= len(priorities):
            currentprio = len(priorities) - 1
        self.prio = currentprio

        self.color = {'text': None, 'bgcolor': None}

        # Done flag
        self.messages = {"current": "", "log": [], "timer": None}

        self.checkedonce = False

        self.totalpeers = "?"
        self.totalseeds = "?"
Beispiel #3
0
class ABCTorrent:
    def __init__(self, queue, src = None, dest = None, forceasklocation = False, caller = ""):
        self.queue = queue
        self.utility = self.queue.utility
        self.list = self.utility.list
        self.listindex = len(self.utility.torrents["all"])

        self.src = src

        self.status = TorrentStatus(self)
        self.actions = TorrentActions(self)
        self.dialogs = TorrentDialogs(self)
        self.connection = TorrentConnections(self)

        #########
        self.metainfo = self.getResponse()
        if self.metainfo is None:
            return

        # Get infohash first before doing anything else
        self.infohash = sha(bencode(self.metainfo['info'])).hexdigest()

        self.torrentconfig = TorrentConfig(self)
             
        # Check for valid windows filename
        if sys.platform == 'win32':
            fixedname = self.utility.fixWindowsName(self.metainfo['info']['name'])
            if fixedname:
                self.metainfo['info']['name'] = fixedname
        
        self.info = self.metainfo['info']

        self.title = None
                      
        # Initialize values to defaults

        self.files = TorrentFiles(self)
        
        # Setup the destination
        self.files.setupDest(dest, forceasklocation, caller)
        
        if self.files.dest is None:
            return
       
        #########

        # Priority "Normal"
        priorities = [ self.utility.lang.get('highest'), 
                       self.utility.lang.get('high'), 
                       self.utility.lang.get('normal'), 
                       self.utility.lang.get('low'), 
                       self.utility.lang.get('lowest') ]
        currentprio = self.utility.config.Read('defaultpriority', "int")
        if currentprio < 0:
            currentprio = 0
        elif currentprio >= len(priorities):
            currentprio = len(priorities) - 1
        self.prio = currentprio
       
        self.color = { 'text': None, 
                       'bgcolor': None } 
        
        # Done flag
        self.messages = { "current": "", 
                          "log": [], 
                          "timer": None }

        self.checkedonce = False
        
        self.totalpeers = "?"
        self.totalseeds = "?"
     
    #
    # Tasks to perform when first starting adding this torrent to the display
    #
    def postInitTasks(self):        
        self.utility.torrents["all"].append(self)
        self.utility.torrents["inactive"][self] = 1
        
        # Read extra information about the torrent
        self.torrentconfig.readAll()
    
        # Add a new item to the list
        self.list.InsertStringItem(self.listindex, "")
        
        # Allow updates
        self.status.dontupdate = False
        
        # Add Status info in List
        self.updateColumns(force = True)
        
        self.updateColor()
        
        # Update the size to reflect torrents with pieces set to "download never"
        self.files.updateRealSize()
        
        # Do a quick check to see if it's finished
        self.status.isDoneUploading()

    #
    # As opposed to getColumnText,
    # this will get numbers in their raw form for doing comparisons
    # 
    # default is used when getting values for sorting comparisons
    # (this way an empty string can be treated as less than 0.0)
    #
    def getColumnValue(self, colid = None, default = 0.0):
        if colid is None:
            colid = COL_TITLE
        value = None
        
        activetorrent = self.status.isActive(checking = False, pause = False)
        
        try:
            if colid == COL_PROGRESS: # Progress
                progress = self.files.progress
                if self.status.isActive(pause = False):
                    progress = self.connection.engine.progress
                value = progress
    
            elif colid == COL_PRIO: # Priority
                value = self.prio
    
            elif colid == COL_ETA: # ETA
                if activetorrent:
                    if self.status.completed:
                        if self.connection.getSeedOption('uploadoption') == '0':
                            value = 999999999999999
                        else:
                            value = self.connection.seedingtimeleft
                    elif self.connection.engine.eta is not None:
                        value = self.connection.engine.eta
    
            elif colid == COL_SIZE: # Size
                value = self.files.floattotalsize
    
            elif colid == COL_DLSPEED: # DL Speed
                if activetorrent and not self.status.completed:
                    if self.connection.engine.hasConnections:
                        value = self.connection.engine.rate['down']
                    else:
                        value = 0.0
    
            elif colid == COL_ULSPEED: # UL Speed
                if activetorrent:
                    if self.connection.engine.hasConnections:
                        value = self.connection.engine.rate['up']
                    else:
                        value = 0.0
    
            elif colid == COL_RATIO: # %U/D Size
                if self.files.downsize == 0.0 : 
                    ratio = ((self.files.upsize/self.files.floattotalsize) * 100)
                else:
                    ratio = ((self.files.upsize/self.files.downsize) * 100)
                value = ratio
    
            elif colid == COL_SEEDS: # #Connected Seed
                if activetorrent:
                    value = self.connection.engine.numseeds
            
            elif colid == COL_PEERS: # #Connected Peer
                if activetorrent:
                    value = self.connection.engine.numpeers
            
            elif colid == COL_COPIES: # #Seeing Copies
                if (activetorrent
                    and self.connection.engine.numcopies is not None):
                    value = float(0.001*int(1000*self.connection.engine.numcopies))
            
            elif colid == COL_PEERPROGRESS: # Peer Avg Progress
                if (self.connection.engine is not None
                    and self.connection.engine.peeravg is not None):
                    value = self.connection.engine.peeravg
            
            elif colid == COL_DLSIZE: # Download Size
                value = self.files.downsize
            
            elif colid == COL_ULSIZE: # Upload Size
                value = self.files.upsize
            
            elif colid == COL_TOTALSPEED: # Total Speed
                if activetorrent:
                    value = self.connection.engine.totalspeed
            
            elif colid == COL_SEEDTIME: # Seeding time
                value = self.connection.seedingtime
            
            elif colid == COL_CONNECTIONS: # Connections
                if activetorrent:
                    value = self.connection.engine.numconnections
            
            elif colid == COL_SEEDOPTION: # Seeding option
                option = int(self.connection.getSeedOption('uploadoption'))
                if option == 0:
                    # Unlimited
                    value = 0.0
                elif option == 1:
                    text = "1." + str(self.connection.getTargetSeedingTime())
                    value = float(text)
                elif option == 2:
                    text = "1." + str(self.connection.getSeedOption('uploadratio'))
                    value = float(text)
            else:
                value = self.getColumnText(colid)
        except:
            value = self.getColumnText(colid)
            
        if value is None or value == "":
            return default
            
        return value
                
    #
    # Get the text representation of a given column's data
    # (used for display)
    #
    def getColumnText(self, colid):
        text = None
        
        activetorrent = self.status.isActive(checking = False, pause = False)
        
        try:
            if colid == COL_TITLE: # Title
                if self.title is None:
                    text = self.files.filename
                else:
                    text = self.title
                
            elif colid == COL_PROGRESS: # Progress
                progress = self.files.progress
                if self.status.isActive(pause = False):
                    progress = self.connection.engine.progress
                
                # Truncate the progress value rather than round down
                # (will show 99.9% for incomplete torrents rather than 100.0%)
                progress = int(progress * 10)/10.0
                
                text = ('%.1f' % progress) + "%"

            elif colid == COL_BTSTATUS: # BT Status
                text = self.status.getStatusText()

            elif colid == COL_PRIO: # Priority
                priorities = [ self.utility.lang.get('highest'), 
                               self.utility.lang.get('high'), 
                               self.utility.lang.get('normal'), 
                               self.utility.lang.get('low'), 
                               self.utility.lang.get('lowest') ]
                text = priorities[self.prio]

            elif colid == COL_ETA and activetorrent: # ETA
                value = None
                if self.status.completed:
                    if self.connection.getSeedOption('uploadoption') == "0":
                        text = "(oo)"
                    else:
                        value = self.connection.seedingtimeleft
                        text = "(" + self.utility.eta_value(value) + ")"
                elif self.connection.engine.eta is not None:
                    value = self.connection.engine.eta
                    text = self.utility.eta_value(value)

            elif colid == COL_SIZE: # Size                            
                # Some file pieces are set to "download never"
                if self.files.floattotalsize != self.files.realsize:
                    label = self.utility.size_format(self.files.floattotalsize, textonly = True)
                    realsizetext = self.utility.size_format(self.files.realsize, truncate = 1, stopearly = label, applylabel = False)
                    totalsizetext = self.utility.size_format(self.files.floattotalsize, truncate = 1)
                    text = realsizetext + "/" + totalsizetext
                else:
                    text = self.utility.size_format(self.files.floattotalsize)
                    
            elif (colid == COL_DLSPEED
                  and activetorrent
                  and not self.status.completed): # DL Speed
                if self.connection.engine.hasConnections:
                    value = self.connection.engine.rate['down']
                else:
                    value = 0.0
                text = self.utility.speed_format(value)

            elif colid == COL_ULSPEED and activetorrent: # UL Speed
                if self.connection.engine.hasConnections:
                    value = self.connection.engine.rate['up']
                else:
                    value = 0.0
                text = self.utility.speed_format(value)

            elif colid == COL_RATIO: # %U/D Size
                if self.files.downsize == 0.0 : 
                    ratio = ((self.files.upsize/self.files.floattotalsize) * 100)
                else:
                    ratio = ((self.files.upsize/self.files.downsize) * 100)
                text = '%.1f' % (ratio) + "%"

            elif colid == COL_MESSAGE: # Error Message
                text = self.messages["current"]
                # If the error message is a system traceback, write an error
                if text.find("Traceback") != -1:
                    sys.stderr.write(text + "\n")

            elif colid == COL_SEEDS: # #Connected Seed
                seeds = "0"
                if activetorrent:
                    seeds = ('%d' % self.connection.engine.numseeds)

                text = seeds + " (" + str(self.totalseeds) + ")"

            elif colid == COL_PEERS: # #Connected Peer
                peers = "0"
                if activetorrent:
                    peers = ('%d' % self.connection.engine.numpeers)
                    
                text = peers + " (" + str(self.totalpeers) + ")"

            elif (colid == COL_COPIES
                  and activetorrent
                  and self.connection.engine.numcopies is not None): # #Seeing Copies
                text = ('%.3f' % float(0.001*int(1000*self.connection.engine.numcopies)))

            elif (colid == COL_PEERPROGRESS
                  and activetorrent
                  and self.connection.engine.peeravg is not None): # Peer Avg Progress
                text = ('%.1f%%'%self.connection.engine.peeravg)

            elif colid == COL_DLSIZE: # Download Size
                text = self.utility.size_format(self.files.downsize)

            elif colid == COL_ULSIZE: # Upload Size
                text = self.utility.size_format(self.files.upsize)

            elif colid == COL_TOTALSPEED and activetorrent: # Total Speed
                text = self.utility.speed_format(self.connection.engine.totalspeed, truncate = 0)

            elif colid == COL_NAME: # Torrent Name
                text = os.path.split(self.src)[1]

            elif colid == COL_DEST: # Destination
                text = self.files.dest

            elif colid == COL_SEEDTIME: # Seeding time
                value = self.connection.seedingtime
                if value > 0:
                    text = self.utility.eta_value(value)

            elif colid == COL_CONNECTIONS and activetorrent: # Connections
                if self.connection.engine is not None:
                    text = ('%d' % self.connection.engine.numconnections)

            elif colid == COL_SEEDOPTION:
                value = self.connection.getSeedOption('uploadoption')
                if value == "0":
                    # Unlimited
                    text = 'oo'
                elif value == "1":
                    targettime = self.connection.getTargetSeedingTime()
                    text = self.utility.eta_value(targettime, 2)
                elif value == "2":
                    text = str(self.connection.getSeedOption('uploadratio')) + "%"
        except:
            nowactive = self.status.isActive(checking = False, pause = False)
            # Just ignore the error if it was caused by the torrent changing
            # from active to inactive
            if activetorrent != nowactive:
                # Note: if we have an error returning the text for
                #       the column used to display errors, just output
                #       to stderr, since we don't want to cause an infinite
                #       loop. 
                data = StringIO()
                print_exc(file = data)
                if colid != 13:
                    self.changeMessage(data.getvalue(), type = "error")
                else:
                    sys.stderr.write(data.getvalue())

        if text is None:
            text = ""
            
        return text

    #
    # Update multiple columns in the display
    # if columnlist is None, update all columns
    # (only visible columns will be updated)
    #
    def updateColumns(self, columnlist = None, force = False):
        if columnlist is None:
            columnlist = range(self.list.columns.minid, self.list.columns.maxid)
            
        try:
            for colid in columnlist:
                # Don't do anything if ABC is shutting down
                # or minimized
                if self.status.dontupdate or not self.utility.frame.GUIupdate:
                    return

                # Only update if this column is currently shown
                rank = self.list.columns.getRankfromID(colid)
                if (rank == -1):
                    continue
                
                text = self.getColumnText(colid)
                
                if not force:
                    # Only update if the text has changed
                    try:
                        oldtext = self.list.GetItem(self.listindex, rank).GetText()
                    except:
                        oldtext = ""
    
                    if text != oldtext:
                        force = True
                
                if force:
                    self.list.SetStringItem(self.listindex, rank, text)
        except wx.PyDeadObjectError:
            pass
               
    #
    # Update the text and background color for the torrent
    # 
    # colorString should be the name of a valid entry in
    #             the config file for a color
    #
    # force allows forcing the color update even if the values
    #       don't appear to have changed
    #       (needed when moving list items, since we're only
    #        comparing the value that we last set the color to
    #        not the acutal color of the list item to save time)
    #
#    def updateColor(self, colorString = None, force = False):
    def updateColor(self, force = False):
        # Don't do anything if ABC is shutting down
        if self.status.dontupdate:
            return

        # Don't update display while minimized/shutting down
        if not self.utility.frame.GUIupdate:
            return
        
        colorString = None
        if self.connection.engine is not None:
            colorString = self.connection.engine.color

        if colorString is None:
            colorString = 'color_startup'
        
        color = self.utility.config.Read(colorString, "color")
                    
        # Update color            
        if (self.utility.config.Read('stripedlist', "boolean")) and (self.listindex % 2):
            bgcolor = self.utility.config.Read('color_stripe', "color")
        else:
            # Use system specified background:
            bgcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)

        # Only update the color if it has changed
        # (or if the force flag is set to True)
        if (force
            or self.color['bgcolor'] is None
            or bgcolor != self.color['bgcolor']
            or self.color['text'] is None
            or color != self.color['text']):
            
            try:
                item = self.list.GetItem(self.listindex)
                item.SetTextColour(color)
                item.SetBackgroundColour(bgcolor)
                self.list.SetItem(item)
                
                self.color['text'] = color
                self.color['bgcolor'] = bgcolor
            except:
                self.color['text'] = None
                self.color['bgcolor'] = None

    #
    # Update the fields that change frequently
    # for active torrents
    #
    def updateSingleItemStatus(self):
        # Ignore 4, 5, 7, 9, 12, 13, 18, 22, 25
        
        # Do check to see if we're done uploading
        self.status.isDoneUploading()
               
        self.updateColumns([COL_PROGRESS, 
                            COL_BTSTATUS, 
                            COL_ETA, 
                            COL_DLSPEED, 
                            COL_ULSPEED, 
                            COL_SEEDS, 
                            COL_PEERS, 
                            COL_COPIES, 
                            COL_PEERPROGRESS, 
                            COL_ULSIZE, 
                            COL_TOTALSPEED, 
                            COL_NAME, 
                            COL_SEEDTIME, 
                            COL_CONNECTIONS])

        self.updateColor('color_startup')
        
    #
    # Get metainfo for the torrent
    #
    def getResponse(self):
        if self.status.isActive():
            #active process
            metainfo = self.connection.engine.dow.getResponse()
        else:
            #not active process
            metainfo = self.utility.getMetainfo(self.src)

        return metainfo

    #
    # Get information about the torrent to return to the webservice
    #
    def getInfo(self, fieldlist = None):
        # Default to returning all fields
        if fieldlist is None:
            fieldlist = range(self.list.columns.minid, self.list.columns.maxid)

        try :
            retmsg = ""

            for colid in fieldlist:
                retmsg += self.getColumnText(colid) + "|"
                       
            retmsg += self.infohash + "\n"
            
            return retmsg
        except:               
            # Should never get to this point
            return "|" * len(fieldlist) + "\n"
              
    #
    # Update the torrent with new scrape information
    #
    def updateScrapeData(self, newpeer, newseed, message = ""):
        self.actions.lastgetscrape = time()
        self.totalpeers = newpeer
        self.totalseeds = newseed
        self.updateColumns([COL_SEEDS, COL_PEERS])
        if message != "":
            print "message: " + message
            
            if message == self.utility.lang.get('scraping'):
                msgtype = "status"
            elif message == self.utility.lang.get('scrapingdone'):
                msgtype = "status"
                message += " (" + \
                           self.utility.lang.get('column14_text') + \
                           ": " + \
                           str(self.totalseeds) + \
                           " / " + \
                           self.utility.lang.get('column15_text') + \
                           ": " + \
                           str(self.totalpeers) + \
                           ")"
            else:
                msgtype = "error"
             
            self.changeMessage(message, msgtype)
        
        # Update detail window
        if self.dialogs.details is not None:
            self.dialogs.details.detailPanel.updateFromABCTorrent()
    
    def changeMessage(self, message = "", type = "clear"):       
        # Clear the error message
        if type == "clear":
            self.messages["current"] = ""
            self.updateColumns([COL_MESSAGE])
            return
        
        if not message:
            return
        
        now = time()
        self.messages["lasttime"] = now
        
        if type == "error" or type == "status":
            self.messages["current"] = strftime('%H:%M', localtime(now)) + " - " + message
            self.updateColumns([COL_MESSAGE])

        self.messages["log"].append([now, message, type])
        
        if self.dialogs.details is not None:
            self.dialogs.details.messageLogPanel.updateMessageLog()
        
    def makeInactive(self, update = True):          
        self.files.updateProgress()

        if self.status.value == STATUS_HASHCHECK:
            self.status.updateStatus(self.actions.oldstatus)
        elif self.status.value == STATUS_STOP:
            pass
        elif self.connection.engine is not None:
            # Ensure that this part only gets called once
            self.status.updateStatus(STATUS_QUEUE)
           
        # Write out to config
        self.torrentconfig.writeAll()
           
        if update:
            self.updateSingleItemStatus()

    def getTitle(self, kind = "current"):
        title = self.getColumnText(COL_TITLE)
        
        if kind == "original":
            title = self.metainfo['info']['name']
        elif kind == "torrent":
            torrentfilename = os.path.split(self.src)[1]
            torrentfilename = torrentfilename[:torrentfilename.rfind('.torrent')]
            title = torrentfilename
        elif kind == "dest":
            if self.files.isFile():
                destloc = self.files.dest
            else:
                destloc = self.files.getProcDest(pathonly = True, checkexists = False)
            title = os.path.split(destloc)[1]
        
        return title

    def changeTitle(self, title):
        if title == self.files.filename:
            self.title = None
        else:
            self.title = title
        
        self.torrentconfig.writeNameParams()
        
        self.updateColumns([COL_TITLE])
            
    # Change the priority for the torrent
    def changePriority(self, prio):
        self.prio = prio
        self.updateColumns([COL_PRIO])
        self.torrentconfig.writePriority()
       
    # Things to do when shutting down a torrent
    def shutdown(self):
        # Set shutdown flag to true
        self.status.dontupdate = True
        
        self.torrentconfig.writeAll()
        
        # Delete Detail Window
        ########################
        try:
            if self.dialogs.details is not None:
                self.dialogs.details.killAdv()
        except wx.PyDeadObjectError:
            pass

#        # (if it's currently active, wait for it to stop)
#        self.connection.stopEngine(waitForThread = True)
        self.connection.stopEngine()
        
        del self.utility.torrents["inactive"][self]
Beispiel #4
0
class ABCTorrent:
    def __init__(self,
                 queue,
                 src=None,
                 dest=None,
                 forceasklocation=False,
                 caller=""):
        self.queue = queue
        self.utility = self.queue.utility
        self.list = self.utility.list
        self.listindex = len(self.utility.torrents["all"])

        self.src = src

        self.status = TorrentStatus(self)
        self.actions = TorrentActions(self)
        self.dialogs = TorrentDialogs(self)
        self.connection = TorrentConnections(self)

        #########
        self.metainfo = self.getResponse()
        if self.metainfo is None:
            return

        # Get infohash first before doing anything else
        self.infohash = sha(bencode(self.metainfo['info'])).hexdigest()

        self.torrentconfig = TorrentConfig(self)

        # Check for valid windows filename
        if sys.platform == 'win32':
            fixedname = self.utility.fixWindowsName(
                self.metainfo['info']['name'])
            if fixedname:
                self.metainfo['info']['name'] = fixedname

        self.info = self.metainfo['info']

        self.title = None

        # Initialize values to defaults

        self.files = TorrentFiles(self)

        # Setup the destination
        self.files.setupDest(dest, forceasklocation, caller)

        if self.files.dest is None:
            return

        #########

        # Priority "Normal"
        priorities = [
            self.utility.lang.get('highest'),
            self.utility.lang.get('high'),
            self.utility.lang.get('normal'),
            self.utility.lang.get('low'),
            self.utility.lang.get('lowest')
        ]
        currentprio = self.utility.config.Read('defaultpriority', "int")
        if currentprio < 0:
            currentprio = 0
        elif currentprio >= len(priorities):
            currentprio = len(priorities) - 1
        self.prio = currentprio

        self.color = {'text': None, 'bgcolor': None}

        # Done flag
        self.messages = {"current": "", "log": [], "timer": None}

        self.checkedonce = False

        self.totalpeers = "?"
        self.totalseeds = "?"

    #
    # Tasks to perform when first starting adding this torrent to the display
    #
    def postInitTasks(self):
        self.utility.torrents["all"].append(self)
        self.utility.torrents["inactive"][self] = 1

        # Read extra information about the torrent
        self.torrentconfig.readAll()

        # Add a new item to the list
        self.list.InsertStringItem(self.listindex, "")

        # Allow updates
        self.status.dontupdate = False

        # Add Status info in List
        self.updateColumns(force=True)

        self.updateColor()

        # Update the size to reflect torrents with pieces set to "download never"
        self.files.updateRealSize()

        # Do a quick check to see if it's finished
        self.status.isDoneUploading()

    #
    # As opposed to getColumnText,
    # this will get numbers in their raw form for doing comparisons
    #
    # default is used when getting values for sorting comparisons
    # (this way an empty string can be treated as less than 0.0)
    #
    def getColumnValue(self, colid=None, default=0.0):
        if colid is None:
            colid = COL_TITLE
        value = None

        activetorrent = self.status.isActive(checking=False, pause=False)

        try:
            if colid == COL_PROGRESS:  # Progress
                progress = self.files.progress
                if self.status.isActive(pause=False):
                    progress = self.connection.engine.progress
                value = progress

            elif colid == COL_PRIO:  # Priority
                value = self.prio

            elif colid == COL_ETA:  # ETA
                if activetorrent:
                    if self.status.completed:
                        if self.connection.getSeedOption(
                                'uploadoption') == '0':
                            value = 999999999999999
                        else:
                            value = self.connection.seedingtimeleft
                    elif self.connection.engine.eta is not None:
                        value = self.connection.engine.eta

            elif colid == COL_SIZE:  # Size
                value = self.files.floattotalsize

            elif colid == COL_DLSPEED:  # DL Speed
                if activetorrent and not self.status.completed:
                    if self.connection.engine.hasConnections:
                        value = self.connection.engine.rate['down']
                    else:
                        value = 0.0

            elif colid == COL_ULSPEED:  # UL Speed
                if activetorrent:
                    if self.connection.engine.hasConnections:
                        value = self.connection.engine.rate['up']
                    else:
                        value = 0.0

            elif colid == COL_RATIO:  # %U/D Size
                if self.files.downsize == 0.0:
                    ratio = ((self.files.upsize / self.files.floattotalsize) *
                             100)
                else:
                    ratio = ((self.files.upsize / self.files.downsize) * 100)
                value = ratio

            elif colid == COL_SEEDS:  # #Connected Seed
                if activetorrent:
                    value = self.connection.engine.numseeds

            elif colid == COL_PEERS:  # #Connected Peer
                if activetorrent:
                    value = self.connection.engine.numpeers

            elif colid == COL_COPIES:  # #Seeing Copies
                if (activetorrent
                        and self.connection.engine.numcopies is not None):
                    value = float(0.001 *
                                  int(1000 * self.connection.engine.numcopies))

            elif colid == COL_PEERPROGRESS:  # Peer Avg Progress
                if (self.connection.engine is not None
                        and self.connection.engine.peeravg is not None):
                    value = self.connection.engine.peeravg

            elif colid == COL_DLSIZE:  # Download Size
                value = self.files.downsize

            elif colid == COL_ULSIZE:  # Upload Size
                value = self.files.upsize

            elif colid == COL_TOTALSPEED:  # Total Speed
                if activetorrent:
                    value = self.connection.engine.totalspeed

            elif colid == COL_SEEDTIME:  # Seeding time
                value = self.connection.seedingtime

            elif colid == COL_CONNECTIONS:  # Connections
                if activetorrent:
                    value = self.connection.engine.numconnections

            elif colid == COL_SEEDOPTION:  # Seeding option
                option = int(self.connection.getSeedOption('uploadoption'))
                if option == 0:
                    # Unlimited
                    value = 0.0
                elif option == 1:
                    text = "1." + str(self.connection.getTargetSeedingTime())
                    value = float(text)
                elif option == 2:
                    text = "1." + str(
                        self.connection.getSeedOption('uploadratio'))
                    value = float(text)
            else:
                value = self.getColumnText(colid)
        except:
            value = self.getColumnText(colid)

        if value is None or value == "":
            return default

        return value

    #
    # Get the text representation of a given column's data
    # (used for display)
    #
    def getColumnText(self, colid):
        text = None

        activetorrent = self.status.isActive(checking=False, pause=False)

        try:
            if colid == COL_TITLE:  # Title
                if self.title is None:
                    text = self.files.filename
                else:
                    text = self.title

            elif colid == COL_PROGRESS:  # Progress
                progress = self.files.progress
                if self.status.isActive(pause=False):
                    progress = self.connection.engine.progress

                # Truncate the progress value rather than round down
                # (will show 99.9% for incomplete torrents rather than 100.0%)
                progress = int(progress * 10) / 10.0

                text = ('%.1f' % progress) + "%"

            elif colid == COL_BTSTATUS:  # BT Status
                text = self.status.getStatusText()

            elif colid == COL_PRIO:  # Priority
                priorities = [
                    self.utility.lang.get('highest'),
                    self.utility.lang.get('high'),
                    self.utility.lang.get('normal'),
                    self.utility.lang.get('low'),
                    self.utility.lang.get('lowest')
                ]
                text = priorities[self.prio]

            elif colid == COL_ETA and activetorrent:  # ETA
                value = None
                if self.status.completed:
                    if self.connection.getSeedOption('uploadoption') == "0":
                        text = "(oo)"
                    else:
                        value = self.connection.seedingtimeleft
                        text = "(" + self.utility.eta_value(value) + ")"
                elif self.connection.engine.eta is not None:
                    value = self.connection.engine.eta
                    text = self.utility.eta_value(value)

            elif colid == COL_SIZE:  # Size
                # Some file pieces are set to "download never"
                if self.files.floattotalsize != self.files.realsize:
                    label = self.utility.size_format(self.files.floattotalsize,
                                                     textonly=True)
                    realsizetext = self.utility.size_format(
                        self.files.realsize,
                        truncate=1,
                        stopearly=label,
                        applylabel=False)
                    totalsizetext = self.utility.size_format(
                        self.files.floattotalsize, truncate=1)
                    text = realsizetext + "/" + totalsizetext
                else:
                    text = self.utility.size_format(self.files.floattotalsize)

            elif (colid == COL_DLSPEED and activetorrent
                  and not self.status.completed):  # DL Speed
                if self.connection.engine.hasConnections:
                    value = self.connection.engine.rate['down']
                else:
                    value = 0.0
                text = self.utility.speed_format(value)

            elif colid == COL_ULSPEED and activetorrent:  # UL Speed
                if self.connection.engine.hasConnections:
                    value = self.connection.engine.rate['up']
                else:
                    value = 0.0
                text = self.utility.speed_format(value)

            elif colid == COL_RATIO:  # %U/D Size
                if self.files.downsize == 0.0:
                    ratio = ((self.files.upsize / self.files.floattotalsize) *
                             100)
                else:
                    ratio = ((self.files.upsize / self.files.downsize) * 100)
                text = '%.1f' % (ratio) + "%"

            elif colid == COL_MESSAGE:  # Error Message
                text = self.messages["current"]
                # If the error message is a system traceback, write an error
                if text.find("Traceback") != -1:
                    sys.stderr.write(text + "\n")

            elif colid == COL_SEEDS:  # #Connected Seed
                seeds = "0"
                if activetorrent:
                    seeds = ('%d' % self.connection.engine.numseeds)

                text = seeds + " (" + str(self.totalseeds) + ")"

            elif colid == COL_PEERS:  # #Connected Peer
                peers = "0"
                if activetorrent:
                    peers = ('%d' % self.connection.engine.numpeers)

                text = peers + " (" + str(self.totalpeers) + ")"

            elif (colid == COL_COPIES and activetorrent
                  and self.connection.engine.numcopies
                  is not None):  # #Seeing Copies
                text = ('%.3f' % float(
                    0.001 * int(1000 * self.connection.engine.numcopies)))

            elif (colid == COL_PEERPROGRESS and activetorrent
                  and self.connection.engine.peeravg
                  is not None):  # Peer Avg Progress
                text = ('%.1f%%' % self.connection.engine.peeravg)

            elif colid == COL_DLSIZE:  # Download Size
                text = self.utility.size_format(self.files.downsize)

            elif colid == COL_ULSIZE:  # Upload Size
                text = self.utility.size_format(self.files.upsize)

            elif colid == COL_TOTALSPEED and activetorrent:  # Total Speed
                text = self.utility.speed_format(
                    self.connection.engine.totalspeed, truncate=0)

            elif colid == COL_NAME:  # Torrent Name
                text = os.path.split(self.src)[1]

            elif colid == COL_DEST:  # Destination
                text = self.files.dest

            elif colid == COL_SEEDTIME:  # Seeding time
                value = self.connection.seedingtime
                if value > 0:
                    text = self.utility.eta_value(value)

            elif colid == COL_CONNECTIONS and activetorrent:  # Connections
                if self.connection.engine is not None:
                    text = ('%d' % self.connection.engine.numconnections)

            elif colid == COL_SEEDOPTION:
                value = self.connection.getSeedOption('uploadoption')
                if value == "0":
                    # Unlimited
                    text = 'oo'
                elif value == "1":
                    targettime = self.connection.getTargetSeedingTime()
                    text = self.utility.eta_value(targettime, 2)
                elif value == "2":
                    text = str(
                        self.connection.getSeedOption('uploadratio')) + "%"
        except:
            nowactive = self.status.isActive(checking=False, pause=False)
            # Just ignore the error if it was caused by the torrent changing
            # from active to inactive
            if activetorrent != nowactive:
                # Note: if we have an error returning the text for
                #       the column used to display errors, just output
                #       to stderr, since we don't want to cause an infinite
                #       loop.
                data = StringIO()
                print_exc(file=data)
                if colid != 13:
                    self.changeMessage(data.getvalue(), type="error")
                else:
                    sys.stderr.write(data.getvalue())

        if text is None:
            text = ""

        return text

    #
    # Update multiple columns in the display
    # if columnlist is None, update all columns
    # (only visible columns will be updated)
    #
    def updateColumns(self, columnlist=None, force=False):
        if columnlist is None:
            columnlist = range(self.list.columns.minid,
                               self.list.columns.maxid)

        try:
            for colid in columnlist:
                # Don't do anything if ABC is shutting down
                # or minimized
                if self.status.dontupdate or not self.utility.frame.GUIupdate:
                    return

                # Only update if this column is currently shown
                rank = self.list.columns.getRankfromID(colid)
                if (rank == -1):
                    continue

                text = self.getColumnText(colid)

                if not force:
                    # Only update if the text has changed
                    try:
                        oldtext = self.list.GetItem(self.listindex,
                                                    rank).GetText()
                    except:
                        oldtext = ""

                    if text != oldtext:
                        force = True

                if force:
                    self.list.SetStringItem(self.listindex, rank, text)
        except wx.PyDeadObjectError:
            pass

    #
    # Update the text and background color for the torrent
    #
    # colorString should be the name of a valid entry in
    #             the config file for a color
    #
    # force allows forcing the color update even if the values
    #       don't appear to have changed
    #       (needed when moving list items, since we're only
    #        comparing the value that we last set the color to
    #        not the acutal color of the list item to save time)
    #
#    def updateColor(self, colorString = None, force = False):

    def updateColor(self, force=False):
        # Don't do anything if ABC is shutting down
        if self.status.dontupdate:
            return

        # Don't update display while minimized/shutting down
        if not self.utility.frame.GUIupdate:
            return

        colorString = None
        if self.connection.engine is not None:
            colorString = self.connection.engine.color

        if colorString is None:
            colorString = 'color_startup'

        color = self.utility.config.Read(colorString, "color")

        # Update color
        if (self.utility.config.Read('stripedlist',
                                     "boolean")) and (self.listindex % 2):
            bgcolor = self.utility.config.Read('color_stripe', "color")
        else:
            # Use system specified background:
            bgcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)

        # Only update the color if it has changed
        # (or if the force flag is set to True)
        if (force or self.color['bgcolor'] is None
                or bgcolor != self.color['bgcolor']
                or self.color['text'] is None or color != self.color['text']):

            try:
                item = self.list.GetItem(self.listindex)
                item.SetTextColour(color)
                item.SetBackgroundColour(bgcolor)
                self.list.SetItem(item)

                self.color['text'] = color
                self.color['bgcolor'] = bgcolor
            except:
                self.color['text'] = None
                self.color['bgcolor'] = None

    #
    # Update the fields that change frequently
    # for active torrents
    #
    def updateSingleItemStatus(self):
        # Ignore 4, 5, 7, 9, 12, 13, 18, 22, 25

        # Do check to see if we're done uploading
        self.status.isDoneUploading()

        self.updateColumns([
            COL_PROGRESS, COL_BTSTATUS, COL_ETA, COL_DLSPEED, COL_ULSPEED,
            COL_SEEDS, COL_PEERS, COL_COPIES, COL_PEERPROGRESS, COL_ULSIZE,
            COL_TOTALSPEED, COL_NAME, COL_SEEDTIME, COL_CONNECTIONS
        ])

        self.updateColor('color_startup')

    #
    # Get metainfo for the torrent
    #
    def getResponse(self):
        if self.status.isActive():
            #active process
            metainfo = self.connection.engine.dow.getResponse()
        else:
            #not active process
            metainfo = self.utility.getMetainfo(self.src)

        return metainfo

    #
    # Get information about the torrent to return to the webservice
    #
    def getInfo(self, fieldlist=None):
        # Default to returning all fields
        if fieldlist is None:
            fieldlist = range(self.list.columns.minid, self.list.columns.maxid)

        try:
            retmsg = ""

            for colid in fieldlist:
                retmsg += self.getColumnText(colid) + "|"

            retmsg += self.infohash + "\n"

            return retmsg
        except:
            # Should never get to this point
            return "|" * len(fieldlist) + "\n"

    #
    # Update the torrent with new scrape information
    #
    def updateScrapeData(self, newpeer, newseed, message=""):
        self.actions.lastgetscrape = time()
        self.totalpeers = newpeer
        self.totalseeds = newseed
        self.updateColumns([COL_SEEDS, COL_PEERS])
        if message != "":
            print "message: " + message

            if message == self.utility.lang.get('scraping'):
                msgtype = "status"
            elif message == self.utility.lang.get('scrapingdone'):
                msgtype = "status"
                message += " (" + \
                           self.utility.lang.get('column14_text') + \
                           ": " + \
                           str(self.totalseeds) + \
                           " / " + \
                           self.utility.lang.get('column15_text') + \
                           ": " + \
                           str(self.totalpeers) + \
                           ")"
            else:
                msgtype = "error"

            self.changeMessage(message, msgtype)

        # Update detail window
        if self.dialogs.details is not None:
            self.dialogs.details.detailPanel.updateFromABCTorrent()

    def changeMessage(self, message="", type="clear"):
        # Clear the error message
        if type == "clear":
            self.messages["current"] = ""
            self.updateColumns([COL_MESSAGE])
            return

        if not message:
            return

        now = time()
        self.messages["lasttime"] = now

        if type == "error" or type == "status":
            self.messages["current"] = strftime(
                '%H:%M', localtime(now)) + " - " + message
            self.updateColumns([COL_MESSAGE])

        self.messages["log"].append([now, message, type])

        if self.dialogs.details is not None:
            self.dialogs.details.messageLogPanel.updateMessageLog()

    def makeInactive(self, update=True):
        self.files.updateProgress()

        if self.status.value == STATUS_HASHCHECK:
            self.status.updateStatus(self.actions.oldstatus)
        elif self.status.value == STATUS_STOP:
            pass
        elif self.connection.engine is not None:
            # Ensure that this part only gets called once
            self.status.updateStatus(STATUS_QUEUE)

        # Write out to config
        self.torrentconfig.writeAll()

        if update:
            self.updateSingleItemStatus()

    def getTitle(self, kind="current"):
        title = self.getColumnText(COL_TITLE)

        if kind == "original":
            title = self.metainfo['info']['name']
        elif kind == "torrent":
            torrentfilename = os.path.split(self.src)[1]
            torrentfilename = torrentfilename[:torrentfilename.rfind('.torrent'
                                                                     )]
            title = torrentfilename
        elif kind == "dest":
            if self.files.isFile():
                destloc = self.files.dest
            else:
                destloc = self.files.getProcDest(pathonly=True,
                                                 checkexists=False)
            title = os.path.split(destloc)[1]

        return title

    def changeTitle(self, title):
        if title == self.files.filename:
            self.title = None
        else:
            self.title = title

        self.torrentconfig.writeNameParams()

        self.updateColumns([COL_TITLE])

    # Change the priority for the torrent
    def changePriority(self, prio):
        self.prio = prio
        self.updateColumns([COL_PRIO])
        self.torrentconfig.writePriority()

    # Things to do when shutting down a torrent
    def shutdown(self):
        # Set shutdown flag to true
        self.status.dontupdate = True

        self.torrentconfig.writeAll()

        # Delete Detail Window
        ########################
        try:
            if self.dialogs.details is not None:
                self.dialogs.details.killAdv()
        except wx.PyDeadObjectError:
            pass

#        # (if it's currently active, wait for it to stop)
#        self.connection.stopEngine(waitForThread = True)
        self.connection.stopEngine()

        del self.utility.torrents["inactive"][self]