Archived:Python on Symbian/05. Contacts and Calendar

From Nokia Developer Wiki
Jump to: navigation, search

Archived.pngAquivado: Este artigo foi arquivado, pois o conteúdo não é mais considerado relevante para se criar soluções comerciais atuais. Se você achar que este artigo ainda é importante, inclua o template {{ForArchiveReview|escreva a sua justificativa}}.

All PySymbian articles have been archived. PySymbian is no longer maintained by Nokia and is not guaranteed to work on more recent Symbian devices. It is not possible to submit apps to Nokia Store.

Original Author: bogdan.galiceanu

Mobile devices are, for many people, the most important and personal tool that they own; they hold all their important contacts, and are used to organize their busy social and work lives.

Access to APIs that interact with a user's contacts and calendar enables compelling and personal applications to be developed. Python on Symbian provides access to contacts and calendar data through the contacts and e32calendar modules.




The contacts module provides an API that allows you to open the default phone book on the device to perform operations such as searching, reading, adding, modifying and deleting entries.

The contacts database is represented by a ContactDb, which contains a number of Contact objects, which in turn contain ContactField objects. The ContactDb is a dictionary-like object that is indexed by the unique IDs of any Contacts that are contained. Contacts are list-like objects that are indexed using the field indices of the contained ContactField objects.

ContactDb represents a live view of the database. Changes committed to the database are visible to outside applications immediately and vice versa. Contacts are locked for editing before modification, and released immediately afterwards.

The following sections explain how to search for, add, delete and modify contacts and how to work with contact groups. Additional information is available at http://pys60.garage.maemo.org/doc/s60/module-contacts.html.

Opening the database

A database must be opened before any contacts operations can be performed. In order to open the device's default database, the contacts module open() method is called as shown below:

import contacts
#Open the default contacts database
db = contacts.open()

In theory, you can also create your own application-specific database by passing the name of the database and a mode to the open() method. However, this functionality is considered unreliable according to the official documentation found at http://pys60.garage.maemo.org/doc/s60/module-contacts.html and is, in any case, of limited use.

There is no need to explicitly close the contact database; it will automatically be closed when the contacts object goes out of scope.

Adding a contact

To create a new contact, first open the database, create a Contact object, add the desired fields and values and save it by calling commit().

The following code fragment creates a new contact, specifying a first name and mobile number.

import contacts
#Open the default contact database
db = contacts.open()
#Add new contact's details
c = db.add_contact()
c.add_field('first_name', 'Samantha')
c.add_field('mobile_number', '0123456789')
#And save the changes

The following table lists the most common field types available from Nokia S60 (3rd Edition) onwards. Fields with these types are added using add_field(), which uses the same syntax as the previous code fragment.

Table 5.1: Contact fields
city company_name country date
dtmf_string email_address extended_address fax_number
first_name job_title last_name mobile_number
note pager_number phone_number po_box
postal_address postal_code state street_address
url video_number picture second_name
voip sip_id personal_ringtone share_view
prefix suffix push_to_talk locationid_indication

The official documentation at http://pys60.garage.maemo.org/doc/s60/node83.html explains what data type they can be assigned, and also lists a few fields that are recognized but that cannot be created.

Deleting a contact

The next section shows how to find the ID of a specific contact and, once the ID is known, a contact may be deleted from the database by using the del operator with its ID. The following code fragment shows how to delete the first Contact object that has 'Samantha' in its name:

import contacts
#Open the default contact database
db = contacts.open()
#Search for a contact whose name is Samantha
l = db.find('Samantha')
#l is a list of contacts matching the criterion
#We only need the first one, if it exists
if len(l) > 0:
c = l[0]
#Get its ID
id = c.id
#Delete it
del db[id]
print "No such contact found"

Finding contacts

The contacts database can be queried for contacts that have a certain string in any of their fields using the find() method, passing the search string as its argument. The search can then be refined to see if a certain field matches the search criteria.

For example, the following code fragment first retrieves all contacts that have the text "James" in any field, and then displays information for those contacts that have "James" in the first_name field (only).

import contacts
#Open the database
db = contacts.open()
#Retrieve every contact that contains the name "James"
#and display only those that have it in the first_name field
for c in db.find('James'):
if c.find('first_name')[0].value == u"James":
print c.find('first_name')[0].value + " " + c.find('last_name')[0].value + " " c.find('mobile_number')[0].value

Modifying existing contacts

Modifying a contact can be done in two ways: A simple way is to just make the changes and then call the contact object's commit() method, which saves them.


  1. call the contact object's begin() method, which locks the contact for editing (thus making it inaccessible to other applications)
  2. make the changes
  3. then call the contact object's commit method, which releases the lock and saves the changes.

