peerlist.py :  » Network » Rufus-BitTorrent-Client » Rufus_0.7.0_src » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Rufus BitTorrent Client 
Rufus BitTorrent Client » Rufus_0.7.0_src » peerlist.py
#-----------------------------------------------------------------------------
# Name:        peerlist.py
# Purpose:     
#
# Author:      Jeremy Arendt
#
# Created:     2004/30/01
# RCS-ID:      $Id: peerlist.py,v 1.14 2005/11/30 00:57:59 inigo Exp $
# Copyright:   (c) 2002
# Licence:     See G3.LICENCE.TXT
#-----------------------------------------------------------------------------

import  locale
import wx
from wx.lib.mixins.listctrl import ColumnSorterMixin,ListCtrlAutoWidthMixin
from traceback import print_exc
from images import Images
from g3listctrl import *
from btconfig import BTConfig
import friend
import types
import sys
import re

ipaddr_re = re.compile("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") 

if sys.platform == "win32":   
    win32_flag = True
else:
    win32_flag = False

def LongIP(ip):
    address = [""] * 4
    i = 0
    for char in ip:
        if char != '.':
            address[i] += char
        else:
            i += 1
    i = 24
    
    longip = 0
    for num in address:
        longip += long(num) << i
        i -= 8
    
    return longip

        
