Source

filesnake / filesnake / gui / transfers.py

Full commit
from ..pygtkhelpers.ui.objectlist import ObjectList, Column, Cell
from ..pygtkhelpers.delegates import SlaveView,ToplevelView
from ..pygtkhelpers.utils import gsignal
from gobject import GObject
import time

class TransferList(SlaveView):
    '''
    Good candidate to be the transfer controller, at least it can be
    adapted to it
    '''
    def create_ui(self):        
        listing = ObjectList([
                Column("filename", str, resizable = True),
                Column("status", str),
                Column("size", str),
                Column("complete", int, use_progress=True),
                Column("speed",str),
                Column("ETA",str),
                Column("peer", str)
                ])
        self.objectlist = listing
        self.widget.add(listing)

    def append(self, item):
        item.connect("changed", self.objectlist.update)
        self.objectlist.append(item)
        
class TransfersDialog(ToplevelView):
    
    builder_file="transfers.glade"
    
    def create_ui(self):
        
        self.transferlist = TransferList()
        self.add_slave(self.transferlist, "transferlist_cont")
    
    def on_widget__delete_event(self, w, e): 
        self.widget.hide_all()
        return True

    def add_transfer(self, name, filename, size):
        '''
        Add a new transfer and return the object connected with the GUI
        '''
        newmon = TransferMonitor(filename, size)
        newmon.peer = name
        self.transferlist.append(newmon)
        self.widget.show_all()
        return newmon

    def append(self, item):
        # Item must be a TransferMonitor
        item.connect("changed", self.objectlist.update)
        self.objectlist.append(item)
        
    def remove_completed(self):
        
        for item in self.objectlist:
            if item.completed == 100:
                self.objectlist.remove(item)


class TransferMonitor(GObject):
    '''
    This class monitors a transfer, and updates the info associated
    with the transfer, it's observed by the GUI
    '''

    gsignal("changed")

    def __init__(self, filename, size):
        super(TransferMonitor, self).__init__()
        self.filename = filename
        self.size = size  # Total size of the transfer
        self.progress = 0 # bytes transferred
        self.status = "waiting" # status of the transfer
        self.speed = 0 # Speed in byte/sec
        self.ETA = 0   # Estimate of the time
        self.complete = 0
        self._count = 0
    
    @property
    def speed(self):
        value = self._speed
        if value < 1024:
            return "{0} b/s".format(value)
        elif value > 1024 and value <  1048576:
            return "{0:.2} Kb/s".format(value/1024.0)
        elif value > 1048576:
            return "{0:.2} Mb/s".format(value/1048576.0)  
    
    @speed.setter
    def speed(self, value):
        '''
        Set speed in byte/s
        '''
        self._speed = value


    def update_speed(self):
        if not hasattr(self, "_old_progress"):
            self._old_progress = self.progress
        prog =  self.progress - self._old_progress 
        self._old_progress = self.progress
        
        self.speed = prog/self.time_interval()
        

    def time_interval(self):
        if not hasattr(self,"_prec"):
            self._prec=time.time()
            
        cur = time.time()
        
        # Avoid zero division error
        ret = cur - self._prec
        self._prec=cur
        return ret

    def producing(self,data):
        '''
        Called when the source is producing data
        '''
        chunk = len(data)
        # Checking
        if self.progress + chunk > self.size:
            raise ValueError("Producing more data that the declared one")
        
        self.progress += chunk        
        self.complete = self.progress*100/self.size 

        self._count+=1
        if self._count%100 == 0:
            self.update_speed()
            self.emit("changed")

        if self.progress == self.size:
            self.finish()
        
    def pause(self):
        '''
        Called when the source is paused
        '''
        self.status = "pause"
        
    def stop(self):
        '''
        Called when the source has stopped sending files, ungracefully
        '''
        self.status = "stop"
        
    def finish(self):
        '''
        The source has finished to do its stuff
        '''
        self.emit("changed")
        self.status = "finish"
        
def test():
    a = TransfersDialog()
    a.show()
    import gtk

    for i in range(3):
        mon = a.add_transfer("galois", "filename%d"%i, 1024)
    for i in range(100):
        mon.producing("hello")
        
    gtk.main()


if __name__ == '__main__':
    test()