Wednesday, October 12, 2011

Read/Edit Phone Contacts Using Qt

Here I'm posting a code snippet I used to modify my contacts on both SIM card and phone memory. What this code does is that it loops over all available memories on phone and edits each number according to a criteria I set. To simplify the code, I removed the business parts and posted only the parts related to Qt Framework and the loop over the contacts.

 The skeleton of the process is as follows:

  1. Get all available manager on device. In my case they where "symbian" (i.e: phone memory) and "symbiansim" (i.e: SIM card)
  2. Loop over the list of managers.
  3. For each manager, get the ids of available contacts.
  4. For each contact id, get all the available phone numbers.
  5. For each phone number, decide if it needs to be changed (the business part), or just output the number or use it however you want.
  6. A couple of flags are set to save any changes in a number/contact


[*.pro]
symbian:TARGET.CAPABILITY += ReadUserData WriteUserData

CONFIG += mobility
MOBILITY += contacts


[*.h]
#include <QContactManager>
#include <QContact>
#include <QContactPhoneNumber>

QTM_USE_NAMESPACE


[*.cpp]
//find all the available mamagers on device
QStringList managers = QContactManager::availableManagers();

//loop on all the available managers
for(int m=0; m<managers.length(); m++)
{
    //initialize a new contact manager with one of the ids in "mamagers" list
    QContactManager cManager(managers.at(m));

    QList<QContactLocalId> idsList = cManager.contactIds();
    
    //loop on all the available contacts
    for(int i=0; i<idsList.length(); i++)
    {
        QContact contact = cManager.contact(idsList.at(i));
        bool contactEdited = false;
        
        //get all contact details the can be considered a phone numbers (mobile, home .. etc)
        QList<QContactPhoneNumber> phoneNumbers = contact.details<QContactPhoneNumber>();

        //iterate on the phone numbers of the contact
        for(int idx=0; idx<phoneNumbers.length(); idx++)
        {
            QContactPhoneNumber phone = phoneNumbers.at(idx);
            QString number = phone.value(QContactPhoneNumber::FieldNumber);
            bool numberEdited = false;

            // ################### Editing Zone #################
            
            // here you put any operations related to editing the number
            // and set the "edited" flag to true if you changed the number
            
            // ##################################################

            //if the number is edited, save it in the "contact" object
            if(numberEdited)
            {
                phone.setNumber(number);
                contact.saveDetail(&phone);
                
                //raise the contactEdited flag to save the contact later
                contactEdited = true;
            }
        } // end of numbers loop

        if(contactEdited)
        {
            //save the edited contact
            cManager.saveContact(&contact);
        }
    } // end of contacts loop
} // end of managers loop


Here are some notes about this code:
- If you need to interact with one manager, just pass one item to the "managers" list, or simply remove the managers loop.and set the manager manually.
QContactManager cManager("symbiansim");
- It is a good practice to not freeze the application with all these nested loops. So if you are sure that no other event can cause a problem while executing these operations, you can insert this line inside each loop.
qApp->processEvents();
- Self-signing is enough to get this code running on a Symbian device.