Mercurial > libervia-web
comparison src/browser/sat_browser/contact_list.py @ 589:a5019e62c3e9 frontends_multi_profiles
browser side: big refactoring to base Libervia on QuickFrontend, first draft:
/!\ not finished, partially working and highly instable
- add collections module with an OrderedDict like class
- SatWebFrontend inherit from QuickApp
- general sat_frontends tools.jid module is used
- bridge/json methods have moved to json module
- UniBox is partially removed (should be totally removed before merge to trunk)
- Signals are now register with the generic registerSignal method (which is called mainly in QuickFrontend)
- the generic getOrCreateWidget method from QuickWidgetsManager is used instead of Libervia's specific methods
- all Widget are now based more or less directly on QuickWidget
- with the new QuickWidgetsManager.getWidgets method, it's no more necessary to check all widgets which are instance of a particular class
- ChatPanel and related moved to chat module
- MicroblogPanel and related moved to blog module
- global and overcomplicated send method has been disabled: each class should manage its own sending
- for consistency with other frontends, former ContactPanel has been renamed to ContactList and vice versa
- for the same reason, ChatPanel has been renamed to Chat
- for compatibility with QuickFrontend, a fake profile is used in several places, it is set to C.PROF_KEY_NONE (real profile is managed server side for obvious security reasons)
- changed default url for web panel to SàT website, and contact address to generic SàT contact address
- ContactList is based on QuickContactList, UI changes are done in update method
- bride call (now json module) have been greatly improved, in particular call can be done in the same way as for other frontends (bridge.method_name(arg1, arg2, ..., callback=cb, errback=eb). Blocking method must be called like async methods due to javascript architecture
- in bridge calls, a callback can now exists without errback
- hard reload on BridgeSignals remote error has been disabled, a better option should be implemented
- use of constants where that make sens, some style improvments
- avatars are temporarily disabled
- lot of code disabled, will be fixed or removed before merge
- various other changes, check diff for more details
server side: manage remote exception on getEntityData, removed getProfileJid call, added getWaitingConf, added getRoomsSubjects
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 24 Jan 2015 01:45:39 +0100 |
parents | src/browser/sat_browser/contact.py@668bb04e9708 |
children | c66f7227848e |
comparison
equal
deleted
inserted
replaced
585:bade589dbd5a | 589:a5019e62c3e9 |
---|---|
1 #!/usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Libervia: a Salut à Toi frontend | |
5 # Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.org> | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 import pyjd # this is dummy in pyjs | |
21 from sat.core.log import getLogger | |
22 log = getLogger(__name__) | |
23 from sat_frontends.quick_frontend.quick_contact_list import QuickContactList | |
24 from pyjamas.ui.SimplePanel import SimplePanel | |
25 from pyjamas.ui.ScrollPanel import ScrollPanel | |
26 from pyjamas.ui.VerticalPanel import VerticalPanel | |
27 from pyjamas.ui.ClickListener import ClickHandler | |
28 from pyjamas.ui.Label import Label | |
29 from pyjamas.ui.HTML import HTML | |
30 from pyjamas.ui.Image import Image | |
31 from pyjamas import Window | |
32 from pyjamas import DOM | |
33 from __pyjamas__ import doc | |
34 | |
35 from sat_frontends.tools import jid | |
36 from constants import Const as C | |
37 import base_widget | |
38 import panels | |
39 import html_tools | |
40 import chat | |
41 | |
42 | |
43 def buildPresenceStyle(presence, base_style=None): | |
44 """Return the CSS classname to be used for displaying the given presence information. | |
45 @param presence (str): presence is a value in ('', 'chat', 'away', 'dnd', 'xa') | |
46 @param base_style (str): base classname | |
47 @return: str | |
48 """ | |
49 if not base_style: | |
50 base_style = "contactLabel" | |
51 return '%s-%s' % (base_style, presence or 'connected') | |
52 | |
53 | |
54 def setPresenceStyle(widget, presence, base_style=None): | |
55 """ | |
56 Set the CSS style of a contact's element according to its presence. | |
57 | |
58 @param widget (Widget): the UI element of the contact | |
59 @param presence (str): a value in ("", "chat", "away", "dnd", "xa"). | |
60 @param base_style (str): the base name of the style to apply | |
61 """ | |
62 if not hasattr(widget, 'presence_style'): | |
63 widget.presence_style = None | |
64 style = buildPresenceStyle(presence, base_style) | |
65 if style == widget.presence_style: | |
66 return | |
67 if widget.presence_style is not None: | |
68 widget.removeStyleName(widget.presence_style) | |
69 widget.addStyleName(style) | |
70 widget.presence_style = style | |
71 | |
72 | |
73 class GroupLabel(base_widget.DragLabel, Label, ClickHandler): | |
74 def __init__(self, host, group): | |
75 self.group = group | |
76 self.host = host | |
77 Label.__init__(self, group) # , Element=DOM.createElement('div') | |
78 self.setStyleName('group') | |
79 base_widget.DragLabel.__init__(self, group, "GROUP") | |
80 ClickHandler.__init__(self) | |
81 self.addClickListener(self) | |
82 | |
83 def onClick(self, sender): | |
84 self.host.getOrCreateLiberviaWidget(panels.MicroblogPanel, {'item': self.group}) | |
85 | |
86 | |
87 class ContactLabel(HTML): | |
88 def __init__(self, jid, name=None): | |
89 HTML.__init__(self) | |
90 self.name = name or str(jid) | |
91 self.waiting = False | |
92 self.refresh() | |
93 self.setStyleName('contactLabel') | |
94 | |
95 def refresh(self): | |
96 if self.waiting: | |
97 wait_html = "<b>(*)</b> " | |
98 self.setHTML("%(wait)s%(name)s" % {'wait': wait_html, | |
99 'name': html_tools.html_sanitize(self.name)}) | |
100 | |
101 def setMessageWaiting(self, waiting): | |
102 """Show a visual indicator if message are waiting | |
103 | |
104 @param waiting: True if message are waiting""" | |
105 self.waiting = waiting | |
106 self.refresh() | |
107 | |
108 | |
109 class ContactMenuBar(base_widget.WidgetMenuBar): | |
110 | |
111 def onBrowserEvent(self, event): | |
112 base_widget.WidgetMenuBar.onBrowserEvent(self, event) | |
113 event.stopPropagation() # prevent opening the chat dialog | |
114 | |
115 @classmethod | |
116 def getCategoryHTML(cls, menu_name_i18n, type_): | |
117 return '<img src="%s"/>' % C.DEFAULT_AVATAR | |
118 | |
119 def setUrl(self, url): | |
120 """Set the URL of the contact avatar.""" | |
121 self.items[0].setHTML('<img src="%s" />' % url) | |
122 | |
123 | |
124 class ContactBox(VerticalPanel, ClickHandler, base_widget.DragLabel): | |
125 | |
126 def __init__(self, host, jid_, name=None, click_listener=None, handle_menu=None): | |
127 VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') | |
128 base_widget.DragLabel.__init__(self, jid_, "CONTACT") | |
129 self.host = host | |
130 self.jid = jid_ | |
131 self.label = ContactLabel(jid_, name) | |
132 self.avatar = ContactMenuBar(self, host) if handle_menu else Image() | |
133 # self.updateAvatar(host.getAvatar(jid_)) # FIXME | |
134 self.add(self.avatar) | |
135 self.add(self.label) | |
136 if click_listener: | |
137 ClickHandler.__init__(self) | |
138 self.addClickListener(self) | |
139 self.click_listener = click_listener | |
140 | |
141 def addMenus(self, menu_bar): | |
142 menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': self.jid}) | |
143 menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': self.jid}) | |
144 | |
145 def setMessageWaiting(self, waiting): | |
146 """Show a visual indicator if message are waiting | |
147 | |
148 @param waiting: True if message are waiting""" | |
149 self.label.setMessageWaiting(waiting) | |
150 | |
151 def updateAvatar(self, url): | |
152 """Update the avatar. | |
153 | |
154 @param url (str): image url | |
155 """ | |
156 self.avatar.setUrl(url) | |
157 | |
158 def onClick(self, sender): | |
159 self.click_listener(self.jid) | |
160 | |
161 | |
162 class GroupPanel(VerticalPanel): | |
163 | |
164 def __init__(self, parent): | |
165 VerticalPanel.__init__(self) | |
166 self.setStyleName('groupPanel') | |
167 self._parent = parent | |
168 self._groups = set() | |
169 | |
170 def add(self, group): | |
171 if group in self._groups: | |
172 log.warning("trying to add an already existing group") | |
173 return | |
174 _item = GroupLabel(self._parent.host, group) | |
175 _item.addMouseListener(self._parent) | |
176 DOM.setStyleAttribute(_item.getElement(), "cursor", "pointer") | |
177 index = 0 | |
178 for group_ in [child.group for child in self.getChildren()]: | |
179 if group_ > group: | |
180 break | |
181 index += 1 | |
182 VerticalPanel.insert(self, _item, index) | |
183 self._groups.add(group) | |
184 | |
185 def remove(self, group): | |
186 for wid in self: | |
187 if isinstance(wid, GroupLabel) and wid.group == group: | |
188 VerticalPanel.remove(self, wid) | |
189 self._groups.remove(group) | |
190 return | |
191 log.warning("Trying to remove a non existent group") | |
192 | |
193 def getGroupBox(self, group): | |
194 """get the widget of a group | |
195 | |
196 @param group (str): the group | |
197 @return: GroupLabel instance if present, else None""" | |
198 for wid in self: | |
199 if isinstance(wid, GroupLabel) and wid.group == group: | |
200 return wid | |
201 return None | |
202 | |
203 def getGroups(self): | |
204 return self._groups | |
205 | |
206 | |
207 class BaseContactsPanel(VerticalPanel): | |
208 """Class that can be used to represent a contact list, but not necessarily | |
209 the one that is displayed on the left side. Special features like popup menu | |
210 panel or changing the contact states must be done in a sub-class.""" | |
211 | |
212 def __init__(self, host, handle_click=False, handle_menu=False): | |
213 VerticalPanel.__init__(self) | |
214 self.host = host | |
215 self.contacts = [] | |
216 self.click_listener = None | |
217 self.handle_menu = handle_menu | |
218 | |
219 if handle_click: | |
220 def cb(contact_jid): | |
221 host.widgets.getOrCreateWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE, profile=C.PROF_KEY_NONE) | |
222 self.click_listener = cb | |
223 | |
224 def add(self, jid_, name=None): | |
225 """Add a contact to the list. | |
226 | |
227 @param jid_ (jid.JID): jid_ of the contact | |
228 @param name (str): optional name of the contact | |
229 """ | |
230 assert isinstance(jid_, jid.JID) | |
231 if jid_ in self.contacts: | |
232 return | |
233 index = 0 | |
234 for contact_ in self.contacts: | |
235 if contact_ > jid_: | |
236 break | |
237 index += 1 | |
238 self.contacts.insert(index, jid_) | |
239 box = ContactBox(self.host, jid_, name, self.click_listener, self.handle_menu) | |
240 VerticalPanel.insert(self, box, index) | |
241 | |
242 def remove(self, jid_): | |
243 box = self.getContactBox(jid_) | |
244 if not box: | |
245 return | |
246 VerticalPanel.remove(self, box) | |
247 self.contacts.remove(jid_) | |
248 | |
249 def isContactPresent(self, contact_jid): | |
250 """Return True if a contact is present in the panel""" | |
251 return contact_jid in self.contacts | |
252 | |
253 def getContacts(self): | |
254 return self.contacts | |
255 | |
256 def getContactBox(self, contact_jid): | |
257 """get the widget of a contact | |
258 | |
259 @param contact_jid (jid.JID): the contact | |
260 @return: ContactBox instance if present, else None""" | |
261 for wid in self: | |
262 if isinstance(wid, ContactBox) and wid.jid == contact_jid: | |
263 return wid | |
264 return None | |
265 | |
266 def updateAvatar(self, jid_, url): | |
267 """Update the avatar of the given contact | |
268 | |
269 @param jid_ (jid.JID): contact jid | |
270 @param url (str): image url | |
271 """ | |
272 try: | |
273 self.getContactBox(jid_).updateAvatar(url) | |
274 except TypeError: | |
275 pass | |
276 | |
277 | |
278 class ContactsPanel(BaseContactsPanel): | |
279 """The contact list that is displayed on the left side.""" | |
280 | |
281 def __init__(self, host): | |
282 BaseContactsPanel.__init__(self, host, handle_click=True, handle_menu=True) | |
283 | |
284 def setState(self, jid_, type_, state): | |
285 """Change the appearance of the contact, according to the state | |
286 @param jid_ (jid.JID): jid.JID which need to change state | |
287 @param type_ (str): one of "availability", "messageWaiting" | |
288 @param state: | |
289 - for messageWaiting type: | |
290 True if message are waiting | |
291 - for availability type: | |
292 C.PRESENCE_UNAVAILABLE or None if not connected, else presence like RFC6121 #4.7.2.1""" | |
293 assert type_ in ('availability', 'messageWaiting') | |
294 contact_box = self.getContactBox(jid_) | |
295 if not contact_box: | |
296 log.warning("No contact box found for {}".format(jid_)) | |
297 else: | |
298 if type_ == 'availability': | |
299 if state is None: | |
300 state = C.PRESENCE_UNAVAILABLE | |
301 setPresenceStyle(contact_box.label, state) | |
302 elif type_ == 'messageWaiting': | |
303 contact_box.setMessageWaiting(state) | |
304 | |
305 | |
306 class ContactTitleLabel(base_widget.DragLabel, Label, ClickHandler): | |
307 def __init__(self, host, text): | |
308 Label.__init__(self, text) # , Element=DOM.createElement('div') | |
309 self.host = host | |
310 self.setStyleName('contactTitle') | |
311 base_widget.DragLabel.__init__(self, text, "CONTACT_TITLE") | |
312 ClickHandler.__init__(self) | |
313 self.addClickListener(self) | |
314 | |
315 def onClick(self, sender): | |
316 self.host.getOrCreateLiberviaWidget(panels.MicroblogPanel, {'item': None}) | |
317 | |
318 | |
319 class ContactList(SimplePanel, QuickContactList): | |
320 """Manage the contacts and groups""" | |
321 | |
322 def __init__(self, host): | |
323 QuickContactList.__init__(self, host, C.PROF_KEY_NONE) | |
324 SimplePanel.__init__(self) | |
325 self.scroll_panel = ScrollPanel() | |
326 self.vPanel = VerticalPanel() | |
327 _title = ContactTitleLabel(host, 'Contacts') | |
328 DOM.setStyleAttribute(_title.getElement(), "cursor", "pointer") | |
329 self._contacts_panel = ContactsPanel(host) | |
330 self._contacts_panel.setStyleName('contactPanel') # FIXME: style doesn't exists ! | |
331 self._group_panel = GroupPanel(self) | |
332 | |
333 self.vPanel.add(_title) | |
334 self.vPanel.add(self._group_panel) | |
335 self.vPanel.add(self._contacts_panel) | |
336 self.scroll_panel.add(self.vPanel) | |
337 self.add(self.scroll_panel) | |
338 self.setStyleName('contactList') | |
339 Window.addWindowResizeListener(self) | |
340 | |
341 @property | |
342 def profile(self): | |
343 return C.PROF_KEY_NONE | |
344 | |
345 def update(self): | |
346 ### GROUPS ### | |
347 _keys = self._groups.keys() | |
348 try: | |
349 # XXX: Pyjamas doesn't do the set casting if None is present | |
350 _keys.remove(None) | |
351 except KeyError: | |
352 pass | |
353 current_groups = set(_keys) | |
354 shown_groups = self._group_panel.getGroups() | |
355 new_groups = current_groups.difference(shown_groups) | |
356 removed_groups = shown_groups.difference(current_groups) | |
357 for group in new_groups: | |
358 self._group_panel.add(group) | |
359 for group in removed_groups: | |
360 self._group_panel.remove(group) | |
361 | |
362 ### JIDS ### | |
363 current_contacts = set(self._cache.keys()) | |
364 shown_contacts = set(self._contacts_panel.getContacts()) | |
365 new_contacts = current_contacts.difference(shown_contacts) | |
366 removed_contacts = shown_contacts.difference(current_contacts) | |
367 | |
368 for contact in new_contacts: | |
369 self._contacts_panel.add(contact) | |
370 for contact in removed_contacts: | |
371 self._contacts_panel.remove(contact) | |
372 | |
373 def onWindowResized(self, width, height): | |
374 contact_panel_elt = self.getElement() | |
375 # FIXME: still needed ? | |
376 # classname = 'widgetsPanel' if isinstance(self.getParent().getParent(), panels.UniBoxPanel) else 'gwt-TabBar' | |
377 classname = 'gwt-TabBar' | |
378 _elts = doc().getElementsByClassName(classname) | |
379 if not _elts.length: | |
380 log.error("no element of class %s found, it should exist !" % classname) | |
381 tab_bar_h = height | |
382 else: | |
383 tab_bar_h = DOM.getAbsoluteTop(_elts.item(0)) or height # getAbsoluteTop can be 0 if tabBar is hidden | |
384 | |
385 ideal_height = tab_bar_h - DOM.getAbsoluteTop(contact_panel_elt) - 5 | |
386 self.scroll_panel.setHeight("%s%s" % (ideal_height, "px")) | |
387 | |
388 # def updateContact(self, jid_s, attributes, groups): | |
389 # """Add a contact to the panel if it doesn't exist, update it else | |
390 | |
391 # @param jid_s: jid userhost as unicode | |
392 # @param attributes: cf SàT Bridge API's newContact | |
393 # @param groups: list of groups""" | |
394 # _current_groups = self.getContactGroups(jid_s) | |
395 # _new_groups = set(groups) | |
396 # _key = "@%s: " | |
397 | |
398 # for group in _current_groups.difference(_new_groups): | |
399 # # We remove the contact from the groups where he isn't anymore | |
400 # self.groups[group].remove(jid_s) | |
401 # if not self.groups[group]: | |
402 # # The group is now empty, we must remove it | |
403 # del self.groups[group] | |
404 # self._group_panel.remove(group) | |
405 # if self.host.uni_box: | |
406 # self.host.uni_box.removeKey(_key % group) | |
407 | |
408 # for group in _new_groups.difference(_current_groups): | |
409 # # We add the contact to the groups he joined | |
410 # if group not in self.groups.keys(): | |
411 # self.groups[group] = set() | |
412 # self._group_panel.add(group) | |
413 # if self.host.uni_box: | |
414 # self.host.uni_box.addKey(_key % group) | |
415 # self.groups[group].add(jid_s) | |
416 | |
417 # # We add the contact to contact list, it will check if contact already exists | |
418 # self._contacts_panel.add(jid_s) | |
419 # self.updateVisibility([jid_s], self.getContactGroups(jid_s)) | |
420 | |
421 # def removeContact(self, jid): | |
422 # """Remove contacts from groups where he is and contact list""" | |
423 # self.updateContact(jid, {}, []) # we remove contact from every group | |
424 # self._contacts_panel.remove(jid) | |
425 | |
426 # def setConnected(self, jid_s, resource, availability, priority, statuses): | |
427 # """Set connection status | |
428 # @param jid_s (str): JID userhost as unicode | |
429 # """ | |
430 # if availability == 'unavailable': | |
431 # if jid_s in self.connected: | |
432 # if resource in self.connected[jid_s]: | |
433 # del self.connected[jid_s][resource] | |
434 # if not self.connected[jid_s]: | |
435 # del self.connected[jid_s] | |
436 # else: | |
437 # if jid_s not in self.connected: | |
438 # self.connected[jid_s] = {} | |
439 # self.connected[jid_s][resource] = (availability, priority, statuses) | |
440 | |
441 # # check if the contact is connected with another resource, use the one with highest priority | |
442 # if jid_s in self.connected: | |
443 # max_resource = max_priority = None | |
444 # for tmp_resource in self.connected[jid_s]: | |
445 # if max_priority is None or self.connected[jid_s][tmp_resource][1] >= max_priority: | |
446 # max_resource = tmp_resource | |
447 # max_priority = self.connected[jid_s][tmp_resource][1] | |
448 # if availability == "unavailable": # do not check the priority here, because 'unavailable' has a dummy one | |
449 # priority = max_priority | |
450 # availability = self.connected[jid_s][max_resource][0] | |
451 # if jid_s not in self.connected or priority >= max_priority: | |
452 # # case 1: jid not in self.connected means all resources are disconnected, update with 'unavailable' | |
453 # # case 2: update (or confirm) with the values of the resource which takes precedence | |
454 # self._contacts_panel.setState(jid_s, "availability", availability) | |
455 | |
456 # # update the connected contacts chooser live | |
457 # if hasattr(self.host, "room_contacts_chooser") and self.host.room_contacts_chooser is not None: | |
458 # self.host.room_contacts_chooser.resetContacts() | |
459 | |
460 # self.updateVisibility([jid_s], self.getContactGroups(jid_s)) | |
461 | |
462 def setContactMessageWaiting(self, jid, waiting): | |
463 """Show an visual indicator that contact has send a message | |
464 @param jid: jid of the contact | |
465 @param waiting: True if message are waiting""" | |
466 self._contacts_panel.setState(jid, "messageWaiting", waiting) | |
467 | |
468 # def getConnected(self, filter_muc=False): | |
469 # """return a list of all jid (bare jid) connected | |
470 # @param filter_muc: if True, remove the groups from the list | |
471 # """ | |
472 # contacts = self.connected.keys() | |
473 # contacts.sort() | |
474 # return contacts if not filter_muc else list(set(contacts).intersection(set(self.getContacts()))) | |
475 | |
476 # def getContactGroups(self, contact_jid_s): | |
477 # """Get groups where contact is | |
478 # @param group: string of single group, or list of string | |
479 # @param contact_jid_s: jid to test, as unicode | |
480 # """ | |
481 # result = set() | |
482 # for group in self.groups: | |
483 # if self.isContactInGroup(group, contact_jid_s): | |
484 # result.add(group) | |
485 # return result | |
486 | |
487 # def isContactInGroup(self, group, contact_jid): | |
488 # """Test if the contact_jid is in the group | |
489 # @param group: string of single group, or list of string | |
490 # @param contact_jid: jid to test | |
491 # @return: True if contact_jid is in on of the groups""" | |
492 # if group in self.groups and contact_jid in self.groups[group]: | |
493 # return True | |
494 # return False | |
495 | |
496 def isContactInRoster(self, contact_jid): | |
497 """Test if the contact is in our roster list""" | |
498 for contact_box in self._contacts_panel: | |
499 if contact_jid == contact_box.jid: | |
500 return True | |
501 return False | |
502 | |
503 # def getContacts(self): | |
504 # return self._contacts_panel.getContacts() | |
505 | |
506 def getGroups(self): | |
507 return self.groups.keys() | |
508 | |
509 def onMouseMove(self, sender, x, y): | |
510 pass | |
511 | |
512 def onMouseDown(self, sender, x, y): | |
513 pass | |
514 | |
515 def onMouseUp(self, sender, x, y): | |
516 pass | |
517 | |
518 def onMouseEnter(self, sender): | |
519 if isinstance(sender, GroupLabel): | |
520 jids = self.getGroupData(sender.group, "jids") | |
521 for contact in self._contacts_panel: | |
522 if contact.jid in jids: | |
523 contact.label.addStyleName("selected") | |
524 | |
525 def onMouseLeave(self, sender): | |
526 if isinstance(sender, GroupLabel): | |
527 jids = self.getGroupData(sender.group, "jids") | |
528 for contact in self._contacts_panel: | |
529 if contact.jid in jids: | |
530 contact.label.removeStyleName("selected") | |
531 | |
532 def updateAvatar(self, jid_s, url): | |
533 """Update the avatar of the given contact | |
534 | |
535 @param jid_s (str): contact jid | |
536 @param url (str): image url | |
537 """ | |
538 self._contacts_panel.updateAvatar(jid_s, url) | |
539 | |
540 def hasVisibleMembers(self, group): | |
541 """Tell if the given group actually has visible members | |
542 | |
543 @param group (str): the group to check | |
544 @return: boolean | |
545 """ | |
546 for jid_ in self.groups[group]: | |
547 if self._contacts_panel.getContactBox(jid_).isVisible(): | |
548 return True | |
549 return False | |
550 | |
551 def offlineContactsToShow(self): | |
552 """Tell if offline contacts should be visible according to the user settings | |
553 | |
554 @return: boolean | |
555 """ | |
556 return self.host.getCachedParam('General', C.SHOW_OFFLINE_CONTACTS) == 'true' | |
557 | |
558 def emtyGroupsToShow(self): | |
559 """Tell if empty groups should be visible according to the user settings | |
560 | |
561 @return: boolean | |
562 """ | |
563 return self.host.getCachedParam('General', C.SHOW_EMPTY_GROUPS) == 'true' | |
564 | |
565 def updatePresence(self, entity, show, priority, statuses): | |
566 QuickContactList.updatePresence(self, entity, show, priority, statuses) | |
567 entity_bare = entity.bare | |
568 show = self.getCache(entity_bare, C.PRESENCE_SHOW) # we use cache to have the show nformation of main resource only | |
569 self._contacts_panel.setState(entity_bare, "availability", show) | |
570 | |
571 # def updateVisibility(self, jids, groups): | |
572 # """Set the widgets visibility for the given contacts and groups | |
573 | |
574 # @param jids (list[str]): list of JID | |
575 # @param groups (list[str]): list of groups | |
576 # """ | |
577 # for jid_s in jids: | |
578 # try: | |
579 # self._contacts_panel.getContactBox(jid_s).setVisible(jid_s in self.connected or self.offlineContactsToShow()) | |
580 # except TypeError: | |
581 # log.warning('No box for contact %s: this code line should not be reached' % jid_s) | |
582 # for group in groups: | |
583 # try: | |
584 # self._group_panel.getGroupBox(group).setVisible(self.hasVisibleMembers(group) or self.emtyGroupsToShow()) | |
585 # except TypeError: | |
586 # log.warning('No box for group %s: this code line should not be reached' % group) | |
587 | |
588 # def refresh(self): | |
589 # """Show or hide disconnected contacts and empty groups""" | |
590 # self.updateVisibility(self._contacts_panel.contacts, self.groups.keys()) |