qtmobility/plugins/contacts/maemo5/qcontactabook.cpp
changeset 5 453da2cfceef
parent 4 90517678cc4f
child 11 06b8e2af4411
--- a/qtmobility/plugins/contacts/maemo5/qcontactabook.cpp	Mon May 03 13:18:40 2010 +0300
+++ b/qtmobility/plugins/contacts/maemo5/qcontactabook.cpp	Fri May 14 16:41:33 2010 +0300
@@ -73,6 +73,7 @@
    QContactABook* that;
    bool *result;
    char *uid;
+   QContactManager::Error *error;
 };
 
 /* QContactABook */
@@ -109,7 +110,7 @@
   
   cbSharedData* d = static_cast<cbSharedData*>(data);
   if (!d){
-    qWarning() << "d has been deleted";
+    //qWarning() << "d has been deleted";
     return;
   }
   
@@ -127,7 +128,9 @@
     if (id)
       contactIds << id;
   }
-  d->that->_contactsAdded(contactIds);
+
+  if (!contactIds.isEmpty())
+    d->that->_contactsAdded(contactIds);
 }
 
 static void contactsChangedCB(OssoABookRoster *roster, OssoABookContact **contacts, gpointer data)
@@ -137,7 +140,7 @@
   
   cbSharedData* d = static_cast<cbSharedData*>(data);
   if (!d){
-    qWarning() << "d has been deleted";
+    //qWarning() << "d has been deleted";
     return;
   }
   
@@ -154,7 +157,9 @@
     if (id)
       contactIds << id;
   }
-  d->that->_contactsChanged(contactIds);
+
+  if (!contactIds.isEmpty())
+    d->that->_contactsChanged(contactIds);
 }
 
 static void contactsRemovedCB(OssoABookRoster *roster, const char **ids, gpointer data)
@@ -164,7 +169,7 @@
   
   cbSharedData* d = static_cast<cbSharedData*>(data);
   if (!d){
-    qWarning() << "d has been deleted";
+    //qWarning() << "d has been deleted";
     return;
   }
   
@@ -172,13 +177,15 @@
   QList<QContactLocalId> contactIds;
   
   for (p = ids; *p; ++p) {
-    QContactLocalId id = d->hash->take(*p);
-    QCM5_DEBUG << "Contact" << id << "has been removed";
-    if (id)
-      contactIds << id;
+      QContactLocalId id = d->hash->take(*p);
+      if (id) {
+        QCM5_DEBUG << "Contact" << id << "has been removed";
+        contactIds << id;
+      }
   }
   
