comparison frontends/src/quick_frontend/quick_contact_list.py @ 2015:20fb71b656e3

quick_frontend, primitivus (contact_list): improved and simplified handling of "special" entities: - special_extras has been removed - specials handle all entities (bare + full) in a single set
author Goffi <goffi@goffi.org>
date Sun, 24 Jul 2016 17:47:09 +0200
parents 8c4087fd034a
children f09562b0704d
comparison
equal deleted inserted replaced
2014:0694a2611bad 2015:20fb71b656e3
54 # bare jids as keys, resources are used in data 54 # bare jids as keys, resources are used in data
55 # XXX: we don't mutualise cache, as values may differ 55 # XXX: we don't mutualise cache, as values may differ
56 # for different profiles (e.g. directed presence) 56 # for different profiles (e.g. directed presence)
57 self._cache = {} 57 self._cache = {}
58 58
59 # special entities (groupchat, gateways, etc), bare jids 59 # special entities (groupchat, gateways, etc)
60 # may be bare or full jid
60 self._specials = set() 61 self._specials = set()
61 # extras are specials with full jids (e.g.: private MUC conversation)
62 self._special_extras = set()
63 62
64 # group data contain jids in groups and misc frontend data 63 # group data contain jids in groups and misc frontend data
65 # None key is used for jids with not group 64 # None key is used for jids with not group
66 self._groups = {} # groups to group data map 65 self._groups = {} # groups to group data map
67 66
175 174
176 @param entity(jid.JID): bare jid of entity 175 @param entity(jid.JID): bare jid of entity
177 @raise (KeyError): entity is unknown 176 @raise (KeyError): entity is unknown
178 """ 177 """
179 return self._cache[entity] 178 return self._cache[entity]
180
181 def getSpecialExtras(self, special_type=None):
182 """Return special extras with given type
183
184 If special_type is None, return all special extras.
185
186 @param special_type(unicode, None): one of special type (e.g. C.CONTACT_SPECIAL_GROUP)
187 None to return all special extras.
188 @return (set[jid.JID])
189 """
190 if special_type is None:
191 return self._special_extras
192 specials = self.getSpecials(special_type)
193 return {extra for extra in self._special_extras if extra.bare in specials}
194 179
195 def _gotContacts(self, contacts): 180 def _gotContacts(self, contacts):
196 """Called during filling, add contacts and notice parent that contacts are filled""" 181 """Called during filling, add contacts and notice parent that contacts are filled"""
197 for contact in contacts: 182 for contact in contacts:
198 self.host.newContactHandler(*contact, profile=self.profile) 183 self.host.newContactHandler(*contact, profile=self.profile)
287 272
288 def setSpecial(self, entity, special_type): 273 def setSpecial(self, entity, special_type):
289 """Set special flag on an entity 274 """Set special flag on an entity
290 275
291 @param entity(jid.JID): jid of the special entity 276 @param entity(jid.JID): jid of the special entity
277 if the jid is full, will be added to special extras
292 @param special_type: one of special type (e.g. C.CONTACT_SPECIAL_GROUP) or None to remove special flag 278 @param special_type: one of special type (e.g. C.CONTACT_SPECIAL_GROUP) or None to remove special flag
293 """ 279 """
294 assert special_type in C.CONTACT_SPECIAL_ALLOWED + (None,) 280 assert special_type in C.CONTACT_SPECIAL_ALLOWED + (None,)
295 self.setCache(entity, C.CONTACT_SPECIAL, special_type) 281 self.setCache(entity, C.CONTACT_SPECIAL, special_type)
296 282
297 def getSpecials(self, special_type=None): 283 def getSpecials(self, special_type=None, bare=False):
298 """Return all the bare JIDs of the special roster entities of with given type. 284 """Return all the bare JIDs of the special roster entities of with given type.
299 285
300 If special_type is None, return all specials. 286 @param special_type(unicode, None): if not None, filter by special type (e.g. C.CONTACT_SPECIAL_GROUP)
301 @param special_type: one of special type (e.g. C.CONTACT_SPECIAL_GROUP) or None to return all specials. 287 @param bare(bool): return only bare jids if True
302 @return: set(jid.JID) 288 @return (iter[jid.JID]): found special entities
303 """ 289 """
304 if special_type is None: 290 for entity in self._specials:
305 return self._specials 291 if bare and entity.resource:
306 return set([entity for entity in self._specials if self.getCache(entity, C.CONTACT_SPECIAL) == special_type]) 292 continue
307 293 if special_type is not None and self.getCache(entity, C.CONTACT_SPECIAL) != special_type:
294 continue
295 yield entity
308 296
309 def disconnect(self): 297 def disconnect(self):
310 # for now we just clear contacts on disconnect 298 # for now we just clear contacts on disconnect
311 self.clearContacts() 299 self.clearContacts()
312 300
318 self.select(None) 306 self.select(None)
319 if not keep_cache: 307 if not keep_cache:
320 self._cache.clear() 308 self._cache.clear()
321 self._groups.clear() 309 self._groups.clear()
322 self._specials.clear() 310 self._specials.clear()
323 self._special_extras.clear()
324 self._roster.clear() 311 self._roster.clear()
325 self.update() 312 self.update()
326 313
327 def setContact(self, entity, groups=None, attributes=None, in_roster=False): 314 def setContact(self, entity, groups=None, attributes=None, in_roster=False):
328 """Add a contact to the list if doesn't exist, else update it. 315 """Add a contact to the list if doesn't exist, else update it.
367 354
368 # special entities management 355 # special entities management
369 if C.CONTACT_SPECIAL in attributes: 356 if C.CONTACT_SPECIAL in attributes:
370 if attributes[C.CONTACT_SPECIAL] is None: 357 if attributes[C.CONTACT_SPECIAL] is None:
371 del attributes[C.CONTACT_SPECIAL] 358 del attributes[C.CONTACT_SPECIAL]
372 self._specials.remove(entity_bare) 359 self._specials.remove(entity)
373 else: 360 else:
374 self._specials.add(entity_bare) 361 self._specials.add(entity)
375 cache[C.CONTACT_MAIN_RESOURCE] = None 362 cache[C.CONTACT_MAIN_RESOURCE] = None
376 363
377 # now the attributes we keep in cache 364 # now the attributes we keep in cache
378 for attribute, value in attributes.iteritems(): 365 for attribute, value in attributes.iteritems():
379 cache[attribute] = value 366 cache[attribute] = value
439 del self._cache[entity_bare] 426 del self._cache[entity_bare]
440 for group in groups: 427 for group in groups:
441 self._groups[group]['jids'].remove(entity_bare) 428 self._groups[group]['jids'].remove(entity_bare)
442 if not self._groups[group]['jids']: 429 if not self._groups[group]['jids']:
443 self._groups.pop(group) # FIXME: we use pop because of pyjamas: http://wiki.goffi.org/wiki/Issues_with_Pyjamas/en 430 self._groups.pop(group) # FIXME: we use pop because of pyjamas: http://wiki.goffi.org/wiki/Issues_with_Pyjamas/en
444 for iterable in (self._selected, self._specials, self._special_extras): 431 for iterable in (self._selected, self._specials):
445 to_remove = set() 432 to_remove = set()
446 for set_entity in iterable: 433 for set_entity in iterable:
447 if set_entity.bare == entity.bare: 434 if set_entity.bare == entity.bare:
448 to_remove.add(set_entity) 435 to_remove.add(set_entity)
449 iterable.difference_update(to_remove) 436 iterable.difference_update(to_remove)