Should you wish to undo the changes, you can simply call the object's rollback() method instead of commit(), which releases the lock and restores the contact to the way it was before begin*( was called

New fields can be added, as shown in the section Adding a contact, and existing fields, labels and values can also be customized, as demonstrated in the following example.

#The changes are undone at the end
import contacts
db = contacts.open()
c = db.find('Jim')[0]
#Retrieve the "last_name" field if it exists, change its value to some other name and its label to "Surname"
if c.find("last_name"):
c.find("last_name")[0].value = u"Cohen"
c.find("last_name")[0].label = u"Surname"
#Undo the changes

#The changes are saved and the contact remains modified
import contacts
db = contacts.open()
c = db.find('Jim')[0]
#Retrieve the "last_name" field if it exists, change its value to some other name and its label to "Surname"
if c.find("last_name"):
c.find("last_name")[0].value = u"Cohen"
c.find("last_name")[0].label = u"Surname"
#Save the changes

Finally, individual fields can be removed from the contact using the del operator.

Working with groups

Python on Symbian allows you to create and access related contacts using Group objects, and gives access to a set of Group objects through a Groups object.

In simple terms, a Group is a list-like object containing the IDs of Contact objects belonging to that group. A Groups object is a dictionary-like collection of all the Group objects from the database, which can each be accessed using a Group's unique ID.

As with any contact operation, the database must be opened before any of the group operations may be performed.

Creating a new group

After creating a Groups object, its add_group(name) method is used to create a new group (a new Group object).

The following code fragment adds the group 'My new group' to the Groups object (and hence to the database):

import contacts
#Open the database
db = contacts.open()
#Instantiate a Groups object
groups = db.Groups(db)
#Add a new group
group = groups.add_group(u"My new group")

Retrieving existing groups

Groups are identified by their unique ID. A list of the unique group IDs can be obtained by calling Python's built-in list() function on the iterator object, which is returned by calling Python's built-in iter() function on the Groups object.

The following code fragment uses the list iterator to print out the names of all the groups, based on their id:

import contacts
#Open the database
db = contacts.open()
#Get a list of IDs of the available groups
ids = list(iter(db.groups))
#Show the names of the groups
for id in ids:
print db.groups[id].name

Deleting a group

A group is deleted from a Groups object and, simultaneously, from the database by using Python's del() operator. The following code fragment gets the list of available groups by ID, then calls del() to remove a specific Group object:

import contacts
#Open the database
db = contacts.open()
#Get a list of IDs of the available groups
ids = list(iter(db.groups))
#Remove the group whose ID is first in the list
del db.groups[ids[0]]

Note.pngNote: Deleting a group will not delete its members, that is, the contacts that are in the group are not deleted from the contacts database, but remain in the phone's contact list.

Adding and removing contacts from a group

Calling the append(id) method of a Group object adds a contact with the corresponding ID to the group, as shown in the following code.

import contacts
#Open the database
db = contacts.open()
#Get a list of IDs of the available groups
group_ids = list(iter(db.groups))
#Open the first group in the list
group = db.groups[group_ids[0]]
#Get a list of all the contact IDs
contact_ids = contacts.open().keys()
#Add the first contact in the list

To remove a contact from a group, we use the del() operator on the group.



Calendar data is accessed in much the same way as contacts data. A calendar is represented by a CalendarDb object that contains Entry objects. Any new entries or changes saved to existing entries in a Python application appear in the device's native Calendar application, and vice versa.

The available entry types are classes derived from the main Entry class, as follows:

  • AppointmentEntry - returned by the add_appointment() method
  • EventEntry - returned by the add_event() method
  • AnniversaryEntry - returned by the add_anniversary() method
  • ReminderEntry - returned by the add_reminder() method
  • ToDoEntry - returned by the add_todo() method

Adding entries

Creating a calendar entry is simple: open a database, call one of its methods (depending on what type of entry you opt for), optionally give values to the attributes of the entry and save the changes.

The following snippet demonstrates how to add an appointment that expires at a certain time. The content attribute of the Entry class is used to specify the subject of the appointment – a short description that will be shown in the phone’s Calendar application. The location attribute is used to specify the location of the appointment. The set_time() function is used to specify the time frame during which the appointment entry will be valid.

After creating the entry it is important to save it using the commit() method.

import e32calendar, appuifw
#Open the database
db = e32calendar.open()
#Create an appointment entry
appointment = db.add_appointment()
#Add the regular information
appointment.content = appuifw.query(u"Enter subject", "text")
appointment.location = appuifw.query(u"Enter location", "text")
#Ask the user for the start and end time
t1 = appuifw.query(u"Enter start hour", "time")
d1 = appuifw.query(u"Enter start date", "date")
t2 = appuifw.query(u"Enter end hour", "time")
d2 = appuifw.query(u"Enter end date", "date")
start_time = t1 + d1
end_time = t2 + d2
#Set the start and end time
appointment.set_time(start_time, end_time)
#Save the entry

