Mercurial > libervia-web
comparison src/browser/sat_browser/contact_list.py @ 630:71abccd8d228 frontends_multi_profiles
browser side: contact_list update:
- removed ContactPanel's "add" and "remove" method, and replaced them by a display which display all needed contact at once
- first naive implementation of display: if the display change, clear and add all ContactBox. Need to be done in a more efficient way in the future
- ContactBox are never deleted, and only hidden when not displayed. ContactBox are automatically created on first use (TODO: add a way to delete them for entities not in roster)
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 23 Feb 2015 18:16:07 +0100 |
parents | 57a651a5b31d |
children | 617f7a5c5312 |
comparison
equal
deleted
inserted
replaced
629:57a651a5b31d | 630:71abccd8d228 |
---|---|
129 self.items[0].setHTML('<img src="%s" />' % url) | 129 self.items[0].setHTML('<img src="%s" />' % url) |
130 | 130 |
131 | 131 |
132 class ContactBox(VerticalPanel, ClickHandler, base_widget.DragLabel): | 132 class ContactBox(VerticalPanel, ClickHandler, base_widget.DragLabel): |
133 | 133 |
134 def __init__(self, host, jid_, name=None, click_listener=None, handle_menu=None): | 134 def __init__(self, host, jid_, name=None, on_click=None, handle_menu=None): |
135 """ | 135 """ |
136 | 136 |
137 @param host (SatWebFrontend) | 137 @param host (SatWebFrontend): %(doc_host)s |
138 @param jid_ (jid.JID): contact JID | 138 @param jid_ (jid.JID): contact JID |
139 @param name (unicode): contact alias | 139 @param name (unicode): contact alias |
140 @param click_listener (callable): click callback | 140 @param on_click (callable): click callback |
141 @param handle_menu (bool): if True, bind a popup menu to the avatar | 141 @param handle_menu (bool): if True, bind a popup menu to the avatar |
142 """ | 142 """ |
143 VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') | 143 VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') |
144 base_widget.DragLabel.__init__(self, jid_, "CONTACT", host) | 144 base_widget.DragLabel.__init__(self, jid_, "CONTACT", host) |
145 self.jid = jid_ | 145 self.jid = jid_ |
146 self.label = ContactLabel(jid_, name) | 146 self.label = ContactLabel(jid_, name) |
147 self.avatar = ContactMenuBar(self, host) if handle_menu else Image() | 147 self.avatar = ContactMenuBar(self, host) if handle_menu else Image() |
148 self.updateAvatar(host.getAvatarURL(jid_)) | 148 self.updateAvatar(host.getAvatarURL(jid_)) |
149 self.add(self.avatar) | 149 self.add(self.avatar) |
150 self.add(self.label) | 150 self.add(self.label) |
151 if click_listener: | 151 if on_click: |
152 ClickHandler.__init__(self) | 152 ClickHandler.__init__(self) |
153 self.addClickListener(self) | 153 self.addClickListener(self) |
154 self.click_listener = click_listener | 154 self._on_click = on_click |
155 | 155 |
156 def addMenus(self, menu_bar): | 156 def addMenus(self, menu_bar): |
157 menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': unicode(self.jid)}) | 157 menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': unicode(self.jid)}) |
158 menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': unicode(self.jid)}) | 158 menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': unicode(self.jid)}) |
159 | 159 |
169 @param url (unicode): image url | 169 @param url (unicode): image url |
170 """ | 170 """ |
171 self.avatar.setUrl(url) | 171 self.avatar.setUrl(url) |
172 | 172 |
173 def onClick(self, sender): | 173 def onClick(self, sender): |
174 self.click_listener(self.jid) | 174 self._on_click(self.jid) |
175 | 175 |
176 | 176 |
177 class GroupPanel(VerticalPanel): | 177 class GroupPanel(VerticalPanel): |
178 | 178 |
179 def __init__(self, parent): | 179 def __init__(self, parent): |
218 def getGroups(self): | 218 def getGroups(self): |
219 return self._groups | 219 return self._groups |
220 | 220 |
221 | 221 |
222 class BaseContactsPanel(VerticalPanel): | 222 class BaseContactsPanel(VerticalPanel): |
223 """Class that can be used to represent a contact list, but not necessarily | 223 """ContactList graphic representation |
224 the one that is displayed on the left side. Special features like popup menu | 224 |
225 panel or changing the contact states must be done in a sub-class.""" | 225 Special features like popup menu panel or changing the contact states must be done in a sub-class. |
226 """ | |
226 | 227 |
227 def __init__(self, host, handle_click=False, handle_menu=False): | 228 def __init__(self, host, handle_click=False, handle_menu=False): |
228 VerticalPanel.__init__(self) | 229 VerticalPanel.__init__(self) |
229 self.host = host | 230 self.host = host |
230 self.contacts = [] | 231 self._contacts = {} # entity jid to ContactBox map |
231 self.click_listener = None | 232 self.click_listener = None |
232 self.handle_menu = handle_menu | 233 self.handle_menu = handle_menu |
233 | 234 |
234 if handle_click: | 235 if handle_click: |
235 def cb(contact_jid): | 236 def cb(contact_jid): |
236 host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE) | 237 host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE) |
237 self.click_listener = cb | 238 self.click_listener = cb |
238 | 239 |
239 def add(self, jid_, name=None): | 240 def display(self, jids): |
240 """Add a contact to the list. | 241 """Display a contact in the list. |
241 | 242 |
242 @param jid_ (jid.JID): jid_ of the contact | 243 @param jids (list[jid.JID]): jids to display (the order is kept) |
243 @param name (unicode): optional name of the contact | 244 @param name (unicode): optional name of the contact |
244 """ | 245 """ |
245 assert isinstance(jid_, jid.JID) | 246 # FIXME: we do a full clear and add boxes after, we should only remove recently hidden boxes and add new ones, and re-order |
246 if jid_ in self.contacts: | 247 current = [box.jid for box in self.children if isinstance(box, ContactBox)] |
248 if current == jids: | |
249 # the display doesn't change | |
247 return | 250 return |
248 index = 0 | 251 self.clear() |
249 for contact_ in self.contacts: | 252 for jid_ in jids: |
250 if contact_ > jid_: | 253 assert isinstance(jid_, jid.JID) |
251 break | 254 box = self.getContactBox(jid_) |
252 index += 1 | 255 VerticalPanel.append(self, box) |
253 self.contacts.insert(index, jid_) | |
254 box = ContactBox(self.host, jid_, name, self.click_listener, self.handle_menu) | |
255 VerticalPanel.insert(self, box, index) | |
256 | |
257 def remove(self, jid_): | |
258 box = self.getContactBox(jid_) | |
259 if not box: | |
260 return | |
261 VerticalPanel.remove(self, box) | |
262 self.contacts.remove(jid_) | |
263 | 256 |
264 def isContactPresent(self, contact_jid): | 257 def isContactPresent(self, contact_jid): |
265 """Return True if a contact is present in the panel""" | 258 """Return True if a contact is present in the panel""" |
266 return contact_jid in self.contacts | 259 return contact_jid in self._contacts |
267 | 260 |
268 def getContacts(self): | 261 def getContacts(self): |
269 return self.contacts | 262 return self._contacts |
270 | 263 |
271 def getContactBox(self, contact_jid): | 264 def getContactBox(self, contact_jid, name=None, on_click=None, handle_menu=None): |
272 """get the widget of a contact | 265 """get the Contactbox of a contact |
273 | 266 |
267 if the Contactbox doesn't exists, it will be created | |
274 @param contact_jid (jid.JID): the contact | 268 @param contact_jid (jid.JID): the contact |
275 @return: ContactBox instance if present, else None""" | 269 @param name (unicode): contact alias (used if ContactBox is created) |
270 @param on_click (callable): click callback (used if ContactBox is created) | |
271 @param handle_menu (bool): if True, bind a popup menu to the avatar (used if ContactBox is created) | |
272 @return: ContactBox instance | |
273 """ | |
276 assert isinstance(contact_jid, jid.JID) | 274 assert isinstance(contact_jid, jid.JID) |
277 for wid in self: | 275 try: |
278 if isinstance(wid, ContactBox) and wid.jid == contact_jid: | 276 return self._contacts[contact_jid] |
279 return wid | 277 except KeyError: |
280 return None | 278 box = ContactBox(self.host, contact_jid, name, on_click, handle_menu) |
279 self._contacts[contact_jid] = box | |
280 return box | |
281 | 281 |
282 def updateAvatar(self, jid_, url): | 282 def updateAvatar(self, jid_, url): |
283 """Update the avatar of the given contact | 283 """Update the avatar of the given contact |
284 | 284 |
285 @param jid_ (jid.JID): contact jid | 285 @param jid_ (jid.JID): contact jid |
306 True if message are waiting | 306 True if message are waiting |
307 - for availability type: | 307 - for availability type: |
308 C.PRESENCE_UNAVAILABLE or None if not connected, else presence like RFC6121 #4.7.2.1""" | 308 C.PRESENCE_UNAVAILABLE or None if not connected, else presence like RFC6121 #4.7.2.1""" |
309 assert type_ in ('availability', 'messageWaiting') | 309 assert type_ in ('availability', 'messageWaiting') |
310 contact_box = self.getContactBox(jid_) | 310 contact_box = self.getContactBox(jid_) |
311 if not contact_box: | 311 if type_ == 'availability': |
312 log.warning("No contact box found for {}".format(jid_)) | 312 if state is None: |
313 else: | 313 state = C.PRESENCE_UNAVAILABLE |
314 if type_ == 'availability': | 314 setPresenceStyle(contact_box.label, state) |
315 if state is None: | 315 elif type_ == 'messageWaiting': |
316 state = C.PRESENCE_UNAVAILABLE | 316 contact_box.setMessageWaiting(state) |
317 setPresenceStyle(contact_box.label, state) | |
318 elif type_ == 'messageWaiting': | |
319 contact_box.setMessageWaiting(state) | |
320 | 317 |
321 | 318 |
322 class ContactTitleLabel(base_widget.DragLabel, Label, ClickHandler): | 319 class ContactTitleLabel(base_widget.DragLabel, Label, ClickHandler): |
323 def __init__(self, host, text): | 320 def __init__(self, host, text): |
324 Label.__init__(self, text) # , Element=DOM.createElement('div') | 321 Label.__init__(self, text) # , Element=DOM.createElement('div') |
378 self._group_panel.add(group) | 375 self._group_panel.add(group) |
379 for group in removed_groups: | 376 for group in removed_groups: |
380 self._group_panel.remove(group) | 377 self._group_panel.remove(group) |
381 | 378 |
382 ### JIDS ### | 379 ### JIDS ### |
383 current_contacts = set([jid_ for jid_ in self._cache.keys() if self.entityToShow(jid_)]) | 380 to_show = [jid_ for jid_ in self._cache.keys() if self.entityToShow(jid_)] |
384 shown_contacts = set(self._contacts_panel.getContacts()) | 381 to_show.sort() |
385 new_contacts = current_contacts.difference(shown_contacts) | 382 |
386 removed_contacts = shown_contacts.difference(current_contacts) | 383 self._contacts_panel.display(to_show) |
387 | 384 |
388 for contact in new_contacts: | 385 for jid_ in self._alerts: |
389 self._contacts_panel.add(contact) | 386 self._contacts_panel.setState(jid_, "messageWaiting", True) |
390 for contact in removed_contacts: | |
391 self._contacts_panel.remove(contact) | |
392 | 387 |
393 def onWindowResized(self, width, height): | 388 def onWindowResized(self, width, height): |
394 contact_panel_elt = self.getElement() | 389 contact_panel_elt = self.getElement() |
395 # FIXME: still needed ? | 390 # FIXME: still needed ? |
396 # classname = 'widgetsPanel' if isinstance(self.getParent().getParent(), panels.UniBoxPanel) else 'gwt-TabBar' | 391 # classname = 'widgetsPanel' if isinstance(self.getParent().getParent(), panels.UniBoxPanel) else 'gwt-TabBar' |
478 # self.host.room_contacts_chooser.resetContacts() | 473 # self.host.room_contacts_chooser.resetContacts() |
479 | 474 |
480 # self.updateVisibility([jid_s], self.getContactGroups(jid_s)) | 475 # self.updateVisibility([jid_s], self.getContactGroups(jid_s)) |
481 | 476 |
482 def setContactMessageWaiting(self, jid, waiting): | 477 def setContactMessageWaiting(self, jid, waiting): |
483 """Show an visual indicator that contact has send a message | 478 """Show a visual indicator that contact has send a message |
479 | |
484 @param jid: jid of the contact | 480 @param jid: jid of the contact |
485 @param waiting: True if message are waiting""" | 481 @param waiting: True if message are waiting""" |
486 self._contacts_panel.setState(jid, "messageWaiting", waiting) | 482 raise Exception("Should not be there") |
483 # self._contacts_panel.setState(jid, "messageWaiting", waiting) | |
487 | 484 |
488 # def getConnected(self, filter_muc=False): | 485 # def getConnected(self, filter_muc=False): |
489 # """return a list of all jid (bare jid) connected | 486 # """return a list of all jid (bare jid) connected |
490 # @param filter_muc: if True, remove the groups from the list | 487 # @param filter_muc: if True, remove the groups from the list |
491 # """ | 488 # """ |
594 def updatePresence(self, entity, show, priority, statuses): | 591 def updatePresence(self, entity, show, priority, statuses): |
595 QuickContactList.updatePresence(self, entity, show, priority, statuses) | 592 QuickContactList.updatePresence(self, entity, show, priority, statuses) |
596 entity_bare = entity.bare | 593 entity_bare = entity.bare |
597 show = self.getCache(entity_bare, C.PRESENCE_SHOW) # we use cache to have the show nformation of main resource only | 594 show = self.getCache(entity_bare, C.PRESENCE_SHOW) # we use cache to have the show nformation of main resource only |
598 self._contacts_panel.setState(entity_bare, "availability", show) | 595 self._contacts_panel.setState(entity_bare, "availability", show) |
596 self.update() | |
599 | 597 |
600 # def updateVisibility(self, jids, groups): | 598 # def updateVisibility(self, jids, groups): |
601 # """Set the widgets visibility for the given contacts and groups | 599 # """Set the widgets visibility for the given contacts and groups |
602 | 600 |
603 # @param jids (list[unicode]): list of JID | 601 # @param jids (list[unicode]): list of JID |