# Written by Jie Yang # see LICENSE.txt for license information import wx from socket import inet_aton, inet_ntoa from Swapper.CacheDB.CacheDBHandler import PeerDBHandler, FriendDBHandler, PreferenceDBHandler from Swapper.utilities import friendly_time, sort_dictlist from Swapper.unicode import str2unicode from common import CommonSwapperList from managefriends import ManageFriendsPanel from Utility.constants import * DEBUG = False class TasteBuddyList(CommonSwapperList): def __init__(self, parent): self.parent = parent self.peer_db = parent.peer_db self.friend_db = parent.friend_db self.pref_db = parent.pref_db self.utility = parent.utility self.min_rank = -1 self.max_rank = 5 self.reversesort = 0 self.lastcolumnsorted = -1 style = wx.LC_REPORT|wx.LC_HRULES|wx.LC_VRULES prefix = 'buddy' minid = 0 maxid = 8 rightalign = [] centeralign = [ BUDDY_FRIEND, BUDDY_NAME, BUDDY_IP, BUDDY_SIM, BUDDY_LASTSEEN, BUDDY_NPREF, BUDDY_NCONN, BUDDY_NEXNG, ] exclude = [] self.keys = ['friend', 'name', 'ip', 'similarity', 'last_seen', 'npref', 'connected_times', 'buddycast_times'] CommonSwapperList.__init__(self, parent, style, prefix, minid, maxid, exclude, rightalign, centeralign) def getText(self, data, row, col): key = self.keys[col] original_data = data[row][key] if key == 'friend': if original_data: return '*' else: return '' if key == 'ip': try: ip = inet_ntoa(original_data) except: ip = original_data return ip if key == 'name': if original_data == '~': return 'unknown' if key == 'similarity': return '%.2f'%(original_data/1000.0) if key == 'last_seen': if original_data == 0: return '-' return friendly_time(original_data) return str2unicode(original_data) def reloadData(self): peer_list = self.peer_db.getPeerList() key = ['permid', 'name', 'ip', 'similarity', 'last_seen', 'connected_times', 'buddycast_times'] tempdata = self.peer_db.getPeers(peer_list, key) for i in xrange(len(tempdata)): if tempdata[i]['connected_times'] == 0 and tempdata[i]['buddycast_times'] == 0: tempdata[i] = None tempdata = filter(None, tempdata) self.friend_list = self.friend_db.getFriendList() self.data = [] for peer in tempdata: if peer['permid']: self.data.append(peer) for i in xrange(len(self.data)): permid = self.data[i]['permid'] if self.data[i]['name'] == '': self.data[i]['name'] = '~' self.data[i]['friend'] = permid in self.friend_list self.data[i]['npref'] = self.pref_db.getNumPrefs(permid) try: ip = inet_aton(self.data[i]['ip']) except: ip = self.data[i]['ip'] self.data[i]['ip'] = ip # for sort def OnRightClick(self, event=None): curr_idx = self.getSelectedItems() if not hasattr(self, "addFriendID"): self.addFriendID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnAddFriend, id=self.addFriendID) if not hasattr(self, "deleteFriendID"): self.deleteFriendID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnDeleteFriend, id=self.deleteFriendID) if not hasattr(self, "deletePeerID"): self.deletePeerID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnDeletePeer, id=self.deletePeerID) menu = wx.Menu() include_friend = False all_friends = True for i in curr_idx: # if all the selected peers have been friend, don't show add menu if self.data[i]['friend']: include_friend = True else: all_friends = False if not all_friends: menu.Append(self.addFriendID, "Add the peer as your friend") menu.Append(self.deletePeerID, "Delete the peer") if include_friend: menu.Append(self.deleteFriendID, "Remove the peer from your friend list") self.PopupMenu(menu, event.GetPosition()) menu.Destroy() def OnAddFriend(self, event=None): selected = self.getSelectedItems() for i in selected: self.addFriend(i) self.parent.updateFriendPanel() def addFriend(self, curr_idx): if not self.data[curr_idx]['friend']: permid = self.data[curr_idx]['permid'] self.data[curr_idx]['friend'] = True self.SetStringItem(curr_idx, 0, '*') self.friend_db.addFriend(permid) def OnDeleteFriend(self, event=None): selected = self.getSelectedItems() for i in selected: self.deleteFriend(i) self.parent.updateFriendPanel() def deleteFriend(self, curr_idx): if self.data[curr_idx]['friend']: peer = self.data[curr_idx] permid = peer['permid'] peer['friend'] = False self.SetStringItem(curr_idx, 0, '') self.friend_db.deleteFriend(permid) def externalDeleteFriend(self, permid): idx = -1 for i in xrange(len(self.data)): if self.data[i]['permid'] == permid: idx = i break if idx > 0: self.data[idx]['friend'] = False self.SetStringItem(idx, 0, '') def OnDeletePeer(self, event=None): curr_idx = self.getSelectedItems() j = 0 for i in curr_idx: permid = self.data[i-j]['permid'] if self.data[i-j]['friend']: continue self.peer_db.deletePeer(permid) self.DeleteItem(i-j) self.data.pop(i-j) j += 1 def updateView(self, friends): self.loadList(True) class TasteBuddyPanel(wx.Panel): def __init__(self, frame, parent): self.parent = parent self.frame = frame self.utility = frame.utility self.peer_db = frame.peer_db self.friend_db = frame.friend_db self.pref_db = frame.pref_db wx.Panel.__init__(self, parent, -1) colSizer = wx.BoxSizer(wx.VERTICAL) self.list = TasteBuddyList(self) colSizer.Add(self.list, 1, wx.EXPAND|wx.ALL, 5) label = wx.StaticText(self, -1, self.utility.lang.get('add_friend_notes')) colSizer.Add(label, 0, wx.ALIGN_CENTER_VERTICAL) self.SetSizer(colSizer) self.SetAutoLayout(True) #self.Fit() self.Show(True) def updateFriendPanel(self): self.frame.updateFriendPanel() def updateView(self, friends): self.list.updateView(friends) def updateColumns(self, force=False): self.list.loadList(False, False) class ABCBuddyFrame(wx.Frame): def __init__(self, parent): self.utility = parent.utility wx.Frame.__init__(self, None, -1, self.utility.lang.get('tb_buddy_short'), size=self.utility.frame.buddyFrame_size, pos=self.utility.frame.buddyFrame_pos) self.main_panel = self.createMainPanel() self.count = 0 self.loadTasteBuddyList = False self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.Bind(wx.EVT_IDLE, self.updateTasteBuddyList) self.Show() def createMainPanel(self): main_panel = wx.Panel(self) notebook = self.createNoteBook(main_panel) bot_box = self.createBottomBoxer(main_panel) mainbox = wx.BoxSizer(wx.VERTICAL) mainbox.Add(self.notebook, 1, wx.EXPAND|wx.ALL, 5) mainbox.Add(bot_box, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5) main_panel.SetSizer(mainbox) return main_panel def loadDatabase(self): self.friend_db = FriendDBHandler() self.peer_db = PeerDBHandler() self.pref_db = PreferenceDBHandler() def createNoteBook(self, main_panel): self.loadDatabase() self.notebook = wx.Notebook(main_panel, -1) self.friendsPanel = ManageFriendsPanel(self.notebook, self.utility, self) self.tasteBuddyPanel = TasteBuddyPanel(self, self.notebook) self.notebook.InsertPage(0, self.friendsPanel, self.utility.lang.get('managefriends')) self.notebook.InsertPage(1, self.tasteBuddyPanel, self.utility.lang.get('viewpeerlist')) def createBottomBoxer(self, main_panel): bot_box = wx.BoxSizer(wx.HORIZONTAL) button = wx.Button(main_panel, -1, self.utility.lang.get('close'), style = wx.BU_EXACTFIT) self.Bind(wx.EVT_BUTTON, self.OnCloseWindow, button) bot_box.Add(button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 3) return bot_box def updateMyPref(self): # used by buddy List self.myPreferencePanel.list.loadList() def updateTasteBuddyList(self, event=None): # Arno: on Linux, the list does not get painted properly before this # idle handler is called, which is weird. Hence, I wait for the next # idle event and load the filelist there. self.count += 1 if not self.loadTasteBuddyList and self.count >= 2: self.tasteBuddyPanel.list.loadList() self.Unbind(wx.EVT_IDLE) self.count = 0 def OnCloseWindow(self, event = None): self.utility.frame.buddyFrame_size = self.GetSize() self.utility.frame.buddyFrame_pos = self.GetPosition() self.utility.frame.buddyFrame = None self.utility.abcbuddyframe = None self.Destroy() def externalDeleteFriend(self, permid): # keep update if user deletes self.tasteBuddyPanel.list.externalDeleteFriend(permid) def updateFriendPanel(self): self.friendsPanel.updateView(updateBuddyFrame=False) def updateBuddyPanel(self, friends): self.tasteBuddyPanel.updateView(friends)