The following code creates a simple to do calendar entry and, after a few seconds, asks the user if it's been done, marking it as complete if it is.

import e32calendar, appuifw, e32, time
app_lock = e32.Ao_lock()
def quit():
appuifw.app.exit_key_handler = quit
#Open the database
db = e32calendar.open()
#Create a to do entry
todo = db.add_todo()
#Add information about the subject
todo.content = appuifw.query(u"Enter subject", "text")
#Ask the user for the start and end time
t1 = appuifw.query(u"Enter start hour", "time")
d1 = appuifw.query(u"Enter start date", "date")
t2 = appuifw.query(u"Enter end hour", "time")
d2 = appuifw.query(u"Enter end date", "date")
start_time = t1 + d1
end_time = t2 + d2
#Set the start and end time
todo.set_time(start_time, end_time)
appuifw.note(u"Entry created!")
#Create a function that asks if the user has completed the to do
def todo_handler():
answer = appuifw.query(u"Have you finished the to do?", "query")
if answer == True:
#The user no longer needs the entry active in the calendar since it's been taken care of
todo.cross_out = True
#To check when the entry was crossed out we use the crossed_out_time attribute
appuifw.note(u"Entry crossed out at " + time.ctime(todo.cross_out_time))
#Instantiate a timer and use it to call the function after 10 seconds
t = e32.Ao_timer()
t.after(10, todo_handler)
#Save the entry

Calendar entries often have associated alarms for attracting the user’s attention. Alarms are set using the entry's alarm attribute. Note that alarms can only be enabled for entries of type AppointmentEntry and AnniversaryEntry; on other event types the alarm will not go off. Note also that setting the alarm to None cancels it.

The following example code illustrates a calendar entry that is meant to remind to user to pick up a gift for an anniversary:

import e32calendar, time
#Open the database
db = e32calendar.open()
#Create an anniversary entry
anniversary = db.add_anniversary()
#Set the alarm for this time tomorrow, and give the entry highest priority
anniversary.set_time(time.time() + 86400)
anniversary.content = u"Pick up gift for Shelley"
anniversary.priority = 1
anniversary.alarm = time.time() + 86400

Entries can also be repeated, which means they become active at regular intervals based on associated repeat rules. For example, a person can have a calendar entry to remind them of another person's birthday. This entry should repeat every year on the same day.

import e32calendar, time
#Open the database
db = e32calendar.open()
#Add an anniversary entry
anniversary = db.add_anniversary()
anniversary.content = u"Hannah's birthday!"
anniversary.set_time(time.time() + 86400)
#Define the repeat rule
repeat = {"type":"yearly_by_date",
"start":time.time() + 86400,

Displaying and deleting entries

The find_instances(start_date, end_date, search_str=u""[ , appointments=0, events=0, anniversaries=0, todos=0, reminders=0]) method, called on the database, can be used to find all the calendar entries within a time frame that match the search criteria.

find_instances() returns a list of dictionaries that have the IDs of the entries and, using the subscript notation, the actual Entry object can be retrieved and its information can be displayed.

import e32calendar, appuifw, time
db = e32calendar.open()
#Find all entries between two dates given by the user that contain the word "birthday"
start = appuifw.query(u"Enter start date", "date")
end = appuifw.query(u"Enter end date", "date")
entries = db.find_instances(start, end, u"birthday")
#Display their subject and date
for i in entries:
print "Description: " + db[i["id"]].content
print "Date: " + time.strftime("%H:%M %m/%d/%Y", time.localtime(db[i["id"]].start_time))

Deleting an entry is similar to deleting a contact: once the ID is acquired, calling the del() operator on the object removes the entry.


This chapter has demonstrated how to perform operations on the device's contacts and calendar data, including:

  • adding and deleting contacts
  • retrieving information such as name and phone number
  • creating and removing calendar entries of various types.

Licence icon cc-by-sa 3.0-88x31.png© 2010 Symbian Foundation Limited. Portions copyright Bogdan Galiceanu, Hamish Willee, Marcelo Barros de Almeida, Mike Jipping, Pankaj Nathani and others in wiki document history list. This document is licensed under the Creative Commons Attribution-Share Alike 2.0 license. See http://creativecommons.org/licenses/by-sa/2.0/legalcode for the full terms of the license.
Note that this content was originally hosted on the Symbian Foundation developer wiki.

This page was last modified on 8 May 2013, at 09:23.
59 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.


Thank you!

We appreciate your feedback.