class PeerList(G3ListCtrl, ListCtrlAutoWidthMixin, ColumnSorterMixin):
    def __init__(self, parent, btconfig, pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style = wx.LC_REPORT | wx.LC_VRULES,
                 bmps = None, friendfunc = None, colclickfunc = None, cachefunc = None):
        G3ListCtrl.__init__(self, parent, btconfig, "PeerList", -1, pos, size, style, list_type=0)
        ListCtrlAutoWidthMixin.__init__(self)
        ColumnSorterMixin.__init__(self, 14)
        self.itemDataMap = {}
        self.list_rows = {}
        self.initsort = False

        self.FriendFunc = friendfunc
        self.Colclickfunc = colclickfunc
        self.peercache = cachefunc
        self.infohash = None
        self.btconfig = btconfig    #cfg that is always in sync globably.
        self.s_config = btconfig    #cfg that can be in sync with btconfig, or with a independent session cfg
        
        self.last_options = {'reverse_dns'   : btconfig['reverse_dns'], 
                             'country_flags' : btconfig['country_flags']} 
        
        if bmps == None:
            bmps = Images()
        
        self.pl_unchoked = wx.Color(255,255,240)
            
        self.images = [1] * 4
        self.i_list = wx.ImageList(16, 16)
        mask_color = wx.Color(0,0,0)
        b_mask_color = wx.Color(0,0,0)
        self.images[0] = self.i_list.AddWithColourMask(bmps.GetImage('blank.bmp'), b_mask_color)
        self.images[1] = self.i_list.AddWithColourMask(bmps.GetImage('usergreen.png'), mask_color)
        self.images[2] = self.i_list.AddWithColourMask(bmps.GetImage('userblue.png'), mask_color)
        self.images[3] = self.i_list.AddWithColourMask(bmps.GetImage('userred.png'), mask_color)

        self.flags = {}
        flag_bmps = bmps.GetImage('flags')
        for key, flag in flag_bmps.items():
            try:
                self.flags[key] = self.i_list.AddIcon(flag)
            except:
                self.flags[key] = self.i_list.AddIcon(flag_bmps['checkered'])

        self.flags['edu'] = self.i_list.AddIcon(flag_bmps['checkered'])
        self.flags['org'] = self.i_list.AddIcon(flag_bmps['checkered'])
        self.flags['us'] = self.i_list.AddIcon(flag_bmps['us'])
        self.flags['gov'] = self.i_list.AddIcon(flag_bmps['us'])
        self.flags['com'] = self.i_list.AddIcon(flag_bmps['us'])
        self.flags['net'] = self.i_list.AddIcon(flag_bmps['us'])

        self.SetImageList(self.i_list, wx.IMAGE_LIST_SMALL)

        self.col2sort = 1
        self.ascending = False
        
        cols = [ [True, _("Peer IP Addresses"), wx.LIST_FORMAT_LEFT, wx.LIST_AUTOSIZE_USEHEADER],
                 [True, _("KB/s Dn"), wx.LIST_FORMAT_RIGHT, wx.LIST_AUTOSIZE_USEHEADER],
                 [True, _("KB/s Up"), wx.LIST_FORMAT_RIGHT, wx.LIST_AUTOSIZE_USEHEADER],
                 [True, "%", wx.LIST_FORMAT_RIGHT, 45],
                 [True, _("Progress"), wx.LIST_FORMAT_LEFT, 60],
                 [True, _("Downloaded"), wx.LIST_FORMAT_RIGHT, 75],
                 [True, _("Uploaded"), wx.LIST_FORMAT_RIGHT, 75],
                 [True, _("Initiation"), wx.LIST_FORMAT_LEFT, wx.LIST_AUTOSIZE_USEHEADER],
                 [True, _("Client Type"), wx.LIST_FORMAT_LEFT, 80],
                 [True, _("Name"), wx.LIST_FORMAT_LEFT, 73],
                 [True, _("Send"), wx.LIST_FORMAT_LEFT, 80],
                 [True, _("Recv"), wx.LIST_FORMAT_LEFT, 80],
                 [True, _("Raw Peerid"), wx.LIST_FORMAT_LEFT, wx.LIST_AUTOSIZE_USEHEADER],
                 [True, "", wx.LIST_FORMAT_LEFT, wx.LIST_AUTOSIZE_USEHEADER]

            ]

        self.InsertColumns(cols)
        self.SetEbedCol(4)
      
        wx.EVT_LIST_COL_CLICK(self, -1, self.OnColClick)
        wx.EVT_COMMAND_RIGHT_CLICK(self, -1, self.OnRightClick) # wxMSW
        wx.EVT_RIGHT_UP(self, self.OnRightClick) # wxGTK      

    def SetColSort(self, data): #used to remember what column sort was set to between tab/torrent switches
        col, ascending = data
        if col != None and ascending != None: #if both set to None user switched between tabs only
            self.col2sort = col
            self.ascending = ascending
        self.initsort = False

    def GetColSort(self): #returns number of sorted col and whether it is ascending or not
      return (self.col2sort, self.ascending)

    def OnSortToggle(self, event):
        self.s_config['sort_list'] = not self.s_config['sort_list']
    
    def OnDnsToggle(self, event):
        if self.s_config['reverse_dns']:
            self.s_config['reverse_dns'] = False
            self.s_config['country_flags'] = False
        else:
            self.s_config['reverse_dns'] = True
        self.FillRows()
            
    def OnFlagsToggle(self, event):
        if self.s_config['country_flags']:
            self.s_config['country_flags'] = False
        else:
            self.s_config['country_flags'] = True
            self.s_config['reverse_dns'] = True
        self.FillRows()
        
    
    def OnRightClick(self, event):
        self.selected_index = self.GetFirstSelected()
        if not hasattr(self, "popupID1"):   
            self.popupID1 = wx.NewId()
            self.popupID2 = wx.NewId()
            self.popupID3 = wx.NewId()
            self.popupID4 = wx.NewId()
            self.popupID5 = wx.NewId()
            self.popupID6 = wx.NewId()
            wx.EVT_MENU(self, self.popupID1, self.OnSortToggle)
            wx.EVT_MENU(self, self.popupID2, self.OnDnsToggle)
            wx.EVT_MENU(self, self.popupID3, self.OnCBCopy)
            wx.EVT_MENU(self, self.popupID4, self.OnMakeTempFriend)
            wx.EVT_MENU(self, self.popupID5, self.OnMakeTempFoe)
            wx.EVT_MENU(self, self.popupID6, self.OnFlagsToggle)

        menu = wx.Menu()
        menu.Append(self.popupID4, _("Give peer upload preference"), _("Give upload preference to this peer"), True)
        menu.Append(self.popupID5, _("Never upload to this peer"), _("Never upload to this peer"), True)
        menu.AppendSeparator()
        menu.Append(self.popupID1, _("Keep Sorted"), _("Enable/Disable realtime sorting"), True)
        menu.Append(self.popupID2, _("Reverse Dns"), _("Show full addresses where avaiable"), True)
        menu.Append(self.popupID6, _("Show Country Flags"), _("Show country flags where avaiable"), True)
        menu.Append(self.popupID3, _("Copy address"), _("Copy selected address to clipboard"))
        
        if self.s_config['sort_list']:
            menu.Check(self.popupID1, True)
        if self.s_config['reverse_dns']:
            menu.Check(self.popupID2, True)
        if self.s_config['country_flags']:
            menu.Check(self.popupID6, True)
            
        self.PopupMenu(menu, self.ScreenToClient(wx.GetMousePosition()))
        menu.Destroy()

    
    def OnMakeTempFriend(self, event):
        if self.FriendFunc == None:
            return

        if self.selected_index != -1:
            data = self.itemDataMap.get( self.GetItemData(self.selected_index) )
            if data != None:
                #ip, peerid, ADDFRIENDTEMP, (port, infohash)
                self.FriendFunc(data[13], data[15], friend.ADDFRIENDTEMP, (data[13], self.infohash))
                if self.ReChoke:
                    self.ReChoke()
                    
        del self.selected_index
        
    def OnMakeTempFoe(self, event):
        if self.FriendFunc == None:
            return

        if self.selected_index != -1:
            data = self.itemDataMap.get( self.GetItemData(self.selected_index) )
            if data != None:
                #ip, peerid, ADDFOETEMP, temp:True
                self.FriendFunc(data[13], data[9], friend.ADDFOETEMP, True)
                if self.ReChoke:
                    self.ReChoke()
        del self.selected_index
        
        
    def OnCBCopy(self, event):
        msg = ""
        index = self.GetFirstSelected()
        while index != -1:
            data = self.itemDataMap.get( self.GetItemData(index) )
            if data != None:
                msg += data[0] + '\n'
            index = self.GetNextSelected(index)

        if len(msg) > 0:
            wx.TheClipboard.Open()
            wx.TheClipboard.SetData(wx.TextDataObject(msg))
            wx.TheClipboard.Close()

    def OnColClick(self, event):
        col = self.GetLogicalColumn( event.GetColumn() )
        if self.col2sort != col:
            self.ascending = False
        else:
            self.ascending = not self.ascending
        self.col2sort = col
        try:
            self.SortListItems(self.col2sort, self.ascending)
        except IndexError:
            pass

        if self.Colclickfunc != None:
            self.Colclickfunc(col, self.ascending)

    # Sort by first col in tie situations
    def GetSecondarySortValues(self, col, key1, key2):
        item1 = self.itemDataMap[key1][0]
        item2 = self.itemDataMap[key2][0]
        return (item1, item2)

    def GetColumnSorter(self):
        return self.CustColumnSorter

    #Custom sorter needed to correctly sort IP addresses
    def CustColumnSorter(self, key1, key2):
        col = self._col
        ascending = self._colSortFlag[col]
        item1 = self.itemDataMap[key1][col]
        item2 = self.itemDataMap[key2][col]

        #if IP addresses convert to Long to enable correct sorting
        if ipaddr_re.match(str(item1)) != None and ipaddr_re.match(str(item2)) != None:
            item1 = LongIP(item1)
            item2 = LongIP(item2)

        cmpVal = cmp(item1, item2)

        # If the items are equal then pick something else to make the sort value unique
        if cmpVal == 0:
            cmpVal = apply(cmp, self.GetSecondarySortValues(col, key1, key2))

        if ascending:
            return cmpVal
        else:
            return -cmpVal

    def GetListCtrl(self):
        return self
    
    def Reset(self):
        self.list_rows = {}
        if self.GetItemCount() != 0:
            self.DeleteAllItems()
            self.Refresh(True)
            self.Update()
    
    def Populate(self, spew = [], infohash = None, rechokefunc = None, s_config=None):
        if spew == None:
            return
        
        if len(spew) == 0:
            self.Reset()
            return
        
        refresh_all = False
        
        if s_config != None:
            if s_config is not self.s_config:
                self.s_config = s_config
                refresh_all = True
        else:
            s_config = self.s_config

        if not refresh_all and (s_config['country_flags'] != self.last_options['country_flags'] or \
                s_config['reverse_dns'] != self.last_options['reverse_dns']):

            self.last_options = {'reverse_dns': s_config['reverse_dns'], 
                             'country_flags'  : s_config['country_flags']}
            refresh_all = True
            
        
        # Optimization. Map current keys to existing indices
        self.MapKey2Idx(self.itemDataMap)      
                       
        completed_color = wx.Color(0,150,0)
        old_list_rows = self.list_rows
        self.list_rows = {}
        self.itemDataMap = {}
        self.infohash = infohash
        self.ReChoke = rechokefunc
        
        # Generate itemDataMap
        i = 0
        for c in spew:
            ip = c['ip']
            peer_id = c['peerid']

            peer_info = self.peercache(ip, peer_id)

            if self.peercache != None and s_config['reverse_dns'] and peer_info[0] != None:
                address = peer_info[0]
            else:
                address = ip

            if type(address) == types.StringType:
                address = address.lower()

            iurate, uinterested, uchoked = c['upload']
            idrate, dinterested, dchoked, dsnubbed = c['download']
            icompleted = c['completed']
            
