Mercurial > libervia-backend
annotate frontends/src/wix/contact_list.py @ 466:448ce3c9e2ac
core: Roster cache refactoring: cache is now managed by client's SatRosterProtocol instance.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 26 Mar 2012 00:22:49 +0200 |
parents | cf005701624b |
children | 2a072735e459 |
rev | line source |
---|---|
227 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 """ | |
5 wix: a SAT frontend | |
459 | 6 Copyright (C) 2009, 2010, 2011, 2012 Jérôme Poisson (goffi@goffi.org) |
227 | 7 |
8 This program is free software: you can redistribute it and/or modify | |
9 it under the terms of the GNU General Public License as published by | |
10 the Free Software Foundation, either version 3 of the License, or | |
11 (at your option) any later version. | |
12 | |
13 This program is distributed in the hope that it will be useful, | |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 GNU General Public License for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 """ | |
21 | |
72 | 22 import wx |
227 | 23 from sat_frontends.quick_frontend.quick_contact_list import QuickContactList |
72 | 24 from logging import debug, info, error |
25 from cgi import escape | |
225
fd9b7834d98a
distutils installation script, draft
Goffi <goffi@goffi.org>
parents:
223
diff
changeset
|
26 from sat.tools.jid import JID |
366
0806a65a5fa9
wix: updated paths to use media_dir
Goffi <goffi@goffi.org>
parents:
316
diff
changeset
|
27 from os.path import join |
72 | 28 |
29 | |
199 | 30 class Group(unicode): |
72 | 31 """Class used to recognize groups""" |
32 | |
199 | 33 class Contact(unicode): |
72 | 34 """Class used to recognize groups""" |
35 | |
36 class ContactList(wx.SimpleHtmlListBox, QuickContactList): | |
37 """Customized control to manage contacts.""" | |
38 | |
39 def __init__(self, parent, host, type="JID"): | |
40 """init the contact list | |
41 @param parent: WxWidgets parent of the widget | |
42 @param host: wix main app class | |
43 @param type: type of contact list: "JID" for the usual big jid contact list | |
44 "CUSTOM" for a customized contact list (self.__presentItem must then be overrided) | |
45 """ | |
46 wx.SimpleHtmlListBox.__init__(self, parent, -1) | |
47 QuickContactList.__init__(self, host.CM) | |
48 self.host = host | |
49 self.type = type | |
50 self.__typeSwitch() | |
51 self.groups = {} #list contacts in each groups, key = group | |
366
0806a65a5fa9
wix: updated paths to use media_dir
Goffi <goffi@goffi.org>
parents:
316
diff
changeset
|
52 self.empty_avatar = join(host.media_dir, 'misc/empty_avatar') |
72 | 53 self.Bind(wx.EVT_LISTBOX, self.onSelected) |
54 self.Bind(wx.EVT_LISTBOX_DCLICK, self.onActivated) | |
124 | 55 |
56 def __contains__(self, jid): | |
57 return bool(self.__find_idx(jid)) | |
72 | 58 |
59 def __typeSwitch(self): | |
60 if self.type == "JID": | |
61 self.__presentItem = self.__presentItemJID | |
62 elif type != "CUSTOM": | |
63 self.__presentItem = self.__presentItemDefault | |
64 | |
65 def __find_idx(self, entity): | |
66 """Find indexes of given contact (or groups) in contact list, manage jid | |
67 @return: list of indexes""" | |
68 result=[] | |
69 for i in range(self.GetCount()): | |
70 if (type(entity) == JID and type(self.GetClientData(i)) == JID and self.GetClientData(i).short == entity.short) or\ | |
71 self.GetClientData(i) == entity: | |
72 result.append(i) | |
73 return result | |
74 | |
75 def replace(self, contact, groups=None): | |
76 debug(_("update %s") % contact) | |
77 if not self.__find_idx(contact): | |
78 self.add(contact, groups) | |
79 else: | |
80 for i in self.__find_idx(contact): | |
81 self.SetString(i, self.__presentItem(contact)) | |
82 | |
83 def disconnect(self, contact): | |
84 self.remove(contact) #for now, we only show online contacts | |
85 | |
86 def __eraseGroup(self, group): | |
87 """Erase all contacts in group | |
88 @param group: group to erase | |
89 @return: True if something as been erased""" | |
90 erased = False | |
91 indexes = self.__find_idx(group) | |
92 for idx in indexes: | |
93 while idx<self.GetCount()-1 and type(self.GetClientData(idx+1)) != Group: | |
94 erased = True | |
95 self.Delete(idx+1) | |
96 return erased | |
97 | |
98 | |
99 def __presentGroup(self, group): | |
100 """Make a nice presentation for the contact groups""" | |
199 | 101 html = u"""-- [%s] --""" % group |
72 | 102 |
103 return html | |
104 | |
105 def __presentItemDefault(self, contact): | |
106 """Make a basic presentation of string contacts in the list.""" | |
107 return contact | |
108 | |
109 def __presentItemJID(self, jid): | |
110 """Make a nice presentation of the contact in the list for JID contacts.""" | |
111 name = self.CM.getAttr(jid,'name') | |
112 nick = self.CM.getAttr(jid,'nick') | |
113 show = filter(lambda x:x[0]==self.CM.getAttr(jid,'show'), const_STATUS)[0] | |
114 #show[0]==shortcut | |
115 #show[1]==human readable | |
116 #show[2]==color (or None) | |
117 show_html = "<font color='%s'>[%s]</font>" % (show[2], show[1]) if show[2] else "" | |
118 status = self.CM.getAttr(jid,'status') or '' | |
366
0806a65a5fa9
wix: updated paths to use media_dir
Goffi <goffi@goffi.org>
parents:
316
diff
changeset
|
119 avatar = self.CM.getAttr(jid,'avatar') or self.empty_avatar #XXX: there is a weird bug here: if the image has an extension (i.e. empty_avatar.png), |
316
3a21d586dae4
wix: workaround a weird bug which crash wix while using empty_avatar, see comments for more information
Goffi <goffi@goffi.org>
parents:
228
diff
changeset
|
120 #WxPython segfault, and it doesn't without nothing. I couldn't reproduce the case with a basic test script, so it need further investigation before reporting it |
3a21d586dae4
wix: workaround a weird bug which crash wix while using empty_avatar, see comments for more information
Goffi <goffi@goffi.org>
parents:
228
diff
changeset
|
121 #to WxPython dev. Anyway, the program crash with a segfault, not a python exception, so there is definitely something wrong with WxPython. |
3a21d586dae4
wix: workaround a weird bug which crash wix while using empty_avatar, see comments for more information
Goffi <goffi@goffi.org>
parents:
228
diff
changeset
|
122 #The case seems to happen when SimpleHtmlListBox parse the HTML with the <img> tag |
72 | 123 |
124 html = """ | |
125 <table border='0'> | |
126 <td> | |
127 <img height='64' width='64' src='%s' /> | |
128 </td> | |
129 <td> | |
130 <b>%s</b> %s<br /> | |
131 <i>%s</i> | |
132 </td> | |
133 </table> | |
134 """ % (avatar, | |
135 escape(nick or name or jid.node or jid.short), | |
136 show_html, | |
137 escape(status)) | |
138 | |
139 return html | |
140 | |
141 def clear_contacts(self): | |
142 """Clear all the contact list""" | |
143 self.Clear() | |
144 | |
145 def add(self, contact, groups = None): | |
146 """add a contact to the list""" | |
147 debug (_("adding %s"),contact) | |
148 if not groups: | |
149 idx = self.Insert(self.__presentItem(contact), 0, contact) | |
150 else: | |
151 for group in groups: | |
152 indexes = self.__find_idx(group) | |
153 gp_idx = 0 | |
154 if not indexes: #this is a new group, we have to create it | |
155 gp_idx = self.Append(self.__presentGroup(group), Group(group)) | |
156 else: | |
157 gp_idx = indexes[0] | |
316
3a21d586dae4
wix: workaround a weird bug which crash wix while using empty_avatar, see comments for more information
Goffi <goffi@goffi.org>
parents:
228
diff
changeset
|
158 |
72 | 159 self.Insert(self.__presentItem(contact), gp_idx+1, contact) |
160 | |
161 | |
162 | |
163 def remove(self, contact): | |
164 """remove a contact from the list""" | |
165 debug (_("removing %s"), contact) | |
166 list_idx = self.__find_idx(contact) | |
75 | 167 list_idx.reverse() #as we make some deletions, we have to reverse the order |
72 | 168 for i in list_idx: |
169 self.Delete(i) | |
170 | |
171 def onSelected(self, event): | |
172 """Called when a contact is selected.""" | |
173 data = self.getSelection() | |
174 if data == None: #we have a group | |
138
2f8c86488b05
wix: scrolling is not reseted anymore when clicking on a group on contact list
Goffi <goffi@goffi.org>
parents:
125
diff
changeset
|
175 first_visible = self.GetVisibleBegin() |
72 | 176 group = self.GetClientData(self.GetSelection()) |
177 erased = self.__eraseGroup(group) | |
178 if not erased: #the group was already erased, we can add again the contacts | |
179 contacts = self.CM.getContFromGroup(group) | |
180 contacts.sort() | |
181 id_insert = self.GetSelection()+1 | |
182 for contact in contacts: | |
183 self.Insert(self.__presentItem(contact), id_insert, contact) | |
184 self.SetSelection(wx.NOT_FOUND) | |
138
2f8c86488b05
wix: scrolling is not reseted anymore when clicking on a group on contact list
Goffi <goffi@goffi.org>
parents:
125
diff
changeset
|
185 self.ScrollToLine(first_visible) |
72 | 186 event.Skip(False) |
187 else: | |
188 event.Skip() | |
189 | |
190 def onActivated(self, event): | |
191 """Called when a contact is clicked or activated with keyboard.""" | |
192 data = self.getSelection() | |
193 self.onActivatedCB(data) | |
194 event.Skip() | |
195 | |
196 def getSelection(self): | |
197 """Return the selected contact, or an empty string if there is not""" | |
198 if self.GetSelection() == wx.NOT_FOUND: | |
199 return None | |
200 data = self.GetClientData(self.GetSelection()) | |
201 if type(data) == Group: | |
202 return None | |
203 return data | |
204 | |
205 def registerActivatedCB(self, cb): | |
206 """Register a callback with manage contact activation.""" | |
207 self.onActivatedCB=cb | |
208 |