72
|
1 import wx |
|
2 from quick_frontend.quick_contact_list import QuickContactList |
|
3 from logging import debug, info, error |
|
4 from cgi import escape |
|
5 from tools.jid import JID |
|
6 |
|
7 |
|
8 class Group(str): |
|
9 """Class used to recognize groups""" |
|
10 |
|
11 class Contact(str): |
|
12 """Class used to recognize groups""" |
|
13 |
|
14 class ContactList(wx.SimpleHtmlListBox, QuickContactList): |
|
15 """Customized control to manage contacts.""" |
|
16 |
|
17 def __init__(self, parent, host, type="JID"): |
|
18 """init the contact list |
|
19 @param parent: WxWidgets parent of the widget |
|
20 @param host: wix main app class |
|
21 @param type: type of contact list: "JID" for the usual big jid contact list |
|
22 "CUSTOM" for a customized contact list (self.__presentItem must then be overrided) |
|
23 """ |
|
24 wx.SimpleHtmlListBox.__init__(self, parent, -1) |
|
25 QuickContactList.__init__(self, host.CM) |
|
26 self.host = host |
|
27 self.type = type |
|
28 self.__typeSwitch() |
|
29 self.groups = {} #list contacts in each groups, key = group |
|
30 self.Bind(wx.EVT_LISTBOX, self.onSelected) |
|
31 self.Bind(wx.EVT_LISTBOX_DCLICK, self.onActivated) |
124
|
32 |
|
33 def __contains__(self, jid): |
|
34 return bool(self.__find_idx(jid)) |
72
|
35 |
|
36 def __typeSwitch(self): |
|
37 if self.type == "JID": |
|
38 self.__presentItem = self.__presentItemJID |
|
39 elif type != "CUSTOM": |
|
40 self.__presentItem = self.__presentItemDefault |
|
41 |
|
42 def __find_idx(self, entity): |
|
43 """Find indexes of given contact (or groups) in contact list, manage jid |
|
44 @return: list of indexes""" |
|
45 result=[] |
|
46 for i in range(self.GetCount()): |
|
47 if (type(entity) == JID and type(self.GetClientData(i)) == JID and self.GetClientData(i).short == entity.short) or\ |
|
48 self.GetClientData(i) == entity: |
|
49 result.append(i) |
|
50 return result |
|
51 |
|
52 def replace(self, contact, groups=None): |
|
53 debug(_("update %s") % contact) |
|
54 if not self.__find_idx(contact): |
|
55 self.add(contact, groups) |
|
56 else: |
|
57 for i in self.__find_idx(contact): |
|
58 self.SetString(i, self.__presentItem(contact)) |
|
59 |
|
60 def disconnect(self, contact): |
|
61 self.remove(contact) #for now, we only show online contacts |
|
62 |
|
63 def __eraseGroup(self, group): |
|
64 """Erase all contacts in group |
|
65 @param group: group to erase |
|
66 @return: True if something as been erased""" |
|
67 erased = False |
|
68 indexes = self.__find_idx(group) |
|
69 for idx in indexes: |
|
70 while idx<self.GetCount()-1 and type(self.GetClientData(idx+1)) != Group: |
|
71 erased = True |
|
72 self.Delete(idx+1) |
|
73 return erased |
|
74 |
|
75 |
|
76 def __presentGroup(self, group): |
|
77 """Make a nice presentation for the contact groups""" |
|
78 html = """-- [%s] --""" % group |
|
79 |
|
80 return html |
|
81 |
|
82 def __presentItemDefault(self, contact): |
|
83 """Make a basic presentation of string contacts in the list.""" |
|
84 return contact |
|
85 |
|
86 def __presentItemJID(self, jid): |
|
87 """Make a nice presentation of the contact in the list for JID contacts.""" |
|
88 name = self.CM.getAttr(jid,'name') |
|
89 nick = self.CM.getAttr(jid,'nick') |
|
90 show = filter(lambda x:x[0]==self.CM.getAttr(jid,'show'), const_STATUS)[0] |
|
91 #show[0]==shortcut |
|
92 #show[1]==human readable |
|
93 #show[2]==color (or None) |
|
94 show_html = "<font color='%s'>[%s]</font>" % (show[2], show[1]) if show[2] else "" |
|
95 status = self.CM.getAttr(jid,'status') or '' |
|
96 avatar = self.CM.getAttr(jid,'avatar') or IMAGE_DIR+'/empty_avatar.png' |
|
97 |
|
98 html = """ |
|
99 <table border='0'> |
|
100 <td> |
|
101 <img height='64' width='64' src='%s' /> |
|
102 </td> |
|
103 <td> |
|
104 <b>%s</b> %s<br /> |
|
105 <i>%s</i> |
|
106 </td> |
|
107 </table> |
|
108 """ % (avatar, |
|
109 escape(nick or name or jid.node or jid.short), |
|
110 show_html, |
|
111 escape(status)) |
|
112 |
|
113 return html |
|
114 |
|
115 def clear_contacts(self): |
|
116 """Clear all the contact list""" |
|
117 self.Clear() |
|
118 |
|
119 def add(self, contact, groups = None): |
|
120 """add a contact to the list""" |
|
121 debug (_("adding %s"),contact) |
|
122 #gof: groups = param_groups or self.CM.getAttr(jid, 'groups') |
|
123 if not groups: |
|
124 idx = self.Insert(self.__presentItem(contact), 0, contact) |
|
125 else: |
|
126 for group in groups: |
|
127 indexes = self.__find_idx(group) |
|
128 gp_idx = 0 |
|
129 if not indexes: #this is a new group, we have to create it |
|
130 gp_idx = self.Append(self.__presentGroup(group), Group(group)) |
|
131 else: |
|
132 gp_idx = indexes[0] |
|
133 |
|
134 self.Insert(self.__presentItem(contact), gp_idx+1, contact) |
|
135 |
|
136 |
|
137 |
|
138 def remove(self, contact): |
|
139 """remove a contact from the list""" |
|
140 debug (_("removing %s"), contact) |
|
141 list_idx = self.__find_idx(contact) |
75
|
142 list_idx.reverse() #as we make some deletions, we have to reverse the order |
72
|
143 for i in list_idx: |
|
144 self.Delete(i) |
|
145 |
|
146 def onSelected(self, event): |
|
147 """Called when a contact is selected.""" |
|
148 data = self.getSelection() |
|
149 if data == None: #we have a group |
|
150 group = self.GetClientData(self.GetSelection()) |
|
151 erased = self.__eraseGroup(group) |
|
152 if not erased: #the group was already erased, we can add again the contacts |
|
153 contacts = self.CM.getContFromGroup(group) |
|
154 contacts.sort() |
|
155 id_insert = self.GetSelection()+1 |
|
156 for contact in contacts: |
|
157 self.Insert(self.__presentItem(contact), id_insert, contact) |
|
158 self.SetSelection(wx.NOT_FOUND) |
|
159 event.Skip(False) |
|
160 else: |
|
161 event.Skip() |
|
162 |
|
163 def onActivated(self, event): |
|
164 """Called when a contact is clicked or activated with keyboard.""" |
|
165 data = self.getSelection() |
|
166 self.onActivatedCB(data) |
|
167 event.Skip() |
|
168 |
|
169 def getSelection(self): |
|
170 """Return the selected contact, or an empty string if there is not""" |
|
171 if self.GetSelection() == wx.NOT_FOUND: |
|
172 return None |
|
173 data = self.GetClientData(self.GetSelection()) |
|
174 if type(data) == Group: |
|
175 return None |
|
176 return data |
|
177 |
|
178 def registerActivatedCB(self, cb): |
|
179 """Register a callback with manage contact activation.""" |
|
180 self.onActivatedCB=cb |
|
181 |