-  d->that->_contactsRemoved(contactIds);
+  if (!contactIds.isEmpty())
+    d->that->_contactsRemoved(contactIds);
 }
 
 void QContactABook::initAddressBook(){
@@ -239,7 +246,7 @@
    contactList = osso_abook_aggregator_list_master_contacts(m_abookAgregator);
 
    if (!contactList) {
-     qWarning() << "There are no Master contacts. LocalId hash is empty.";
+     //qWarning() << "There are no Master contacts. LocalId hash is empty.";
      return;
    }
    
@@ -261,8 +268,30 @@
 QList<QContactLocalId> QContactABook::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
 {
   QList<QContactLocalId> rtn;
-  
-  /* Sorting */
+
+  // do this naively for now...
+  *error = QContactManager::NoError;
+  QContactManager::Error tempError = QContactManager::NoError;
+  QList<QContactLocalId> allIds = m_localIds.keys();
+  QList<QContact> sortedAndFiltered;
+  QContact *curr = 0;
+  foreach (const QContactLocalId& currId, allIds) {
+    curr = getQContact(currId, &tempError);
+    if (tempError != QContactManager::NoError)
+      *error = tempError;
+    if (QContactManagerEngine::testFilter(filter, *curr)) {
+      QContactManagerEngine::addSorted(&sortedAndFiltered, *curr, sortOrders);
+    }
+    delete curr;
+  }
+
+  foreach (const QContact& contact, sortedAndFiltered) {
+    rtn.append(contact.localId());
+  }
+  return rtn;
+
+  /*
+  // Sorting
   //NOTE Native sorting is possible thanks to g_list_sort.
   //     It's limited just to one filter.
   //     Multi filters support need non native sorting.
@@ -296,40 +325,6 @@
     return QContactManagerEngine::sortContacts(contacts, sortOrders);
   }
   
-  /* Matching action filter */
-  //NOTE The code was not really tested */
-  if(filter.type() == QContactFilter::ActionFilter){
-    QContactActionFilter af(filter);
-    /* This looks a bit strange for me */
-    QList<QContactActionDescriptor> descriptors = QContactAction::actionDescriptors(af.actionName(), af.vendorName(), af.implementationVersion());
-
-    GList *masterContacts = osso_abook_aggregator_list_master_contacts(m_abookAgregator);
-    for(; masterContacts; ){
-      OssoABookContact *masterContact = A_CONTACT(masterContacts->data);
-      bool match = contactActionsMatch(masterContact, descriptors);
-      if(!match) {
-        GList *rosterContacts = osso_abook_contact_get_roster_contacts(masterContact);
-        for(; rosterContacts && !match; ){
-          OssoABookContact *rosterContact = A_CONTACT(rosterContacts->data);
-          match = contactActionsMatch(rosterContact, descriptors);
-          rosterContacts = g_list_delete_link(rosterContacts, rosterContacts);
-        }
-        g_list_free(rosterContacts);
-      }
-      if(match){
-        EContact *contact = E_CONTACT(masterContact);
-        const char* data = CONST_CHAR(e_contact_get_const(contact, E_CONTACT_UID));
-        QByteArray localId(data);
-        m_localIds << localId;
-        rtn.append(m_localIds[localId]);
-        QCM5_DEBUG << "eContactID " << localId << "has been stored in m_localIDs with key" << m_localIds[localId];
-      }
-      masterContacts = g_list_delete_link(masterContacts, masterContacts);
-    }
-    *error = QContactManager::NoError;
-    return  rtn;
-  }
-  
   EBookQuery* query = convert(filter);
   
   GList* l = osso_abook_aggregator_find_contacts(m_abookAgregator, query);
@@ -348,23 +343,66 @@
   
   *error = QContactManager::NoError;
   return rtn;
+  */
 }
 
 QContact* QContactABook::getQContact(const QContactLocalId& contactId, QContactManager::Error* error) const
 {
   QContact *rtn;
-  OssoABookContact* aContact = getAContact(contactId);
+  OssoABookContact* aContact = getAContact(contactId, error);
   if (!aContact) {
-    qWarning() << "Unable to get a valid AContact";
-    *error = QContactManager::DoesNotExistError;
+    //qWarning() << "Unable to get a valid AContact";
     return new QContact;
   }
   
   //Convert aContact => qContact
   rtn = convert(E_CONTACT(aContact));
+  QContactId cId;
+  cId.setLocalId(contactId);
+  rtn->setId(cId);
   return rtn;
 }
 
+static QContactManager::Error getErrorFromStatus(const EBookStatus status){
+  switch (status) {
+    case E_BOOK_ERROR_OK:
+      return QContactManager::NoError;
+    case E_BOOK_ERROR_INVALID_ARG:
+      return QContactManager::BadArgumentError;
+    case E_BOOK_ERROR_BUSY:
+      return QContactManager::LockedError;        
+    case E_BOOK_ERROR_PERMISSION_DENIED:
+    case E_BOOK_ERROR_AUTHENTICATION_FAILED:
+    case E_BOOK_ERROR_AUTHENTICATION_REQUIRED:
+    //case E_BOOK_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD: //Missing in current Maemo5 Ebook lib version
+      return QContactManager::PermissionsError;
+    case E_BOOK_ERROR_CONTACT_NOT_FOUND:
+      return QContactManager::DoesNotExistError;
+    case E_BOOK_ERROR_CONTACT_ID_ALREADY_EXISTS:
+      return QContactManager::AlreadyExistsError;
+    case E_BOOK_ERROR_NO_SPACE:
+      return QContactManager::OutOfMemoryError;
+#if 0
+    case E_BOOK_ERROR_REPOSITORY_OFFLINE:
+    case E_BOOK_ERROR_NO_SUCH_BOOK:
+    case E_BOOK_ERROR_NO_SELF_CONTACT:
+    case E_BOOK_ERROR_SOURCE_NOT_LOADED:
+    case E_BOOK_ERROR_SOURCE_ALREADY_LOADED:
+    case E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED:
+    case E_BOOK_ERROR_CANCELLED:
+    case E_BOOK_ERROR_COULD_NOT_CANCEL:
+    case E_BOOK_ERROR_TLS_NOT_AVAILABLE:
+    case E_BOOK_ERROR_CORBA_EXCEPTION:
+    case E_BOOK_ERROR_NO_SUCH_SOURCE:
+    case E_BOOK_ERROR_OFFLINE_UNAVAILABLE:
+    case E_BOOK_ERROR_OTHER_ERROR:
+    case E_BOOK_ERROR_INVALID_SERVER_VERSION:
+#endif
+    default:
+      return QContactManager::UnspecifiedError;
+  }
+}
+
 static void delContactCB(EBook *book, EBookStatus status, gpointer closure)
 {
   Q_UNUSED(book);
@@ -375,11 +413,12 @@
     return;
   
   *sd->result = (status != E_BOOK_ERROR_OK &&
-                 status != E_BOOK_ERROR_CONTACT_NOT_FOUND) ? false : true;  
+                 status != E_BOOK_ERROR_CONTACT_NOT_FOUND) ? false : true;
+  *sd->error = getErrorFromStatus(status);
+  
   sd->that->_jobRemovingCompleted();
 }
 
