comparison frontends/src/quick_frontend/quick_contact_list.py @ 1972:02d21a589be2

quick_frontend, primitivus: notifications refactoring replaced old "alerts" system by a more generic one which use listeners and can activate callbacks on notification click.
author Goffi <goffi@goffi.org>
date Mon, 27 Jun 2016 22:36:22 +0200
parents 633b5c21aefd
children 8c4087fd034a
comparison
equal deleted inserted replaced
1971:9421e721d5e2 1972:02d21a589be2
66 self._groups = {} # groups to group data map 66 self._groups = {} # groups to group data map
67 67
68 # contacts in roster (bare jids) 68 # contacts in roster (bare jids)
69 self._roster = set() 69 self._roster = set()
70 70
71 # alerts per entity (key: full jid, value: list of alerts)
72 self._alerts = {}
73
74 # selected entities, full jid 71 # selected entities, full jid
75 self._selected = set() 72 self._selected = set()
76 73
77 # we keep our own jid 74 # we keep our own jid
78 self.whoami = self.host.profiles[profile].whoami 75 self.whoami = self.host.profiles[profile].whoami
89 # FIXME: workaround for a pyjamas issue: calling hash on a class method always return a different value if that method is defined directly within the class (with the "def" keyword) 86 # FIXME: workaround for a pyjamas issue: calling hash on a class method always return a different value if that method is defined directly within the class (with the "def" keyword)
90 self.presenceListener = self.onPresenceUpdate 87 self.presenceListener = self.onPresenceUpdate
91 self.host.addListener('presence', self.presenceListener, [self.profile]) 88 self.host.addListener('presence', self.presenceListener, [self.profile])
92 self.nickListener = self.onNickUpdate 89 self.nickListener = self.onNickUpdate
93 self.host.addListener('nick', self.nickListener, [self.profile]) 90 self.host.addListener('nick', self.nickListener, [self.profile])
91 self.notifListener = self.onNotification
92 self.host.addListener('notification', self.notifListener, [self.profile])
93 # notifListener only update the entity, so we can re-use it
94 self.host.addListener('notificationsClear', self.notifListener, [self.profile])
94 95
95 def _showEmptyGroups(self, show_str): 96 def _showEmptyGroups(self, show_str):
96 # Called only by __init__ 97 # Called only by __init__
97 # self.update is not wanted here, as it is done by 98 # self.update is not wanted here, as it is done by
98 # handler when all profiles are ready 99 # handler when all profiles are ready
319 self._cache.clear() 320 self._cache.clear()
320 self._groups.clear() 321 self._groups.clear()
321 self._specials.clear() 322 self._specials.clear()
322 self._special_extras.clear() 323 self._special_extras.clear()
323 self._roster.clear() 324 self._roster.clear()
324 self._alerts.clear()
325 self.host.updateAlertsCounter()
326 self.update() 325 self.update()
327 326
328 def setContact(self, entity, groups=None, attributes=None, in_roster=False): 327 def setContact(self, entity, groups=None, attributes=None, in_roster=False):
329 """Add a contact to the list if doesn't exist, else update it. 328 """Add a contact to the list if doesn't exist, else update it.
330 329
390 @return (bool): True if that contact should be showed in the list 389 @return (bool): True if that contact should be showed in the list
391 """ 390 """
392 show = self.getCache(entity, C.PRESENCE_SHOW) 391 show = self.getCache(entity, C.PRESENCE_SHOW)
393 392
394 if check_resource: 393 if check_resource:
395 alerts = self._alerts.keys()
396 selected = self._selected 394 selected = self._selected
397 else: 395 else:
398 alerts = {alert.bare for alert in self._alerts}
399 selected = {selected.bare for selected in self._selected} 396 selected = {selected.bare for selected in self._selected}
400 return ((show is not None and show != C.PRESENCE_UNAVAILABLE) 397 return ((show is not None and show != C.PRESENCE_UNAVAILABLE)
401 or self.show_disconnected 398 or self.show_disconnected
402 or entity in alerts 399 or entity in selected
403 or entity in selected) 400 or self.host.getNotifs(entity.bare, profile=self.profile)
401 )
404 402
405 def anyEntityToShow(self, entities, check_resources=False): 403 def anyEntityToShow(self, entities, check_resources=False):
406 """Tell if in a list of entities, at least one should be shown 404 """Tell if in a list of entities, at least one should be shown
407 405
408 @param entities (list[jid.JID]): list of jids 406 @param entities (list[jid.JID]): list of jids
441 del self._cache[entity_bare] 439 del self._cache[entity_bare]
442 for group in groups: 440 for group in groups:
443 self._groups[group]['jids'].remove(entity_bare) 441 self._groups[group]['jids'].remove(entity_bare)
444 if not self._groups[group]['jids']: 442 if not self._groups[group]['jids']:
445 self._groups.pop(group) # FIXME: we use pop because of pyjamas: http://wiki.goffi.org/wiki/Issues_with_Pyjamas/en 443 self._groups.pop(group) # FIXME: we use pop because of pyjamas: http://wiki.goffi.org/wiki/Issues_with_Pyjamas/en
446 for iterable in (self._selected, self._alerts, self._specials, self._special_extras): 444 for iterable in (self._selected, self._specials, self._special_extras):
447 to_remove = set() 445 to_remove = set()
448 for set_entity in iterable: 446 for set_entity in iterable:
449 if set_entity.bare == entity.bare: 447 if set_entity.bare == entity.bare:
450 to_remove.add(set_entity) 448 to_remove.add(set_entity)
451 if isinstance(iterable, set): 449 iterable.difference_update(to_remove)
452 iterable.difference_update(to_remove)
453 else: # XXX: self._alerts is a dict
454 for item in to_remove:
455 del iterable[item]
456 self.update([entity], C.UPDATE_DELETE, self.profile) 450 self.update([entity], C.UPDATE_DELETE, self.profile)
457 451
458 def onPresenceUpdate(self, entity, show, priority, statuses, profile): 452 def onPresenceUpdate(self, entity, show, priority, statuses, profile):
459 """Update entity's presence status 453 """Update entity's presence status
460 454
498 """ 492 """
499 assert profile == self.profile 493 assert profile == self.profile
500 self.setCache(entity, 'nick', new_nick) 494 self.setCache(entity, 'nick', new_nick)
501 self.update([entity], C.UPDATE_MODIFY, profile) 495 self.update([entity], C.UPDATE_MODIFY, profile)
502 496
497 def onNotification(self, entity, notif, profile):
498 """Update entity with notification
499
500 @param entity(jid.JID): entity updated
501 @param notif(dict): notification data
502 @param profile: %(doc_profile)s
503 """
504 assert profile == self.profile
505 if entity is not None:
506 self.update([entity], C.UPDATE_MODIFY, profile)
507
503 def unselect(self, entity): 508 def unselect(self, entity):
504 """Unselect an entity 509 """Unselect an entity
505 510
506 @param entity(jid.JID): entity to unselect 511 @param entity(jid.JID): entity to unselect
507 """ 512 """
538 else: 543 else:
539 cache[C.CONTACT_SELECTED].add(entity.resource) 544 cache[C.CONTACT_SELECTED].add(entity.resource)
540 self._selected.add(entity) 545 self._selected.add(entity)
541 self.update([entity], C.UPDATE_SELECTION, profile=self.profile) 546 self.update([entity], C.UPDATE_SELECTION, profile=self.profile)
542 547
543 def getAlerts(self, entity, use_bare_jid=False, filter_=None):
544 """Return alerts set to this entity.
545
546 @param entity (jid.JID): entity
547 @param use_bare_jid (bool): if True, cumulate the alerts of all the resources sharing the same bare JID
548 @param filter_(iterable, None): alert to take into account,
549 None to count all of them
550 @return (list[unicode,None]): list of C.ALERT_* or None for undefined ones
551 """
552 return [] # FIXME: temporarily disabled
553 if not use_bare_jid:
554 alerts = self._alerts.get(entity, [])
555 else:
556 alerts = []
557 for contact, contact_alerts in self._alerts:
558 if contact.bare == entity:
559 alerts.extend(contact_alerts)
560 if filter_ is None:
561 return alerts
562 else:
563 return [alert for alert in alerts if alert in filter_]
564
565 def addAlert(self, entity, type_=None):
566 """Add an alert for this enity
567
568 @param entity(jid.JID): entity who received an alert (resource is significant)
569 @param type_(unicode, None): type of alert (C.ALERT_*)
570 None for generic alert
571 """
572 self._alerts.setdefault(entity, [])
573 self._alerts[entity].append(type_)
574 self.update([entity], C.UPDATE_MODIFY, self.profile)
575 self.host.updateAlertsCounter() # FIXME: ?
576
577 def removeAlerts(self, entity, use_bare_jid=True):
578 """Eventually remove an alert on the entity (usually for a waiting message).
579
580 @param entity(jid.JID): entity (resource is significant)
581 @param use_bare_jid (bool): if True, ignore the resource
582 """
583 if use_bare_jid:
584 to_remove = set()
585 for alert_entity in self._alerts:
586 if alert_entity.bare == entity.bare:
587 to_remove.add(alert_entity)
588 if not to_remove:
589 return # nothing changed
590 for entity in to_remove:
591 del self._alerts[entity]
592 self.update([to_remove], C.UPDATE_MODIFY, self.profile)
593 self.host.updateAlertsCounter() # FIXME: ?
594 else:
595 try:
596 del self._alerts[entity]
597 except KeyError:
598 return # nothing changed
599 else:
600 self.update([entity], C.UPDATE_MODIFY, self.profile)
601 self.host.updateAlertsCounter() # FIXME: ?
602
603 def showOfflineContacts(self, show): 548 def showOfflineContacts(self, show):
604 """Tell if offline contacts should shown 549 """Tell if offline contacts should shown
605 550
606 @param show(bool): True if offline contacts should be shown 551 @param show(bool): True if offline contacts should be shown
607 """ 552 """