#            peer_info[1] = peer_info[1] + c['utotal']
#            iutotal = peer_info[1]
            iutotal = c['utotal']
            
#            peer_info[2] = peer_info[2] + c['dtotal']
#            idtotal = peer_info[2]
            idtotal = c['dtotal']

            initiation = c['initiation']
            client_type = peer_info[3]
            peer_name = peer_info[4]
            raw_peerid = peer_info[5]

            port = c['port']
            have_bitfield = c['havelist']
            
            last_send = c['last_send']
            last_recv = c['last_recv']
            
            if iutotal > 0:
                utotal = str(iutotal / (1024)) + 'KB'
            else:
                utotal = ''

            if idtotal > 0:
                dtotal = str(idtotal / (1024)) + 'KB'
            else:
                dtotal = ''

            if idrate > 0 and not dchoked and not dsnubbed:
                drate = "%0.1f" % (float(idrate)/1024)
            else:
                idrate = 0
                drate = ''

            if iurate > 0 and not uchoked:
                urate = "%0.1f" % (float(iurate)/1024)
            else:
                iurate = 0
                urate = ''

            completed = "%d%c" % (int(icompleted*100), '%')

            key = hash(peer_id)
            
            self.itemDataMap[key] = [address, idrate, iurate, icompleted, icompleted,
                            idtotal, iutotal, initiation, client_type, peer_name, last_send, last_recv, raw_peerid , ip, port, peer_id, have_bitfield, uchoked]
                
            self.list_rows[key] = [key, address, drate, urate, completed, "              ",
                            dtotal, utotal, initiation, client_type, peer_name, last_send, last_recv, raw_peerid, ""]


        # Fill list with itemDataMap, cmp with old_list_rows
        self.FillRows(old_list_rows, refresh_all)

        #delete list items that are not current
        deleted = False
        if self.GetItemCount() != len(self.itemDataMap):
            self.Freeze()
            item = self.GetNextItem(-1)
            i = 0
            
            while i < self.GetItemCount() and item != -1:
                nextitem = self.GetNextItem(item)
                key = self.GetItemData(item)
                
                if self.itemDataMap.has_key(key) == False:
                    self.DeleteItem(item)
                    deleted = True
                else:
                    item = nextitem
                    i+=1
            self.Thaw()

        if not self.initsort: #inital sort on selection of torrent in master list
            try:
                self.initsort = True
                self.SortListItems(self.col2sort, self.ascending)
            except IndexError:
                pass

        if s_config['sort_list'] and len(self.itemDataMap) > 1 and not deleted:
            try:
                self.SortListItems(self.col2sort, self.ascending)
            except IndexError:
                pass
            
        if not win32_flag:
            self.OnPaint()
    
    def FillRows(self, old_list_rows={}, refresh_all=True):
        # Fill list with itemDataMap, cmp with old_list_rows
        for key, rowdata in self.list_rows.items():
            data = self.itemDataMap[key]
            
            if refresh_all or (not old_list_rows.has_key(key) or (self.list_rows[key] != old_list_rows[key])):
                #item_idx = self.InsertRow_Fast(key, rowdata[1:])
                item_idx = self.InsertRow(key, rowdata[1:])
                self.Insert_Ebed_Ctrl(key, data[4], data[16])
            
                item = self.GetItem(item_idx)
                item.m_mask = wx.LIST_MASK_IMAGE
                
                idtotal = data[5]
                iutotal = data[6]
                uchoked = data[17]
                
                if self.s_config['country_flags'] and self.s_config['reverse_dns']:
                    tld = data[0].split('.')
                    tld = tld[len(tld)-1]
                    if self.flags.has_key(tld):
                        if item.m_image != self.flags[tld]:
                            item.m_image = self.flags[tld]
                    else:
                        item.m_image = self.images[0]
                else:
                    if idtotal > iutotal:
                        if item.m_image != self.images[1]:
                            item.m_image = self.images[1]
                    elif idtotal == iutotal:
                        if item.m_image != self.images[2]:
                            item.m_image = self.images[2]
                    elif idtotal < iutotal:
                        if item.m_image != self.images[3]:
                            item.m_image = self.images[3]
            
                if not uchoked:
                    item.SetBackgroundColour(self.pl_unchoked )
                else:
                    item.SetBackgroundColour(self.bg_color)
                self.SetItem(item)
        
    