-//### FIXME error is not managed
 bool QContactABook::removeContact(const QContactLocalId& contactId, QContactManager::Error* error)
 {
   Q_UNUSED(error);
@@ -389,9 +428,9 @@
   
   OssoABookRoster *roster = A_ROSTER(m_abookAgregator);
   EBook *book = osso_abook_roster_get_book(roster);
-  OssoABookContact *aContact = getAContact(contactId);
+  OssoABookContact *aContact = getAContact(contactId, error);
   if (!OSSO_ABOOK_IS_CONTACT(aContact)){
-    qWarning() << "aCtontact is not a valid ABook contact"; 
+    //qWarning() << "Specified contact is not a valid ABook contact";
     return false;
   }
   
@@ -407,6 +446,7 @@
   m_deleteJobSD = new jobSharedData;
   m_deleteJobSD->that = this;
   m_deleteJobSD->result = &ok;
+  m_deleteJobSD->error = error;
   
   //Remove photos
   EContactPhoto *photo = NULL;
@@ -425,6 +465,7 @@
   GList* rosterContacts = NULL;
   rosterContacts = osso_abook_contact_get_roster_contacts(aContact);
   const char *masterUid = CONST_CHAR(e_contact_get_const(E_CONTACT(aContact), E_CONTACT_UID));
+  char *contactUidCopy = strdup(masterUid);
   while(rosterContacts){
     OssoABookContact *rosterContact = A_CONTACT(rosterContacts->data);
     osso_abook_contact_reject_for_uid(rosterContact, masterUid, NULL);
@@ -436,6 +477,15 @@
                               delContactCB, m_deleteJobSD);
   
   loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
+
+  // update our list of ids...
+  QContactLocalId id = m_localIds[contactUidCopy];
+  m_localIds.remove(contactUidCopy);
+  if (contactUidCopy)
+    free(contactUidCopy);
+  
+  if (id)
+    _contactsRemoved(QList<QContactLocalId>() << id);
   
   return ok;
 }
@@ -444,18 +494,25 @@
 {
   Q_UNUSED(book)
   jobSharedData *sd = static_cast<jobSharedData*>(user_data);
+  if (!sd)
+    return;
   
-  *sd->result = (status == E_BOOK_ERROR_OK) ? true : false;  
+  *sd->result = (status == E_BOOK_ERROR_OK) ? true : false;
+  *sd->error = getErrorFromStatus(status);
   sd->that->_jobSavingCompleted();
 }
 
 static void addContactCB(EBook* book, EBookStatus  status, const char  *uid, gpointer user_data)
 {
   jobSharedData *sd = static_cast<jobSharedData*>(user_data);
+  if (!sd)
+    return;
+  
   if (uid)
     sd->uid = strdup(uid);
-  
-  //osso_abook_contact_set_roster(OssoABookContact *contact, OssoABookRoster *roster)
+
+  //### FIXME IS THIS LINE REALLY NEEDED: osso_abook_contact_set_roster(OssoABookContact *contact, OssoABookRoster *roster)
+  *sd->result = (status == E_BOOK_ERROR_OK) ? true : false;
   commitContactCB(book, status, user_data);
 }
 
@@ -478,10 +535,9 @@
     book = osso_abook_roster_get_book(roster);
   }
   
-  // Conver QContact to AContact
-  aContact = convert(contact);
+  // Convert QContact to AContact
+  aContact = convert(contact, error);
   if (!aContact){
-    *error = QContactManager::UnspecifiedError;
     return false;
   }  
 
@@ -497,10 +553,13 @@
   m_saveJobSD = new jobSharedData;
   m_saveJobSD->that = this;
   m_saveJobSD->result = &ok;
