Mercurial > libervia-web
comparison src/browser/sat_browser/contact_list.py @ 634:16a5da120b7f frontends_multi_profiles
browser side (contact list): Contact list improvments:
- removed optional arguments from getContactBox: they are now managed by the hosting panel, as the arguments should be same for all contacts in a panel
- contact name is no more specified on ContactBox creation, is gotten by the ContactLabel itself using the cache (TODO: "nick" listener)
- renamed setMessageXXX to setAlert for consitency with QuickFrontend (furthermore the alert could be used for something else than waiting messages)
- ContactBoxes are stored using bare jid
- parent is used in ContactBox instead of host
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 23 Feb 2015 18:44:57 +0100 |
parents | 617f7a5c5312 |
children | 7113d40533d6 |
comparison
equal
deleted
inserted
replaced
633:617f7a5c5312 | 634:16a5da120b7f |
---|---|
91 def onClick(self, sender): | 91 def onClick(self, sender): |
92 self.host.displayWidget(blog.MicroblogPanel, self.group) | 92 self.host.displayWidget(blog.MicroblogPanel, self.group) |
93 | 93 |
94 | 94 |
95 class ContactLabel(HTML): | 95 class ContactLabel(HTML): |
96 def __init__(self, jid_, name=None): | 96 """Display a contact in HTML, selecting best display (jid/nick/etc)""" |
97 | |
98 def __init__(self, host, jid_): | |
99 # TODO: add a listener for nick changes | |
97 HTML.__init__(self) | 100 HTML.__init__(self) |
98 self.name = name or unicode(jid_) | 101 self.host = host |
99 self.waiting = False | 102 self.jid = jid_.bare |
103 self.nick = self.host.contact_lists[C.PROF_KEY_NONE].getCache(self.jid, "nick") | |
104 self.alert = False | |
100 self.refresh() | 105 self.refresh() |
101 self.setStyleName('contactLabel') | 106 self.setStyleName('contactLabel') |
102 | 107 |
103 def refresh(self): | 108 def refresh(self): |
104 if self.waiting: | 109 alert_html = "<strong>(*)</strong> " if self.alert else "" |
105 wait_html = "<b>(*)</b> " | 110 contact_html = html_tools.html_sanitize(self.nick or unicode(self.jid)) |
106 self.setHTML("%(wait)s%(name)s" % {'wait': wait_html, | 111 html = "%(alert)s%(contact)s" % {'alert': alert_html, |
107 'name': html_tools.html_sanitize(self.name)}) | 112 'contact': contact_html} |
108 | 113 self.setHTML(html) |
109 def setMessageWaiting(self, waiting): | 114 |
110 """Show a visual indicator if message are waiting | 115 def setAlert(self, alert): |
111 | 116 """Show a visual indicator |
112 @param waiting: True if message are waiting""" | 117 |
113 self.waiting = waiting | 118 @param alert: True if alert must be shown |
119 """ | |
120 self.alert = alert | |
114 self.refresh() | 121 self.refresh() |
115 | 122 |
116 | 123 |
117 class ContactMenuBar(base_widget.WidgetMenuBar): | 124 class ContactMenuBar(base_widget.WidgetMenuBar): |
118 | 125 |
129 self.items[0].setHTML('<img src="%s" />' % url) | 136 self.items[0].setHTML('<img src="%s" />' % url) |
130 | 137 |
131 | 138 |
132 class ContactBox(VerticalPanel, ClickHandler, base_widget.DragLabel): | 139 class ContactBox(VerticalPanel, ClickHandler, base_widget.DragLabel): |
133 | 140 |
134 def __init__(self, host, jid_, name=None, on_click=None, handle_menu=None): | 141 def __init__(self, parent, jid_): |
135 """ | 142 """ |
136 | 143 @param parent (ContactPanel): ContactPanel hosting this box |
137 @param host (SatWebFrontend): %(doc_host)s | |
138 @param jid_ (jid.JID): contact JID | 144 @param jid_ (jid.JID): contact JID |
139 @param name (unicode): contact alias | |
140 @param on_click (callable): click callback | |
141 @param handle_menu (bool): if True, bind a popup menu to the avatar | |
142 """ | 145 """ |
143 VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') | 146 VerticalPanel.__init__(self, StyleName='contactBox', VerticalAlignment='middle') |
144 base_widget.DragLabel.__init__(self, jid_, "CONTACT", host) | 147 ClickHandler.__init__(self) |
145 self.jid = jid_ | 148 base_widget.DragLabel.__init__(self, jid_, "CONTACT", parent.host) |
146 self.label = ContactLabel(jid_, name) | 149 self.jid = jid_.bare |
147 self.avatar = ContactMenuBar(self, host) if handle_menu else Image() | 150 self.label = ContactLabel(parent.host, self.jid) |
148 self.updateAvatar(host.getAvatarURL(jid_)) | 151 self.avatar = ContactMenuBar(self, parent.host) if parent.handle_menu else Image() |
152 self.updateAvatar(parent.host.getAvatarURL(self.jid)) | |
149 self.add(self.avatar) | 153 self.add(self.avatar) |
150 self.add(self.label) | 154 self.add(self.label) |
151 if on_click: | 155 self.addClickListener(self) |
152 ClickHandler.__init__(self) | |
153 self.addClickListener(self) | |
154 self._on_click = on_click | |
155 | 156 |
156 def addMenus(self, menu_bar): | 157 def addMenus(self, menu_bar): |
157 menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': unicode(self.jid)}) | 158 menu_bar.addCachedMenus(C.MENU_ROSTER_JID_CONTEXT, {'jid': unicode(self.jid)}) |
158 menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': unicode(self.jid)}) | 159 menu_bar.addCachedMenus(C.MENU_JID_CONTEXT, {'jid': unicode(self.jid)}) |
159 | 160 |
160 def setMessageWaiting(self, waiting): | 161 def setAlert(self, alert): |
161 """Show a visual indicator if message are waiting | 162 """Show a visual indicator |
162 | 163 |
163 @param waiting: True if message are waiting""" | 164 @param alert: True if alert indicator show be shown""" |
164 self.label.setMessageWaiting(waiting) | 165 self.label.setAlert(alert) |
165 | 166 |
166 def updateAvatar(self, url): | 167 def updateAvatar(self, url): |
167 """Update the avatar. | 168 """Update the avatar. |
168 | 169 |
169 @param url (unicode): image url | 170 @param url (unicode): image url |
170 """ | 171 """ |
171 self.avatar.setUrl(url) | 172 self.avatar.setUrl(url) |
172 | 173 |
173 def onClick(self, sender): | 174 def onClick(self, sender): |
174 self._on_click(self.jid) | 175 try: |
176 self.parent.onClick(self.jid) | |
177 except AttributeError: | |
178 pass | |
179 else: | |
180 self.setAlert(False) | |
175 | 181 |
176 | 182 |
177 class GroupPanel(VerticalPanel): | 183 class GroupPanel(VerticalPanel): |
178 | 184 |
179 def __init__(self, parent): | 185 def __init__(self, parent): |
223 """ContactList graphic representation | 229 """ContactList graphic representation |
224 | 230 |
225 Special features like popup menu panel or changing the contact states must be done in a sub-class. | 231 Special features like popup menu panel or changing the contact states must be done in a sub-class. |
226 """ | 232 """ |
227 | 233 |
228 def __init__(self, host, handle_click=False, handle_menu=False): | 234 def __init__(self, parent, handle_click=True, handle_menu=True): |
235 """@param on_click (callable): click callback (used if ContactBox is created) | |
236 @param handle_menu (bool): if True, bind a popup menu to the avatar (used if ContactBox is created) | |
237 """ # FIXME | |
229 VerticalPanel.__init__(self) | 238 VerticalPanel.__init__(self) |
230 self.host = host | 239 self._parent = parent |
240 self.host = parent.host | |
231 self._contacts = {} # entity jid to ContactBox map | 241 self._contacts = {} # entity jid to ContactBox map |
232 self.click_listener = None | 242 self.click_listener = None |
233 self.handle_menu = handle_menu | 243 self.handle_menu = handle_menu |
234 | 244 |
235 if handle_click: | 245 if handle_click: |
236 def cb(contact_jid): | 246 def cb(contact_jid): |
237 host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE) | 247 self.host.displayWidget(chat.Chat, contact_jid, type_=C.CHAT_ONE2ONE) |
238 self.click_listener = cb | 248 self.onClick = cb |
239 | 249 |
240 def display(self, jids): | 250 def display(self, jids): |
241 """Display a contact in the list. | 251 """Display a contact in the list. |
242 | 252 |
243 @param jids (list[jid.JID]): jids to display (the order is kept) | 253 @param jids (list[jid.JID]): jids to display (the order is kept) |
259 return contact_jid in self._contacts | 269 return contact_jid in self._contacts |
260 | 270 |
261 def getContacts(self): | 271 def getContacts(self): |
262 return self._contacts | 272 return self._contacts |
263 | 273 |
264 def getContactBox(self, contact_jid, name=None, on_click=None, handle_menu=None): | 274 def getContactBox(self, contact_jid): |
265 """get the Contactbox of a contact | 275 """get the Contactbox of a contact |
266 | 276 |
267 if the Contactbox doesn't exists, it will be created | 277 if the Contactbox doesn't exists, it will be created |
268 @param contact_jid (jid.JID): the contact | 278 @param contact_jid (jid.JID): the contact |
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 | 279 @return: ContactBox instance |
273 """ | 280 """ |
274 assert isinstance(contact_jid, jid.JID) | |
275 try: | 281 try: |
276 return self._contacts[contact_jid] | 282 return self._contacts[contact_jid.bare] |
277 except KeyError: | 283 except KeyError: |
278 box = ContactBox(self.host, contact_jid, name, on_click, handle_menu) | 284 box = ContactBox(self, contact_jid) |
279 self._contacts[contact_jid] = box | 285 self._contacts[contact_jid.bare] = box |
280 return box | 286 return box |
281 | 287 |
282 def updateAvatar(self, jid_, url): | 288 def updateAvatar(self, jid_, url): |
283 """Update the avatar of the given contact | 289 """Update the avatar of the given contact |
284 | 290 |
292 | 298 |
293 | 299 |
294 class ContactsPanel(BaseContactsPanel): | 300 class ContactsPanel(BaseContactsPanel): |
295 """The contact list that is displayed on the left side.""" | 301 """The contact list that is displayed on the left side.""" |
296 | 302 |
297 def __init__(self, host): | 303 def __init__(self, parent): |
298 BaseContactsPanel.__init__(self, host, handle_click=True, handle_menu=True) | 304 BaseContactsPanel.__init__(self, parent, handle_click=True, handle_menu=True) |
299 | 305 |
300 def setState(self, jid_, type_, state): | 306 def setState(self, jid_, type_, state): |
301 """Change the appearance of the contact, according to the state | 307 """Change the appearance of the contact, according to the state |
308 | |
302 @param jid_ (jid.JID): jid.JID which need to change state | 309 @param jid_ (jid.JID): jid.JID which need to change state |
303 @param type_ (unicode): one of "availability", "messageWaiting" | 310 @param type_ (unicode): one of "availability", "messageWaiting" |
304 @param state: | 311 @param state: |
305 - for messageWaiting type: | 312 - for messageWaiting type: |
306 True if message are waiting | 313 True if message are waiting |
311 if type_ == 'availability': | 318 if type_ == 'availability': |
312 if state is None: | 319 if state is None: |
313 state = C.PRESENCE_UNAVAILABLE | 320 state = C.PRESENCE_UNAVAILABLE |
314 setPresenceStyle(contact_box.label, state) | 321 setPresenceStyle(contact_box.label, state) |
315 elif type_ == 'messageWaiting': | 322 elif type_ == 'messageWaiting': |
316 contact_box.setMessageWaiting(state) | 323 contact_box.setAlert(state) |
317 | 324 |
318 | 325 |
319 class ContactTitleLabel(base_widget.DragLabel, Label, ClickHandler): | 326 class ContactTitleLabel(base_widget.DragLabel, Label, ClickHandler): |
327 | |
320 def __init__(self, host, text): | 328 def __init__(self, host, text): |
321 Label.__init__(self, text) # , Element=DOM.createElement('div') | 329 Label.__init__(self, text) # , Element=DOM.createElement('div') |
322 self.setStyleName('contactTitle') | 330 self.setStyleName('contactTitle') |
323 base_widget.DragLabel.__init__(self, text, "CONTACT_TITLE", host) | 331 base_widget.DragLabel.__init__(self, text, "CONTACT_TITLE", host) |
324 ClickHandler.__init__(self) | 332 ClickHandler.__init__(self) |
332 """Manage the contacts and groups""" | 340 """Manage the contacts and groups""" |
333 | 341 |
334 def __init__(self, host): | 342 def __init__(self, host): |
335 QuickContactList.__init__(self, host, C.PROF_KEY_NONE) | 343 QuickContactList.__init__(self, host, C.PROF_KEY_NONE) |
336 SimplePanel.__init__(self) | 344 SimplePanel.__init__(self) |
345 self.host = host | |
337 self.scroll_panel = ScrollPanel() | 346 self.scroll_panel = ScrollPanel() |
338 self.vPanel = VerticalPanel() | 347 self.vPanel = VerticalPanel() |
339 _title = ContactTitleLabel(host, 'Contacts') | 348 _title = ContactTitleLabel(host, 'Contacts') |
340 DOM.setStyleAttribute(_title.getElement(), "cursor", "pointer") | 349 DOM.setStyleAttribute(_title.getElement(), "cursor", "pointer") |
341 self._contacts_panel = ContactsPanel(host) | 350 self._contacts_panel = ContactsPanel(self) |
342 self._contacts_panel.setStyleName('contactPanel') # FIXME: style doesn't exists ! | 351 self._contacts_panel.setStyleName('contactPanel') # FIXME: style doesn't exists ! |
343 self._group_panel = GroupPanel(self) | 352 self._group_panel = GroupPanel(self) |
344 | 353 |
345 self.vPanel.add(_title) | 354 self.vPanel.add(_title) |
346 self.vPanel.add(self._group_panel) | 355 self.vPanel.add(self._group_panel) |
567 """Tell if the given group actually has visible members | 576 """Tell if the given group actually has visible members |
568 | 577 |
569 @param group (unicode): the group to check | 578 @param group (unicode): the group to check |
570 @return: boolean | 579 @return: boolean |
571 """ | 580 """ |
581 raise Exception # FIXME: remove this method | |
572 for jid_ in self.groups[group]: | 582 for jid_ in self.groups[group]: |
573 if self._contacts_panel.getContactBox(jid_).isVisible(): | 583 if self._contacts_panel.getContactBox(jid_).isVisible(): |
574 return True | 584 return True |
575 return False | 585 return False |
576 | 586 |