Mercurial > libervia-backend
comparison frontends/wix/contact_list.py @ 72:f271fff3a713
MUC implementation: first draft
/!\ the experimental muc branche of wokkel must be used
- bridge: new roomJoined signal
- wix: contact list widget is now in a separate file, and manage different kinds of presentation
- wix: chat window now manage group chat (first draft, not working yet)
- wix: constants are now in a separate class, so then can be accessible from everywhere
- wix: new menu to join room (do nothing yet, except entering in a test room)
- new plugin for xep 0045 (MUC), use wokkel experimental MUC branch
- plugins: the profile is now given for get_handler, cause it can be used internally by a plugin (e.g.: xep-0045 plugin)
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 21 Mar 2010 10:28:55 +1100 |
parents | |
children | 7322a41f8a8e |
comparison
equal
deleted
inserted
replaced
71:efe81b61673c | 72:f271fff3a713 |
---|---|
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) | |
32 | |
33 def __typeSwitch(self): | |
34 if self.type == "JID": | |
35 self.__presentItem = self.__presentItemJID | |
36 elif type != "CUSTOM": | |
37 self.__presentItem = self.__presentItemDefault | |
38 | |
39 def __find_idx(self, entity): | |
40 """Find indexes of given contact (or groups) in contact list, manage jid | |
41 @return: list of indexes""" | |
42 result=[] | |
43 for i in range(self.GetCount()): | |
44 if (type(entity) == JID and type(self.GetClientData(i)) == JID and self.GetClientData(i).short == entity.short) or\ | |
45 self.GetClientData(i) == entity: | |
46 result.append(i) | |
47 return result | |
48 | |
49 def replace(self, contact, groups=None): | |
50 debug(_("update %s") % contact) | |
51 if not self.__find_idx(contact): | |
52 self.add(contact, groups) | |
53 else: | |
54 for i in self.__find_idx(contact): | |
55 self.SetString(i, self.__presentItem(contact)) | |
56 | |
57 def disconnect(self, contact): | |
58 self.remove(contact) #for now, we only show online contacts | |
59 | |
60 def __eraseGroup(self, group): | |
61 """Erase all contacts in group | |
62 @param group: group to erase | |
63 @return: True if something as been erased""" | |
64 erased = False | |
65 indexes = self.__find_idx(group) | |
66 for idx in indexes: | |
67 while idx<self.GetCount()-1 and type(self.GetClientData(idx+1)) != Group: | |
68 erased = True | |
69 self.Delete(idx+1) | |
70 return erased | |
71 | |
72 | |
73 def __presentGroup(self, group): | |
74 """Make a nice presentation for the contact groups""" | |
75 html = """-- [%s] --""" % group | |
76 | |
77 return html | |
78 | |
79 def __presentItemDefault(self, contact): | |
80 """Make a basic presentation of string contacts in the list.""" | |
81 return contact | |
82 | |
83 def __presentItemJID(self, jid): | |
84 """Make a nice presentation of the contact in the list for JID contacts.""" | |
85 name = self.CM.getAttr(jid,'name') | |
86 nick = self.CM.getAttr(jid,'nick') | |
87 show = filter(lambda x:x[0]==self.CM.getAttr(jid,'show'), const_STATUS)[0] | |
88 #show[0]==shortcut | |
89 #show[1]==human readable | |
90 #show[2]==color (or None) | |
91 show_html = "<font color='%s'>[%s]</font>" % (show[2], show[1]) if show[2] else "" | |
92 status = self.CM.getAttr(jid,'status') or '' | |
93 avatar = self.CM.getAttr(jid,'avatar') or IMAGE_DIR+'/empty_avatar.png' | |
94 | |
95 #XXX: yes table I know :) but wxHTML* doesn't support CSS | |
96 html = """ | |
97 <table border='0'> | |
98 <td> | |
99 <img height='64' width='64' src='%s' /> | |
100 </td> | |
101 <td> | |
102 <b>%s</b> %s<br /> | |
103 <i>%s</i> | |
104 </td> | |
105 </table> | |
106 """ % (avatar, | |
107 escape(nick or name or jid.node or jid.short), | |
108 show_html, | |
109 escape(status)) | |
110 | |
111 return html | |
112 | |
113 def clear_contacts(self): | |
114 """Clear all the contact list""" | |
115 self.Clear() | |
116 | |
117 def add(self, contact, groups = None): | |
118 """add a contact to the list""" | |
119 debug (_("adding %s"),contact) | |
120 #gof: groups = param_groups or self.CM.getAttr(jid, 'groups') | |
121 if not groups: | |
122 idx = self.Insert(self.__presentItem(contact), 0, contact) | |
123 else: | |
124 for group in groups: | |
125 indexes = self.__find_idx(group) | |
126 gp_idx = 0 | |
127 if not indexes: #this is a new group, we have to create it | |
128 gp_idx = self.Append(self.__presentGroup(group), Group(group)) | |
129 else: | |
130 gp_idx = indexes[0] | |
131 | |
132 self.Insert(self.__presentItem(contact), gp_idx+1, contact) | |
133 | |
134 | |
135 | |
136 def remove(self, contact): | |
137 """remove a contact from the list""" | |
138 debug (_("removing %s"), contact) | |
139 list_idx = self.__find_idx(contact) | |
140 list_idx.reverse() #we me make some deletions, we have to reverse the order | |
141 for i in list_idx: | |
142 self.Delete(i) | |
143 | |
144 def onSelected(self, event): | |
145 """Called when a contact is selected.""" | |
146 data = self.getSelection() | |
147 if data == None: #we have a group | |
148 group = self.GetClientData(self.GetSelection()) | |
149 erased = self.__eraseGroup(group) | |
150 if not erased: #the group was already erased, we can add again the contacts | |
151 contacts = self.CM.getContFromGroup(group) | |
152 contacts.sort() | |
153 id_insert = self.GetSelection()+1 | |
154 for contact in contacts: | |
155 self.Insert(self.__presentItem(contact), id_insert, contact) | |
156 self.SetSelection(wx.NOT_FOUND) | |
157 event.Skip(False) | |
158 else: | |
159 event.Skip() | |
160 | |
161 def onActivated(self, event): | |
162 """Called when a contact is clicked or activated with keyboard.""" | |
163 data = self.getSelection() | |
164 self.onActivatedCB(data) | |
165 event.Skip() | |
166 | |
167 def getSelection(self): | |
168 """Return the selected contact, or an empty string if there is not""" | |
169 if self.GetSelection() == wx.NOT_FOUND: | |
170 return None | |
171 data = self.GetClientData(self.GetSelection()) | |
172 if type(data) == Group: | |
173 return None | |
174 return data | |
175 | |
176 def registerActivatedCB(self, cb): | |
177 """Register a callback with manage contact activation.""" | |
178 self.onActivatedCB=cb | |
179 |