+  m_saveJobSD->error = error;
+  m_saveJobSD->uid = 0;
   
   // Add/Commit the contact
   uid = CONST_CHAR(e_contact_get_const(E_CONTACT (aContact), E_CONTACT_UID)); 
   if (uid) {
+    m_saveJobSD->uid = strdup(uid);
     osso_abook_contact_async_commit(aContact, book, commitContactCB, m_saveJobSD);
   } else {
     osso_abook_contact_async_add(aContact, book, addContactCB, m_saveJobSD);
@@ -508,11 +567,15 @@
   
   loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
 
+  // save the newly saved contact's id in the hash.
+  m_localIds << m_saveJobSD->uid;
+
   // set the id of the contact.
   QContactId cId;
   cId.setLocalId(m_localIds[m_saveJobSD->uid]);
   contact->setId(cId);
-  //free(m_saveJobSD->uid);
+  if (m_saveJobSD->uid)
+      free(m_saveJobSD->uid);
   
   return ok;
 }
@@ -534,7 +597,7 @@
       QCM5_DEBUG << "eContactID " << eContactUID << "has been stored in m_localIDs with key" << id;
     }
   } else {
-    qWarning() << "Cannot find self contact";
+    //qWarning() << "Cannot find self contact";
     *errors = QContactManager::DoesNotExistError;
     id = 0;
   }
@@ -542,38 +605,6 @@
   return id;
 }
 
