7 from org.maemo.hermes.engine.names import canonical, variants
8 from pygobject import *
11 # Constants from http://library.gnome.org/devel/libebook/stable/EContact.html#EContactField
12 ebook = CDLL('libebook-1.2.so.5')
13 E_CONTACT_HOMEPAGE_URL = 42
16 E_CONTACT_BIRTHDAY_DATE = 107
20 """Provide an abstraction of contact, working around limitations
21 in the evolution-python bindings. Properties are defined at:
23 http://library.gnome.org/devel/libebook/stable/EContact.html#id3066469
25 Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
26 Released under the Artistic Licence."""
29 # -----------------------------------------------------------------------
30 def __init__(self, book, contact):
31 """Create a new contact store for modifying contacts in the given
35 self._contact = contact
36 self._identifiers = self._find_ids()
39 # -----------------------------------------------------------------------
41 """Return a set of the identifiers which should be used to match this
42 contact. Includes variants of first name, last name, nickname and
43 email address. These are all Unicode-normalised into the traditional
47 for name in variants(self._contact.get_name()):
48 result.add(canonical(name))
50 for name in variants(self._contact.get_property('nickname')):
51 result.add(canonical(name))
53 for email in self.get_emails():
54 user = canonical(email.split('@')[0])
61 # -----------------------------------------------------------------------
63 """Return this contact's name."""
65 return self._contact.get_name() or self._contact.get_property('nickname')
68 # -----------------------------------------------------------------------
69 def get_identifiers(self):
70 """Return the lowercase, Unicode-normalised, all-alphabetic
71 versions of identifiers for this contact."""
73 return self._identifiers
76 # -----------------------------------------------------------------------
77 def set_photo(self, url):
78 """Set the given contact's photo to the picture found at the URL. If the
79 photo is wider than it is tall, it will be cropped with a bias towards
80 the top of the photo."""
83 f = urllib.urlopen(url)
91 im = Image.open(StringIO.StringIO(data))
94 ##print u"Shrinking photo for %s as it's %d x %d" % (self._contact.get_name(), w, h)
95 im = ImageOps.fit(im, (w, w), Image.NEAREST, 0, (0, 0.1))
97 ## print u"Updating photo for %s" % (self._contact.get_name())
98 f = StringIO.StringIO()
100 image_data = f.getvalue()
101 photo = EContactPhoto()
103 photo.data = EContactPhoto_data()
104 photo.data.inlined = EContactPhoto_inlined()
105 photo.data.inlined.mime_type = cast(create_string_buffer("image/jpeg"), c_char_p)
106 photo.data.inlined.length = len(image_data)
107 photo.data.inlined.data = cast(create_string_buffer(image_data), c_void_p)
108 ebook.e_contact_set(hash(self._contact), E_CONTACT_PHOTO, addressof(photo))
111 print "FAILED to get photo from URL %s" % url
115 # -----------------------------------------------------------------------
121 # -----------------------------------------------------------------------
122 def set_birthday(self, day, month, year = 0):
123 """Set the birthday for this contact to the given day, month and year."""
126 year = datetime.date.today().year
128 birthday = EContactDate()
130 birthday.month = month
132 print u"Setting birthday for [%s] to %d-%d-%d" % (self._contact.get_name(), year, month, day)
133 ebook.e_contact_set(hash(self._contact), E_CONTACT_BIRTHDAY_DATE, addressof(birthday))
137 # -----------------------------------------------------------------------
138 def set_nickname(self, nickname):
139 """Set the nickname for this contact to the given nickname."""
141 # FIXME does this work?
142 self._contact.set_property('nickname', nickname)
143 #ebook.e_contact_set(hash(self._contact), E_NICKNAME, addressof(nickname))
146 # -----------------------------------------------------------------------
147 def get_emails(self):
148 """Return the email addresses associated with this contact."""
151 ai = GList.new(ebook.e_contact_get_attributes(hash(self._contact), E_CONTACT_EMAIL))
153 attr = ai.next(as_a = EVCardAttribute)
155 raise Exception(u"Unexpected null attribute for [" + self._contact.get_name() + "] with emails " + emails)
156 emails.append(string_at(attr.value().next()))
162 # -----------------------------------------------------------------------
164 """Return a list of URLs which are associated with this contact."""
167 ai = GList.new(ebook.e_contact_get_attributes(hash(self._contact), E_CONTACT_HOMEPAGE_URL))
169 attr = ai.next(as_a = EVCardAttribute)
171 raise Exception(u"Unexpected null attribute for [" + self._contact.get_name() + "] with URLs " + urls)
172 urls.append(string_at(attr.value().next()))
177 # -----------------------------------------------------------------------
178 def add_url(self, str, unique = ''):
179 """Add a new URL to the set of URLs for the given contact."""
181 urls = re.findall('(?:(?:ftp|https?):\/\/|\\bwww\.|\\bftp\.)[,\w\.\-\/@:%?&=%+#~_$\*]+[\w=\/&=+#]', str, re.I | re.S)
184 updated = self._add_url(url, unique or re.sub('(?:.*://)?(\w+(?:[\w\.])*).*', '\\1', url)) or updated
189 # -----------------------------------------------------------------------
190 def _add_url(self, url, unique):
191 """Do the work of adding a unique URL to a contact."""
194 ai = GList.new(ebook.e_contact_get_attributes(hash(self._contact), E_CONTACT_HOMEPAGE_URL))
196 attr = ai.next(as_a = EVCardAttribute)
197 existing = string_at(attr.value().next())
198 #print "Existing URL [%s] when adding [%s] to [%s] with constraint [%s]" % (existing, url, contact.get_name(), unique)
199 if existing == unique or existing == url:
201 elif existing.find(unique) > -1:
206 url_attr = EVCardAttribute()
208 url_attr.name = 'URL'
211 ##print u"Setting URL for [%s] to [%s]" % (self._contact.get_name(), url)
212 val.set(create_string_buffer(url))
213 ai.set(addressof(url_attr))
214 url_attr.values = cast(addressof(val), POINTER(GList))
215 ebook.e_contact_set_attributes(hash(self._contact), E_CONTACT_HOMEPAGE_URL, addressof(ai))