#---------------------------------------------------------------------------  

class TestList(wx.Frame):
    def __init__(self):
        from threading import Event
        from peerlistcache import PeerListCache
        wx.Frame.__init__(self, None, -1, 'Test', size = wx.Size(600, 600), style = wx.DEFAULT_FRAME_STYLE)
        panel = wx.Panel(self, -1)

        self.doneflag = Event()
        self.pl_dnsloop = PeerListCache(self.doneflag)

        self.ppp = PeerList(panel, BTConfig(), cachefunc=self.pl_dnsloop.GetPeerInfo)
        self.ppp.SetEbedCol(4)
        testbutton1 = wx.Button(panel, 100, "test1")
        testbutton2 = wx.Button(panel, 101, "test2")
        wx.EVT_BUTTON(self, 100, self.OnClick1)
        wx.EVT_BUTTON(self, 101, self.OnClick2)

        wx.EVT_CLOSE(self, self.OnClose)

        sizer = wx.FlexGridSizer(cols=1)
        sizer.Add(self.ppp, 1, wx.EXPAND)
        sizer.AddGrowableRow(0)
        sizer.AddGrowableCol(0)
        sizer.Add(testbutton1, 1)
        sizer.Add(testbutton2, 1)
        panel.SetSizer(sizer)
        panel.Layout()
        self.Show(True)
        self.OnInit()

    def OnInit(self):            
        self.pl_dnsloop.Start()

    def OnClose(self, event):
            self.doneflag.set()
            self.pl_dnsloop.Stop()

    def OnClick2(self, event):
        spew = []
        c = {}

        for i in range(0, 2):
            c = {'ip' : '%d' % i,
                'upload': [1, 1, 1],
                'download': [1 % 2, i % 3, i % 4, i % 5],
                'completed': 1.0,
                'utotal': 5000,
                'dtotal': 1000,
                'initiation': 'local',
                'peerid': 'peerid1 %d' %i,
                'port': 700,
                'havelist': [1,1,1,1,1,1,1,1,1,1,1,1],
                'last_send': "",
                'last_recv': "",                
                }
            spew.append(c)
            
        self.ppp.Populate(spew)
                
    def OnClick1(self, event):
        import time
        t = time.time()
        spew = []
        c = {}

        for i in range(0, 500):
            if i % 10: #send/recv data sim
                data1 = "choke"
                data2 = "unchoke"
            else:
                data1 = "unchoke"
                data2 = "choke"

            c = {'ip' : '%d' % i,
                'upload': [0, 0, 0],
                'download': [1 % 3, i % 4, i % 5, i % 6],
                'completed': float(i)/(100),
                'utotal': 0,
                'dtotal': 0,
                'initiation': 'local',
                'peerid': 'peerid2 %d' %i,
                'port': 7013,
                'havelist': [0,1,0,1,0,1,0,1,0,1,0],
                'last_send': data1,
                'last_recv': data2,
                }
            spew.append(c)
        
        self.ppp.Populate(spew)
##        self.ppp.Reset()
##        self.ppp.Populate(spew)
        
        print time.time() - t
        
        
if __name__ == "__main__":
    _ = lambda x: x # needed for gettext
    app = wx.PySimpleApp()
    ppp = TestList()   
    ppp.Show(True)
    app.MainLoop()

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.