-bool QContactABook::contactActionsMatch(OssoABookContact *contact, QList<QContactActionDescriptor> descriptors) const
-{
-  OssoABookCapsFlags capsFlags = osso_abook_caps_get_capabilities(OSSO_ABOOK_CAPS(contact));
-
-  if(capsFlags & OSSO_ABOOK_CAPS_NONE)
-    return false;
-
-  /* ActionNames could be incorrect */
-  OssoABookCapsFlags actionFlags = OSSO_ABOOK_CAPS_NONE;
-  for(int i = 0; i < descriptors.size(); i++){
-    QString actionName = descriptors.at(i).actionName();
-    QCM5_DEBUG << actionName;
-    if(!actionName.compare("Phone"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_PHONE);
-    else if(!actionName.compare("Voice"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_VOICE);
-    else if(!actionName.compare("SendEmail"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_EMAIL);
-    else if(!actionName.compare("Chat"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_CHAT);
-    else if(!actionName.compare("ChatAdditional"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_CHAT_ADDITIONAL);
-    else if(!actionName.compare("VoiceAdditional"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_VOICE_ADDITIONAL);
-    else if(!actionName.compare("Video"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_VIDEO);
-    else if(!actionName.compare("Addressbook"))
-      actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_ADDRESSBOOK);
-  }
-  return ((actionFlags & capsFlags) == actionFlags);
-}
-
 EBookQuery* QContactABook::convert(const QContactFilter& filter) const
 {
   EBookQuery* query = NULL;
@@ -626,7 +657,7 @@
         case QContactFilter::MatchEndsWith: queryStr = "endswith"; break;
         default:
           queryStr = "contains";
-          qWarning() << "Match flag not supported";
+          //qWarning() << "Match flag not supported";
       }
       static QHash<QString,QString> hash;
       if (hash.isEmpty()){
@@ -644,14 +675,13 @@
   
       QString eDetail = hash[f.detailDefinitionName()];
       if (eDetail.isEmpty()){
-        qWarning() << "Unable to found an ebook detail for " << f.detailDefinitionName();
+        //qWarning() << "Unable to found an ebook detail for " << f.detailDefinitionName();
         return NULL;
       }
       queryStr = queryStr + " \"" + eDetail + "\" \"" + f.value().toString() + "\"";
       query = e_book_query_from_string(qPrintable(queryStr));
     } break;
     case QContactFilter::ActionFilter:
-      QCM5_DEBUG << "ActionFilter"; //eQuery doesn't support ActionFilter
       break;
     case QContactFilter::IntersectionFilter:
     {
@@ -662,7 +692,7 @@
       foreach(i, fs){
         EBookQuery* q = convert(i);
         if (!q){
-          qWarning() << "Query is null";
+          //qWarning() << "Query is null";
           continue;
         }
         if (query)
@@ -680,7 +710,7 @@
       foreach(i, fs){
         EBookQuery* q = convert(i);
         if (!q){
-          qWarning() << "Query is null";
+          //qWarning() << "Query is null";
           continue;
         }
         if (query)
@@ -696,6 +726,7 @@
     } break;
     default:
       QCM5_DEBUG << "Filter not supported";
+      query = convert(QContactInvalidFilter());
   }
  
   //Debugging
@@ -778,7 +809,7 @@
 
     ok = contact->saveDetail(detail);
     if (!ok){
-      qWarning() << "Detail can't be saved into QContact";
+      //qWarning() << "Detail can't be saved to QContact";
       delete detail;
       continue;
     }
@@ -812,13 +843,14 @@
   return true;
 }
 
-OssoABookContact* QContactABook::getAContact(const QContactLocalId& contactId) const
+OssoABookContact* QContactABook::getAContact(const QContactLocalId& contactId, QContactManager::Error* error) const
 {
   OssoABookContact* rtn = NULL;
 
   QCM5_DEBUG << "Getting aContact with id " << m_localIds[contactId] << "local contactId is" << contactId;
 
   if(QString(m_localIds[contactId]).compare("osso-abook-self") == 0) {
+    *error = QContactManager::NoError;
     rtn = A_CONTACT(osso_abook_self_contact_get_default());
   } else {
     EBookQuery* query;
@@ -830,9 +862,13 @@
         e_book_query_unref(query);
 
     if (g_list_length(contacts) == 1) {
+      *error = QContactManager::NoError;
       rtn = A_CONTACT(contacts->data);
+    } else if (g_list_length(contacts) == 0) {
+      *error = QContactManager::DoesNotExistError;
     } else {
-      qWarning("List is empty or several contacts have the same UID or contactId belongs to a roster contact.");
+      //qWarning("Several contacts have the same UID or contactId belongs to a roster contact.");
+      *error = QContactManager::UnspecifiedError;
     }
     if (contacts)
       g_list_free(contacts);
@@ -850,7 +886,7 @@
     const QByteArray eContactUID(data);
     QContactLocalId localId = m_localIds[eContactUID];
     if (!localId)
-      qWarning("Unable to get valid localId for the specified eContaact UID");
+      //qWarning("Unable to get valid localId for the specified eContaact UID");
     rtn.setLocalId(localId);
   }
   return rtn;
@@ -863,7 +899,7 @@
   //Ordered list of Fields
   QStringList addressFields;
   addressFields << QContactAddress::FieldPostOfficeBox
-                << "Estension" //FIXME I'm not sure we have to use a new field 
+                << AddressFieldExtension //XXX FIXME I'm not sure we have to use a new field
                 << QContactAddress::FieldStreet
                 << QContactAddress::FieldLocality
                 << QContactAddress::FieldRegion 
@@ -933,7 +969,6 @@
     map[QContactName::FieldCustomLabel] = eContactName->additional;
     map[QContactName::FieldFirstName] = eContactName->given;
     map[QContactName::FieldLastName] = eContactName->family;
-    //map[QContactName::FieldMiddleName] = eContactName->
     map[QContactName::FieldPrefix] = eContactName->prefixes;
     map[QContactName::FieldSuffix] = eContactName->suffixes;
     e_contact_name_free (eContactName);
@@ -1194,7 +1229,7 @@
           attrIsOssoValid = paramName.contains("X-OSSO-VALID");
         
         if (!attrIsType && !attrIsOssoValid) {
-          qWarning () << "Skipping attribute parameter checking for" << paramName;
+          //qWarning () << "Skipping attribute parameter checking for" << paramName;
           continue;
         }
         
@@ -1205,7 +1240,7 @@
           if (attrIsOssoValid) {
             ossoValidIsOk = (attributeParameterValue == "yes")? true : false;
             if (!ossoValidIsOk) {
-              qWarning() << "X-OSSO-VALID is false.";
+              //qWarning() << "X-OSSO-VALID is false.";
               break;
             }
           } else if (type.isEmpty()) {
@@ -1233,7 +1268,7 @@
 {
   QContactOrganization* rtn = new QContactOrganization;
   QVariantMap map;
-  const char* title = CONST_CHAR(e_contact_get(eContact, E_CONTACT_TITLE));
+  const char* title = CONST_CHAR(e_contact_get(eContact, E_CONTACT_ORG));
   map[QContactOrganization::FieldTitle] = title;
   FREE(title);
   setDetailValues(map, rtn);
@@ -1379,7 +1414,7 @@
           attrIsOssoValid = paramName.contains("X-OSSO-VALID");
 
         if (!attrIsType && !attrIsOssoValid) {
-          qWarning () << "Skipping attribute parameter checking for" << paramName;
+          //qWarning () << "Skipping attribute parameter checking for" << paramName;
           continue;
         }
 
@@ -1390,7 +1425,7 @@
           if (attrIsOssoValid) {
             ossoValidIsOk = (attributeParameterValue == "yes")? true : false;
             if (!ossoValidIsOk) {
-              qWarning() << "X-OSSO-VALID is false.";
+              //qWarning() << "X-OSSO-VALID is false.";
               break;
             }
           } else if (type.isEmpty()) {
@@ -1491,7 +1526,7 @@
       int pos =  g_list_position(attributeList, node);
       
       if (index > pos){
-        qWarning() << "Attribute doesn't found at position" << index;
+        //qWarning() << "Attribute doesn't found at position" << index;
         return;
       }
       
@@ -1568,26 +1603,17 @@
   }
 }
 
-OssoABookContact* QContactABook::convert(const QContact *contact) const
+OssoABookContact* QContactABook::convert(const QContact *contact, QContactManager::Error* error) const
 {
   Q_CHECK_PTR(contact);
-  
+
   OssoABookContact* rtn;
   
   // Get aContact if it exists or create a new one if it doesn't
   QContactLocalId id = contact->localId();
   QCM5_DEBUG << "Converting QContact id:" << id << " to aContact";
-  if (id){
-    rtn = getAContact(id);
-    // It's not safe to commit changes to a contact that has been modified.
-    // This problem affects attributes with the same name and parameters such as
-    // EMail, Address...
-    QContactTimestamp* ts = getTimestampDetail(E_CONTACT(rtn));
-    if (*ts != contact->detail<QContactTimestamp>()){
-      delete ts;
-      return NULL;
-    }
-    delete ts;
+  if (id) {
+    rtn = getAContact(id, error);
   } else {
     rtn = osso_abook_contact_new();
   }
@@ -1671,7 +1697,7 @@
     QString key = i.key();
       
     if (key == QContactAddress::FieldPostOfficeBox) index = 0;
-    else if (key == "Estension") index = 1;
+    else if (key == AddressFieldExtension) index = 1;
     else if (key == QContactAddress::FieldStreet) index = 2;
     else if (key == QContactAddress::FieldLocality) index = 3;
     else if (key == QContactAddress::FieldRegion) index = 4;
@@ -1680,7 +1706,7 @@
     else if (key == QContactDetail::FieldContext) continue;
     else if (key == QContactDetail::FieldDetailUri) detailUri = i.value().toInt();
     else {
-      qWarning() << "Address contains an invalid field:" << key;
+      //qWarning() << "Address contains an invalid field:" << key;
       return;
     }
     
@@ -1823,16 +1849,16 @@
   // Save First and Last name in the N vcard attribute
   {  
     QStringList supportedDetailValues;
-    supportedDetailValues << QContactName::FieldFirstName << QContactName::FieldLastName;
+    supportedDetailValues << QContactName::FieldLastName << QContactName::FieldFirstName;
   
     foreach(QString key, supportedDetailValues){
       attrValues << detail.value(key);
     }
   
     //REMOVE ME - We don't want to support custom label
-    if (attrValues[0].isEmpty()){
-      qWarning() << "QContactName::FieldFirstName is empty";
-      attrValues[0] = detail.customLabel();
+    if (attrValues[1].isEmpty()){
+      //qWarning() << "QContactName::FieldFirstName is empty";
+      attrValues[1] = detail.customLabel();
     }
   
     addAttributeToAContact(aContact, EVC_N, attrValues);
@@ -1907,6 +1933,8 @@
       QString value = i.value().toString();
       if (value == QContactPhoneNumber::SubTypeMobile)
         value = "CELL";
+      else if (value == QContactPhoneNumber::SubTypeVoice)
+        value = "VOICE";
       paramValues << value.toUpper();
     } else
       attrValues << i.value().toString();
@@ -1916,7 +1944,7 @@
   if (paramValues.isEmpty())
     paramValues << "VOICE";
   
-  addAttributeToAContact(aContact, EVC_TEL, attrValues, EVC_TYPE, paramValues, true, detail.detailUri().toInt());
+  addAttributeToAContact(aContact, EVC_TEL, attrValues, EVC_TYPE, paramValues, false, detail.detailUri().toInt());
 }
 
 void QContactABook::setUrlDetail(const OssoABookContact* aContact, const QContactUrl& detail) const