6 import util.coroutines as coroutines
7 import util.misc as util_misc
10 _moduleLogger = logging.getLogger("gvoice.addressbook")
13 class Addressbook(object):
15 def __init__(self, backend):
16 self._backend = backend
18 self._addedContacts = set()
19 self._removedContacts = set()
20 self._changedContacts = set()
22 self.updateSignalHandler = coroutines.CoTee()
24 def update(self, force=False):
25 if not force and self._contacts:
27 oldContacts = self._contacts
28 oldContactIds = set(self.get_contacts())
31 self._populate_contacts()
32 newContactIds = set(self.get_contacts())
34 self._addedContacts = newContactIds - oldContactIds
35 self._removedContacts = oldContactIds - newContactIds
36 self._changedContacts = set(
38 for contactId in newContactIds.intersection(oldContactIds)
39 if self._has_contact_changed(contactId, oldContacts)
42 if self._addedContacts or self._removedContacts or self._changedContacts:
43 message = self, self._addedContacts, self._removedContacts, self._changedContacts
44 self.updateSignalHandler.stage.send(message)
46 def get_contacts(self):
47 return self._contacts.iterkeys()
49 def get_contact_name(self, contactId):
50 return self._contacts[contactId][0]
52 def get_contact_details(self, contactId):
53 self._populate_contact_details(contactId)
54 return self._get_contact_details(contactId)
56 def find_contacts_with_number(self, queryNumber):
57 strippedQueryNumber = util_misc.strip_number(queryNumber)
58 for contactId, (contactName, contactDetails) in self.get_contacts():
59 for phoneType, number in contactDetails:
60 if number == strippedQueryNumber:
63 def _populate_contacts(self):
66 contacts = self._backend.get_contacts()
67 for contactId, contactDetails in contacts:
68 contactName = contactDetails["name"]
71 numberDetails.get("phoneType", "Mobile"),
72 util_misc.strip_number(numberDetails["phoneNumber"]),
74 for numberDetails in contactDetails["numbers"]
76 self._contacts[contactId] = (contactName, contactNumbers)
78 def _populate_contact_details(self, contactId):
79 if self._get_contact_details(contactId):
81 self._get_contact_details(contactId).extend(
82 self._backend.get_contact_details(contactId)
85 def _get_contact_details(self, contactId):
86 return self._contacts[contactId][1]
88 def _has_contact_changed(self, contactId, oldContacts):
89 oldContact = oldContacts[contactId]
90 oldContactName = oldContact[0]
91 oldContactDetails = oldContact[1]
92 if oldContactName != self.get_contact_name(contactId):
94 if not oldContactDetails:
96 # if its already in the old cache, purposefully add it into the new cache
97 return oldContactDetails != self.get_contact_details(contactId)