qtmobility/plugins/contacts/maemo5/qcontactabook.cpp
changeset 5 453da2cfceef
parent 4 90517678cc4f
child 11 06b8e2af4411
equal deleted inserted replaced
4:90517678cc4f 5:453da2cfceef
    71 
    71 
    72 struct jobSharedData{
    72 struct jobSharedData{
    73    QContactABook* that;
    73    QContactABook* that;
    74    bool *result;
    74    bool *result;
    75    char *uid;
    75    char *uid;
       
    76    QContactManager::Error *error;
    76 };
    77 };
    77 
    78 
    78 /* QContactABook */
    79 /* QContactABook */
    79 QContactABook::QContactABook(QObject* parent) :QObject(parent), m_cbSD(0), m_deleteJobSD(0), m_saveJobSD(0)
    80 QContactABook::QContactABook(QObject* parent) :QObject(parent), m_cbSD(0), m_deleteJobSD(0), m_saveJobSD(0)
    80 {
    81 {
   107   QCM5_DEBUG << "CONTACT ADDED";
   108   QCM5_DEBUG << "CONTACT ADDED";
   108   Q_UNUSED(roster)
   109   Q_UNUSED(roster)
   109   
   110   
   110   cbSharedData* d = static_cast<cbSharedData*>(data);
   111   cbSharedData* d = static_cast<cbSharedData*>(data);
   111   if (!d){
   112   if (!d){
   112     qWarning() << "d has been deleted";
   113     //qWarning() << "d has been deleted";
   113     return;
   114     return;
   114   }
   115   }
   115   
   116   
   116   OssoABookContact **p;
   117   OssoABookContact **p;
   117   QList<QContactLocalId> contactIds;
   118   QList<QContactLocalId> contactIds;
   125     QContactLocalId id = d->hash->append(uid);
   126     QContactLocalId id = d->hash->append(uid);
   126     
   127     
   127     if (id)
   128     if (id)
   128       contactIds << id;
   129       contactIds << id;
   129   }
   130   }
   130   d->that->_contactsAdded(contactIds);
   131 
       
   132   if (!contactIds.isEmpty())
       
   133     d->that->_contactsAdded(contactIds);
   131 }
   134 }
   132 
   135 
   133 static void contactsChangedCB(OssoABookRoster *roster, OssoABookContact **contacts, gpointer data)
   136 static void contactsChangedCB(OssoABookRoster *roster, OssoABookContact **contacts, gpointer data)
   134 {
   137 {
   135   QCM5_DEBUG << "CONTACT CHANGED";
   138   QCM5_DEBUG << "CONTACT CHANGED";
   136   Q_UNUSED(roster)
   139   Q_UNUSED(roster)
   137   
   140   
   138   cbSharedData* d = static_cast<cbSharedData*>(data);
   141   cbSharedData* d = static_cast<cbSharedData*>(data);
   139   if (!d){
   142   if (!d){
   140     qWarning() << "d has been deleted";
   143     //qWarning() << "d has been deleted";
   141     return;
   144     return;
   142   }
   145   }
   143   
   146   
   144   OssoABookContact **p;
   147   OssoABookContact **p;
   145   QList<QContactLocalId> contactIds;
   148   QList<QContactLocalId> contactIds;
   152     QContactLocalId id = d->hash->find(uid);
   155     QContactLocalId id = d->hash->find(uid);
   153     //FREE(uid);
   156     //FREE(uid);
   154     if (id)
   157     if (id)
   155       contactIds << id;
   158       contactIds << id;
   156   }
   159   }
   157   d->that->_contactsChanged(contactIds);
   160 
       
   161   if (!contactIds.isEmpty())
       
   162     d->that->_contactsChanged(contactIds);
   158 }
   163 }
   159 
   164 
   160 static void contactsRemovedCB(OssoABookRoster *roster, const char **ids, gpointer data)
   165 static void contactsRemovedCB(OssoABookRoster *roster, const char **ids, gpointer data)
   161 {
   166 {
   162   QCM5_DEBUG << "CONTACT REMOVED";
   167   QCM5_DEBUG << "CONTACT REMOVED";
   163   Q_UNUSED(roster)
   168   Q_UNUSED(roster)
   164   
   169   
   165   cbSharedData* d = static_cast<cbSharedData*>(data);
   170   cbSharedData* d = static_cast<cbSharedData*>(data);
   166   if (!d){
   171   if (!d){
   167     qWarning() << "d has been deleted";
   172     //qWarning() << "d has been deleted";
   168     return;
   173     return;
   169   }
   174   }
   170   
   175   
   171   const char **p;
   176   const char **p;
   172   QList<QContactLocalId> contactIds;
   177   QList<QContactLocalId> contactIds;
   173   
   178   
   174   for (p = ids; *p; ++p) {
   179   for (p = ids; *p; ++p) {
   175     QContactLocalId id = d->hash->take(*p);
   180       QContactLocalId id = d->hash->take(*p);
   176     QCM5_DEBUG << "Contact" << id << "has been removed";
   181       if (id) {
   177     if (id)
   182         QCM5_DEBUG << "Contact" << id << "has been removed";
   178       contactIds << id;
   183         contactIds << id;
   179   }
   184       }
   180   
   185   }
   181   d->that->_contactsRemoved(contactIds);
   186   
       
   187   if (!contactIds.isEmpty())
       
   188     d->that->_contactsRemoved(contactIds);
   182 }
   189 }
   183 
   190 
   184 void QContactABook::initAddressBook(){
   191 void QContactABook::initAddressBook(){
   185   /* Open AddressBook */
   192   /* Open AddressBook */
   186   GError *gError = NULL;
   193   GError *gError = NULL;
   237    GList *node;
   244    GList *node;
   238    
   245    
   239    contactList = osso_abook_aggregator_list_master_contacts(m_abookAgregator);
   246    contactList = osso_abook_aggregator_list_master_contacts(m_abookAgregator);
   240 
   247 
   241    if (!contactList) {
   248    if (!contactList) {
   242      qWarning() << "There are no Master contacts. LocalId hash is empty.";
   249      //qWarning() << "There are no Master contacts. LocalId hash is empty.";
   243      return;
   250      return;
   244    }
   251    }
   245    
   252    
   246    for (node = contactList; node != NULL; node = g_list_next (node)) {
   253    for (node = contactList; node != NULL; node = g_list_next (node)) {
   247      EContact *contact = E_CONTACT(node->data);
   254      EContact *contact = E_CONTACT(node->data);
   259 }
   266 }
   260 
   267 
   261 QList<QContactLocalId> QContactABook::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
   268 QList<QContactLocalId> QContactABook::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
   262 {
   269 {
   263   QList<QContactLocalId> rtn;
   270   QList<QContactLocalId> rtn;
   264   
   271 
   265   /* Sorting */
   272   // do this naively for now...
       
   273   *error = QContactManager::NoError;
       
   274   QContactManager::Error tempError = QContactManager::NoError;
       
   275   QList<QContactLocalId> allIds = m_localIds.keys();
       
   276   QList<QContact> sortedAndFiltered;
       
   277   QContact *curr = 0;
       
   278   foreach (const QContactLocalId& currId, allIds) {
       
   279     curr = getQContact(currId, &tempError);
       
   280     if (tempError != QContactManager::NoError)
       
   281       *error = tempError;
       
   282     if (QContactManagerEngine::testFilter(filter, *curr)) {
       
   283       QContactManagerEngine::addSorted(&sortedAndFiltered, *curr, sortOrders);
       
   284     }
       
   285     delete curr;
       
   286   }
       
   287 
       
   288   foreach (const QContact& contact, sortedAndFiltered) {
       
   289     rtn.append(contact.localId());
       
   290   }
       
   291   return rtn;
       
   292 
       
   293   /*
       
   294   // Sorting
   266   //NOTE Native sorting is possible thanks to g_list_sort.
   295   //NOTE Native sorting is possible thanks to g_list_sort.
   267   //     It's limited just to one filter.
   296   //     It's limited just to one filter.
   268   //     Multi filters support need non native sorting.
   297   //     Multi filters support need non native sorting.
   269   //     Native filtering needs a lot of coding since we need
   298   //     Native filtering needs a lot of coding since we need
   270   //     detailDefinitionName * detailFieldName functions
   299   //     detailDefinitionName * detailFieldName functions
   294     
   323     
   295     // Non native sorting
   324     // Non native sorting
   296     return QContactManagerEngine::sortContacts(contacts, sortOrders);
   325     return QContactManagerEngine::sortContacts(contacts, sortOrders);
   297   }
   326   }
   298   
   327   
   299   /* Matching action filter */
       
   300   //NOTE The code was not really tested */
       
   301   if(filter.type() == QContactFilter::ActionFilter){
       
   302     QContactActionFilter af(filter);
       
   303     /* This looks a bit strange for me */
       
   304     QList<QContactActionDescriptor> descriptors = QContactAction::actionDescriptors(af.actionName(), af.vendorName(), af.implementationVersion());
       
   305 
       
   306     GList *masterContacts = osso_abook_aggregator_list_master_contacts(m_abookAgregator);
       
   307     for(; masterContacts; ){
       
   308       OssoABookContact *masterContact = A_CONTACT(masterContacts->data);
       
   309       bool match = contactActionsMatch(masterContact, descriptors);
       
   310       if(!match) {
       
   311         GList *rosterContacts = osso_abook_contact_get_roster_contacts(masterContact);
       
   312         for(; rosterContacts && !match; ){
       
   313           OssoABookContact *rosterContact = A_CONTACT(rosterContacts->data);
       
   314           match = contactActionsMatch(rosterContact, descriptors);
       
   315           rosterContacts = g_list_delete_link(rosterContacts, rosterContacts);
       
   316         }
       
   317         g_list_free(rosterContacts);
       
   318       }
       
   319       if(match){
       
   320         EContact *contact = E_CONTACT(masterContact);
       
   321         const char* data = CONST_CHAR(e_contact_get_const(contact, E_CONTACT_UID));
       
   322         QByteArray localId(data);
       
   323         m_localIds << localId;
       
   324         rtn.append(m_localIds[localId]);
       
   325         QCM5_DEBUG << "eContactID " << localId << "has been stored in m_localIDs with key" << m_localIds[localId];
       
   326       }
       
   327       masterContacts = g_list_delete_link(masterContacts, masterContacts);
       
   328     }
       
   329     *error = QContactManager::NoError;
       
   330     return  rtn;
       
   331   }
       
   332   
       
   333   EBookQuery* query = convert(filter);
   328   EBookQuery* query = convert(filter);
   334   
   329   
   335   GList* l = osso_abook_aggregator_find_contacts(m_abookAgregator, query);
   330   GList* l = osso_abook_aggregator_find_contacts(m_abookAgregator, query);
   336   if (query)
   331   if (query)
   337       e_book_query_unref(query);
   332       e_book_query_unref(query);
   346     l = g_list_delete_link(l, l);
   341     l = g_list_delete_link(l, l);
   347   }
   342   }
   348   
   343   
   349   *error = QContactManager::NoError;
   344   *error = QContactManager::NoError;
   350   return rtn;
   345   return rtn;
       
   346   */
   351 }
   347 }
   352 
   348 
   353 QContact* QContactABook::getQContact(const QContactLocalId& contactId, QContactManager::Error* error) const
   349 QContact* QContactABook::getQContact(const QContactLocalId& contactId, QContactManager::Error* error) const
   354 {
   350 {
   355   QContact *rtn;
   351   QContact *rtn;
   356   OssoABookContact* aContact = getAContact(contactId);
   352   OssoABookContact* aContact = getAContact(contactId, error);
   357   if (!aContact) {
   353   if (!aContact) {
   358     qWarning() << "Unable to get a valid AContact";
   354     //qWarning() << "Unable to get a valid AContact";
   359     *error = QContactManager::DoesNotExistError;
       
   360     return new QContact;
   355     return new QContact;
   361   }
   356   }
   362   
   357   
   363   //Convert aContact => qContact
   358   //Convert aContact => qContact
   364   rtn = convert(E_CONTACT(aContact));
   359   rtn = convert(E_CONTACT(aContact));
       
   360   QContactId cId;
       
   361   cId.setLocalId(contactId);
       
   362   rtn->setId(cId);
   365   return rtn;
   363   return rtn;
       
   364 }
       
   365 
       
   366 static QContactManager::Error getErrorFromStatus(const EBookStatus status){
       
   367   switch (status) {
       
   368     case E_BOOK_ERROR_OK:
       
   369       return QContactManager::NoError;
       
   370     case E_BOOK_ERROR_INVALID_ARG:
       
   371       return QContactManager::BadArgumentError;
       
   372     case E_BOOK_ERROR_BUSY:
       
   373       return QContactManager::LockedError;        
       
   374     case E_BOOK_ERROR_PERMISSION_DENIED:
       
   375     case E_BOOK_ERROR_AUTHENTICATION_FAILED:
       
   376     case E_BOOK_ERROR_AUTHENTICATION_REQUIRED:
       
   377     //case E_BOOK_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD: //Missing in current Maemo5 Ebook lib version
       
   378       return QContactManager::PermissionsError;
       
   379     case E_BOOK_ERROR_CONTACT_NOT_FOUND:
       
   380       return QContactManager::DoesNotExistError;
       
   381     case E_BOOK_ERROR_CONTACT_ID_ALREADY_EXISTS:
       
   382       return QContactManager::AlreadyExistsError;
       
   383     case E_BOOK_ERROR_NO_SPACE:
       
   384       return QContactManager::OutOfMemoryError;
       
   385 #if 0
       
   386     case E_BOOK_ERROR_REPOSITORY_OFFLINE:
       
   387     case E_BOOK_ERROR_NO_SUCH_BOOK:
       
   388     case E_BOOK_ERROR_NO_SELF_CONTACT:
       
   389     case E_BOOK_ERROR_SOURCE_NOT_LOADED:
       
   390     case E_BOOK_ERROR_SOURCE_ALREADY_LOADED:
       
   391     case E_BOOK_ERROR_PROTOCOL_NOT_SUPPORTED:
       
   392     case E_BOOK_ERROR_CANCELLED:
       
   393     case E_BOOK_ERROR_COULD_NOT_CANCEL:
       
   394     case E_BOOK_ERROR_TLS_NOT_AVAILABLE:
       
   395     case E_BOOK_ERROR_CORBA_EXCEPTION:
       
   396     case E_BOOK_ERROR_NO_SUCH_SOURCE:
       
   397     case E_BOOK_ERROR_OFFLINE_UNAVAILABLE:
       
   398     case E_BOOK_ERROR_OTHER_ERROR:
       
   399     case E_BOOK_ERROR_INVALID_SERVER_VERSION:
       
   400 #endif
       
   401     default:
       
   402       return QContactManager::UnspecifiedError;
       
   403   }
   366 }
   404 }
   367 
   405 
   368 static void delContactCB(EBook *book, EBookStatus status, gpointer closure)
   406 static void delContactCB(EBook *book, EBookStatus status, gpointer closure)
   369 {
   407 {
   370   Q_UNUSED(book);
   408   Q_UNUSED(book);
   373   jobSharedData *sd = static_cast<jobSharedData*>(closure);
   411   jobSharedData *sd = static_cast<jobSharedData*>(closure);
   374   if (!sd)
   412   if (!sd)
   375     return;
   413     return;
   376   
   414   
   377   *sd->result = (status != E_BOOK_ERROR_OK &&
   415   *sd->result = (status != E_BOOK_ERROR_OK &&
   378                  status != E_BOOK_ERROR_CONTACT_NOT_FOUND) ? false : true;  
   416                  status != E_BOOK_ERROR_CONTACT_NOT_FOUND) ? false : true;
       
   417   *sd->error = getErrorFromStatus(status);
       
   418   
   379   sd->that->_jobRemovingCompleted();
   419   sd->that->_jobRemovingCompleted();
   380 }
   420 }
   381 
   421 
   382 //### FIXME error is not managed
       
   383 bool QContactABook::removeContact(const QContactLocalId& contactId, QContactManager::Error* error)
   422 bool QContactABook::removeContact(const QContactLocalId& contactId, QContactManager::Error* error)
   384 {
   423 {
   385   Q_UNUSED(error);
   424   Q_UNUSED(error);
   386   QMutexLocker locker(&m_delContactMutex);
   425   QMutexLocker locker(&m_delContactMutex);
   387 
   426 
   388   bool ok = false;
   427   bool ok = false;
   389   
   428   
   390   OssoABookRoster *roster = A_ROSTER(m_abookAgregator);
   429   OssoABookRoster *roster = A_ROSTER(m_abookAgregator);
   391   EBook *book = osso_abook_roster_get_book(roster);
   430   EBook *book = osso_abook_roster_get_book(roster);
   392   OssoABookContact *aContact = getAContact(contactId);
   431   OssoABookContact *aContact = getAContact(contactId, error);
   393   if (!OSSO_ABOOK_IS_CONTACT(aContact)){
   432   if (!OSSO_ABOOK_IS_CONTACT(aContact)){
   394     qWarning() << "aCtontact is not a valid ABook contact"; 
   433     //qWarning() << "Specified contact is not a valid ABook contact";
   395     return false;
   434     return false;
   396   }
   435   }
   397   
   436   
   398   // ASync => Sync
   437   // ASync => Sync
   399   QEventLoop loop;                           
   438   QEventLoop loop;                           
   405     m_deleteJobSD = 0;
   444     m_deleteJobSD = 0;
   406   }
   445   }
   407   m_deleteJobSD = new jobSharedData;
   446   m_deleteJobSD = new jobSharedData;
   408   m_deleteJobSD->that = this;
   447   m_deleteJobSD->that = this;
   409   m_deleteJobSD->result = &ok;
   448   m_deleteJobSD->result = &ok;
       
   449   m_deleteJobSD->error = error;
   410   
   450   
   411   //Remove photos
   451   //Remove photos
   412   EContactPhoto *photo = NULL;
   452   EContactPhoto *photo = NULL;
   413   GFile *file = NULL;
   453   GFile *file = NULL;
   414   photo = (EContactPhoto*) e_contact_get(E_CONTACT (aContact), E_CONTACT_PHOTO);
   454   photo = (EContactPhoto*) e_contact_get(E_CONTACT (aContact), E_CONTACT_PHOTO);
   423   
   463   
   424   //Remove all roster contacts from their roster
   464   //Remove all roster contacts from their roster
   425   GList* rosterContacts = NULL;
   465   GList* rosterContacts = NULL;
   426   rosterContacts = osso_abook_contact_get_roster_contacts(aContact);
   466   rosterContacts = osso_abook_contact_get_roster_contacts(aContact);
   427   const char *masterUid = CONST_CHAR(e_contact_get_const(E_CONTACT(aContact), E_CONTACT_UID));
   467   const char *masterUid = CONST_CHAR(e_contact_get_const(E_CONTACT(aContact), E_CONTACT_UID));
       
   468   char *contactUidCopy = strdup(masterUid);
   428   while(rosterContacts){
   469   while(rosterContacts){
   429     OssoABookContact *rosterContact = A_CONTACT(rosterContacts->data);
   470     OssoABookContact *rosterContact = A_CONTACT(rosterContacts->data);
   430     osso_abook_contact_reject_for_uid(rosterContact, masterUid, NULL);
   471     osso_abook_contact_reject_for_uid(rosterContact, masterUid, NULL);
   431     rosterContacts = rosterContacts->next;
   472     rosterContacts = rosterContacts->next;
   432   }  
   473   }  
   434   // Remove contact
   475   // Remove contact
   435   e_book_async_remove_contact(book, E_CONTACT(aContact),
   476   e_book_async_remove_contact(book, E_CONTACT(aContact),
   436                               delContactCB, m_deleteJobSD);
   477                               delContactCB, m_deleteJobSD);
   437   
   478   
   438   loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
   479   loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
       
   480 
       
   481   // update our list of ids...
       
   482   QContactLocalId id = m_localIds[contactUidCopy];
       
   483   m_localIds.remove(contactUidCopy);
       
   484   if (contactUidCopy)
       
   485     free(contactUidCopy);
       
   486   
       
   487   if (id)
       
   488     _contactsRemoved(QList<QContactLocalId>() << id);
   439   
   489   
   440   return ok;
   490   return ok;
   441 }
   491 }
   442 
   492 
   443 static void commitContactCB(EBook* book, EBookStatus  status, gpointer user_data)
   493 static void commitContactCB(EBook* book, EBookStatus  status, gpointer user_data)
   444 {
   494 {
   445   Q_UNUSED(book)
   495   Q_UNUSED(book)
   446   jobSharedData *sd = static_cast<jobSharedData*>(user_data);
   496   jobSharedData *sd = static_cast<jobSharedData*>(user_data);
   447   
   497   if (!sd)
   448   *sd->result = (status == E_BOOK_ERROR_OK) ? true : false;  
   498     return;
       
   499   
       
   500   *sd->result = (status == E_BOOK_ERROR_OK) ? true : false;
       
   501   *sd->error = getErrorFromStatus(status);
   449   sd->that->_jobSavingCompleted();
   502   sd->that->_jobSavingCompleted();
   450 }
   503 }
   451 
   504 
   452 static void addContactCB(EBook* book, EBookStatus  status, const char  *uid, gpointer user_data)
   505 static void addContactCB(EBook* book, EBookStatus  status, const char  *uid, gpointer user_data)
   453 {
   506 {
   454   jobSharedData *sd = static_cast<jobSharedData*>(user_data);
   507   jobSharedData *sd = static_cast<jobSharedData*>(user_data);
       
   508   if (!sd)
       
   509     return;
       
   510   
   455   if (uid)
   511   if (uid)
   456     sd->uid = strdup(uid);
   512     sd->uid = strdup(uid);
   457   
   513 
   458   //osso_abook_contact_set_roster(OssoABookContact *contact, OssoABookRoster *roster)
   514   //### FIXME IS THIS LINE REALLY NEEDED: osso_abook_contact_set_roster(OssoABookContact *contact, OssoABookRoster *roster)
       
   515   *sd->result = (status == E_BOOK_ERROR_OK) ? true : false;
   459   commitContactCB(book, status, user_data);
   516   commitContactCB(book, status, user_data);
   460 }
   517 }
   461 
   518 
   462 bool QContactABook::saveContact(QContact* contact, QContactManager::Error* error)
   519 bool QContactABook::saveContact(QContact* contact, QContactManager::Error* error)
   463 {
   520 {
   476   {
   533   {
   477     OssoABookRoster* roster = reinterpret_cast<OssoABookRoster*>(m_abookAgregator);
   534     OssoABookRoster* roster = reinterpret_cast<OssoABookRoster*>(m_abookAgregator);
   478     book = osso_abook_roster_get_book(roster);
   535     book = osso_abook_roster_get_book(roster);
   479   }
   536   }
   480   
   537   
   481   // Conver QContact to AContact
   538   // Convert QContact to AContact
   482   aContact = convert(contact);
   539   aContact = convert(contact, error);
   483   if (!aContact){
   540   if (!aContact){
   484     *error = QContactManager::UnspecifiedError;
       
   485     return false;
   541     return false;
   486   }  
   542   }  
   487 
   543 
   488   // ASync => Sync
   544   // ASync => Sync
   489   QEventLoop loop;
   545   QEventLoop loop;
   495     m_saveJobSD = 0;
   551     m_saveJobSD = 0;
   496   }
   552   }
   497   m_saveJobSD = new jobSharedData;
   553   m_saveJobSD = new jobSharedData;
   498   m_saveJobSD->that = this;
   554   m_saveJobSD->that = this;
   499   m_saveJobSD->result = &ok;
   555   m_saveJobSD->result = &ok;
       
   556   m_saveJobSD->error = error;
       
   557   m_saveJobSD->uid = 0;
   500   
   558   
   501   // Add/Commit the contact
   559   // Add/Commit the contact
   502   uid = CONST_CHAR(e_contact_get_const(E_CONTACT (aContact), E_CONTACT_UID)); 
   560   uid = CONST_CHAR(e_contact_get_const(E_CONTACT (aContact), E_CONTACT_UID)); 
   503   if (uid) {
   561   if (uid) {
       
   562     m_saveJobSD->uid = strdup(uid);
   504     osso_abook_contact_async_commit(aContact, book, commitContactCB, m_saveJobSD);
   563     osso_abook_contact_async_commit(aContact, book, commitContactCB, m_saveJobSD);
   505   } else {
   564   } else {
   506     osso_abook_contact_async_add(aContact, book, addContactCB, m_saveJobSD);
   565     osso_abook_contact_async_add(aContact, book, addContactCB, m_saveJobSD);
   507   }
   566   }
   508   
   567   
   509   loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
   568   loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
       
   569 
       
   570   // save the newly saved contact's id in the hash.
       
   571   m_localIds << m_saveJobSD->uid;
   510 
   572 
   511   // set the id of the contact.
   573   // set the id of the contact.
   512   QContactId cId;
   574   QContactId cId;
   513   cId.setLocalId(m_localIds[m_saveJobSD->uid]);
   575   cId.setLocalId(m_localIds[m_saveJobSD->uid]);
   514   contact->setId(cId);
   576   contact->setId(cId);
   515   //free(m_saveJobSD->uid);
   577   if (m_saveJobSD->uid)
       
   578       free(m_saveJobSD->uid);
   516   
   579   
   517   return ok;
   580   return ok;
   518 }
   581 }
   519 
   582 
   520 QContactLocalId QContactABook::selfContactId(QContactManager::Error* errors) const
   583 QContactLocalId QContactABook::selfContactId(QContactManager::Error* errors) const
   532       m_localIds << eContactUID; //FIXME MemLeak
   595       m_localIds << eContactUID; //FIXME MemLeak
   533       id = m_localIds[eContactUID];
   596       id = m_localIds[eContactUID];
   534       QCM5_DEBUG << "eContactID " << eContactUID << "has been stored in m_localIDs with key" << id;
   597       QCM5_DEBUG << "eContactID " << eContactUID << "has been stored in m_localIDs with key" << id;
   535     }
   598     }
   536   } else {
   599   } else {
   537     qWarning() << "Cannot find self contact";
   600     //qWarning() << "Cannot find self contact";
   538     *errors = QContactManager::DoesNotExistError;
   601     *errors = QContactManager::DoesNotExistError;
   539     id = 0;
   602     id = 0;
   540   }
   603   }
   541   g_object_unref(self);
   604   g_object_unref(self);
   542   return id;
   605   return id;
   543 }
       
   544 
       
   545 bool QContactABook::contactActionsMatch(OssoABookContact *contact, QList<QContactActionDescriptor> descriptors) const
       
   546 {
       
   547   OssoABookCapsFlags capsFlags = osso_abook_caps_get_capabilities(OSSO_ABOOK_CAPS(contact));
       
   548 
       
   549   if(capsFlags & OSSO_ABOOK_CAPS_NONE)
       
   550     return false;
       
   551 
       
   552   /* ActionNames could be incorrect */
       
   553   OssoABookCapsFlags actionFlags = OSSO_ABOOK_CAPS_NONE;
       
   554   for(int i = 0; i < descriptors.size(); i++){
       
   555     QString actionName = descriptors.at(i).actionName();
       
   556     QCM5_DEBUG << actionName;
       
   557     if(!actionName.compare("Phone"))
       
   558       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_PHONE);
       
   559     else if(!actionName.compare("Voice"))
       
   560       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_VOICE);
       
   561     else if(!actionName.compare("SendEmail"))
       
   562       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_EMAIL);
       
   563     else if(!actionName.compare("Chat"))
       
   564       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_CHAT);
       
   565     else if(!actionName.compare("ChatAdditional"))
       
   566       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_CHAT_ADDITIONAL);
       
   567     else if(!actionName.compare("VoiceAdditional"))
       
   568       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_VOICE_ADDITIONAL);
       
   569     else if(!actionName.compare("Video"))
       
   570       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_VIDEO);
       
   571     else if(!actionName.compare("Addressbook"))
       
   572       actionFlags = (OssoABookCapsFlags)(actionFlags | OSSO_ABOOK_CAPS_ADDRESSBOOK);
       
   573   }
       
   574   return ((actionFlags & capsFlags) == actionFlags);
       
   575 }
   606 }
   576 
   607 
   577 EBookQuery* QContactABook::convert(const QContactFilter& filter) const
   608 EBookQuery* QContactABook::convert(const QContactFilter& filter) const
   578 {
   609 {
   579   EBookQuery* query = NULL;
   610   EBookQuery* query = NULL;
   624         case QContactFilter::MatchExactly: queryStr = "is"; break;
   655         case QContactFilter::MatchExactly: queryStr = "is"; break;
   625         case QContactFilter::MatchStartsWith: queryStr = "beginswith"; break;
   656         case QContactFilter::MatchStartsWith: queryStr = "beginswith"; break;
   626         case QContactFilter::MatchEndsWith: queryStr = "endswith"; break;
   657         case QContactFilter::MatchEndsWith: queryStr = "endswith"; break;
   627         default:
   658         default:
   628           queryStr = "contains";
   659           queryStr = "contains";
   629           qWarning() << "Match flag not supported";
   660           //qWarning() << "Match flag not supported";
   630       }
   661       }
   631       static QHash<QString,QString> hash;
   662       static QHash<QString,QString> hash;
   632       if (hash.isEmpty()){
   663       if (hash.isEmpty()){
   633         hash[QContactAddress::DefinitionName] = "address";
   664         hash[QContactAddress::DefinitionName] = "address";
   634         hash[QContactBirthday::DefinitionName] = "birth-date";
   665         hash[QContactBirthday::DefinitionName] = "birth-date";
   642         hash[QContactUrl::DefinitionName] = "homepage-url";
   673         hash[QContactUrl::DefinitionName] = "homepage-url";
   643       }
   674       }
   644   
   675   
   645       QString eDetail = hash[f.detailDefinitionName()];
   676       QString eDetail = hash[f.detailDefinitionName()];
   646       if (eDetail.isEmpty()){
   677       if (eDetail.isEmpty()){
   647         qWarning() << "Unable to found an ebook detail for " << f.detailDefinitionName();
   678         //qWarning() << "Unable to found an ebook detail for " << f.detailDefinitionName();
   648         return NULL;
   679         return NULL;
   649       }
   680       }
   650       queryStr = queryStr + " \"" + eDetail + "\" \"" + f.value().toString() + "\"";
   681       queryStr = queryStr + " \"" + eDetail + "\" \"" + f.value().toString() + "\"";
   651       query = e_book_query_from_string(qPrintable(queryStr));
   682       query = e_book_query_from_string(qPrintable(queryStr));
   652     } break;
   683     } break;
   653     case QContactFilter::ActionFilter:
   684     case QContactFilter::ActionFilter:
   654       QCM5_DEBUG << "ActionFilter"; //eQuery doesn't support ActionFilter
       
   655       break;
   685       break;
   656     case QContactFilter::IntersectionFilter:
   686     case QContactFilter::IntersectionFilter:
   657     {
   687     {
   658       QCM5_DEBUG << "IntersectionFilter";
   688       QCM5_DEBUG << "IntersectionFilter";
   659       const QContactIntersectionFilter f(filter);
   689       const QContactIntersectionFilter f(filter);
   660       const QList<QContactFilter>  fs= f.filters();
   690       const QList<QContactFilter>  fs= f.filters();
   661       QContactFilter i;
   691       QContactFilter i;
   662       foreach(i, fs){
   692       foreach(i, fs){
   663         EBookQuery* q = convert(i);
   693         EBookQuery* q = convert(i);
   664         if (!q){
   694         if (!q){
   665           qWarning() << "Query is null";
   695           //qWarning() << "Query is null";
   666           continue;
   696           continue;
   667         }
   697         }
   668         if (query)
   698         if (query)
   669           query = e_book_query_andv(query, q, NULL);
   699           query = e_book_query_andv(query, q, NULL);
   670         else
   700         else
   678       const QList<QContactFilter>  fs= f.filters();
   708       const QList<QContactFilter>  fs= f.filters();
   679       QContactFilter i;
   709       QContactFilter i;
   680       foreach(i, fs){
   710       foreach(i, fs){
   681         EBookQuery* q = convert(i);
   711         EBookQuery* q = convert(i);
   682         if (!q){
   712         if (!q){
   683           qWarning() << "Query is null";
   713           //qWarning() << "Query is null";
   684           continue;
   714           continue;
   685         }
   715         }
   686         if (query)
   716         if (query)
   687           query = e_book_query_orv(query, q, NULL);
   717           query = e_book_query_orv(query, q, NULL);
   688         else
   718         else
   694       QCM5_DEBUG << "InvalidFilter";
   724       QCM5_DEBUG << "InvalidFilter";
   695       query = e_book_query_from_string("(is \"id\" \"-1\")");
   725       query = e_book_query_from_string("(is \"id\" \"-1\")");
   696     } break;
   726     } break;
   697     default:
   727     default:
   698       QCM5_DEBUG << "Filter not supported";
   728       QCM5_DEBUG << "Filter not supported";
       
   729       query = convert(QContactInvalidFilter());
   699   }
   730   }
   700  
   731  
   701   //Debugging
   732   //Debugging
   702   const char *queryString = e_book_query_to_string(query);
   733   const char *queryString = e_book_query_to_string(query);
   703   QCM5_DEBUG << "QUERY" << queryString;
   734   QCM5_DEBUG << "QUERY" << queryString;
   776       continue;
   807       continue;
   777     }
   808     }
   778 
   809 
   779     ok = contact->saveDetail(detail);
   810     ok = contact->saveDetail(detail);
   780     if (!ok){
   811     if (!ok){
   781       qWarning() << "Detail can't be saved into QContact";
   812       //qWarning() << "Detail can't be saved to QContact";
   782       delete detail;
   813       delete detail;
   783       continue;
   814       continue;
   784     }
   815     }
   785     delete detail;
   816     delete detail;
   786   }
   817   }
   810   if (detail->isEmpty())
   841   if (detail->isEmpty())
   811     return false;
   842     return false;
   812   return true;
   843   return true;
   813 }
   844 }
   814 
   845 
   815 OssoABookContact* QContactABook::getAContact(const QContactLocalId& contactId) const
   846 OssoABookContact* QContactABook::getAContact(const QContactLocalId& contactId, QContactManager::Error* error) const
   816 {
   847 {
   817   OssoABookContact* rtn = NULL;
   848   OssoABookContact* rtn = NULL;
   818 
   849 
   819   QCM5_DEBUG << "Getting aContact with id " << m_localIds[contactId] << "local contactId is" << contactId;
   850   QCM5_DEBUG << "Getting aContact with id " << m_localIds[contactId] << "local contactId is" << contactId;
   820 
   851 
   821   if(QString(m_localIds[contactId]).compare("osso-abook-self") == 0) {
   852   if(QString(m_localIds[contactId]).compare("osso-abook-self") == 0) {
       
   853     *error = QContactManager::NoError;
   822     rtn = A_CONTACT(osso_abook_self_contact_get_default());
   854     rtn = A_CONTACT(osso_abook_self_contact_get_default());
   823   } else {
   855   } else {
   824     EBookQuery* query;
   856     EBookQuery* query;
   825     GList* contacts;
   857     GList* contacts;
   826 
   858 
   828     contacts = osso_abook_aggregator_find_contacts(m_abookAgregator, query);
   860     contacts = osso_abook_aggregator_find_contacts(m_abookAgregator, query);
   829     if (query)
   861     if (query)
   830         e_book_query_unref(query);
   862         e_book_query_unref(query);
   831 
   863 
   832     if (g_list_length(contacts) == 1) {
   864     if (g_list_length(contacts) == 1) {
       
   865       *error = QContactManager::NoError;
   833       rtn = A_CONTACT(contacts->data);
   866       rtn = A_CONTACT(contacts->data);
       
   867     } else if (g_list_length(contacts) == 0) {
       
   868       *error = QContactManager::DoesNotExistError;
   834     } else {
   869     } else {
   835       qWarning("List is empty or several contacts have the same UID or contactId belongs to a roster contact.");
   870       //qWarning("Several contacts have the same UID or contactId belongs to a roster contact.");
       
   871       *error = QContactManager::UnspecifiedError;
   836     }
   872     }
   837     if (contacts)
   873     if (contacts)
   838       g_list_free(contacts);
   874       g_list_free(contacts);
   839   }
   875   }
   840 
   876 
   848   {
   884   {
   849     const char* data = CONST_CHAR(e_contact_get_const(eContact, E_CONTACT_UID));
   885     const char* data = CONST_CHAR(e_contact_get_const(eContact, E_CONTACT_UID));
   850     const QByteArray eContactUID(data);
   886     const QByteArray eContactUID(data);
   851     QContactLocalId localId = m_localIds[eContactUID];
   887     QContactLocalId localId = m_localIds[eContactUID];
   852     if (!localId)
   888     if (!localId)
   853       qWarning("Unable to get valid localId for the specified eContaact UID");
   889       //qWarning("Unable to get valid localId for the specified eContaact UID");
   854     rtn.setLocalId(localId);
   890     rtn.setLocalId(localId);
   855   }
   891   }
   856   return rtn;
   892   return rtn;
   857 }
   893 }
   858 
   894 
   861   QList<QContactAddress*> rtnList;
   897   QList<QContactAddress*> rtnList;
   862 
   898 
   863   //Ordered list of Fields
   899   //Ordered list of Fields
   864   QStringList addressFields;
   900   QStringList addressFields;
   865   addressFields << QContactAddress::FieldPostOfficeBox
   901   addressFields << QContactAddress::FieldPostOfficeBox
   866                 << "Estension" //FIXME I'm not sure we have to use a new field 
   902                 << AddressFieldExtension //XXX FIXME I'm not sure we have to use a new field
   867                 << QContactAddress::FieldStreet
   903                 << QContactAddress::FieldStreet
   868                 << QContactAddress::FieldLocality
   904                 << QContactAddress::FieldLocality
   869                 << QContactAddress::FieldRegion 
   905                 << QContactAddress::FieldRegion 
   870                 << QContactAddress::FieldPostcode 
   906                 << QContactAddress::FieldPostcode 
   871                 << QContactAddress::FieldCountry;
   907                 << QContactAddress::FieldCountry;
   931   EContactName* eContactName = static_cast<EContactName*> (e_contact_get(eContact, E_CONTACT_NAME));
   967   EContactName* eContactName = static_cast<EContactName*> (e_contact_get(eContact, E_CONTACT_NAME));
   932   if (eContactName){
   968   if (eContactName){
   933     map[QContactName::FieldCustomLabel] = eContactName->additional;
   969     map[QContactName::FieldCustomLabel] = eContactName->additional;
   934     map[QContactName::FieldFirstName] = eContactName->given;
   970     map[QContactName::FieldFirstName] = eContactName->given;
   935     map[QContactName::FieldLastName] = eContactName->family;
   971     map[QContactName::FieldLastName] = eContactName->family;
   936     //map[QContactName::FieldMiddleName] = eContactName->
       
   937     map[QContactName::FieldPrefix] = eContactName->prefixes;
   972     map[QContactName::FieldPrefix] = eContactName->prefixes;
   938     map[QContactName::FieldSuffix] = eContactName->suffixes;
   973     map[QContactName::FieldSuffix] = eContactName->suffixes;
   939     e_contact_name_free (eContactName);
   974     e_contact_name_free (eContactName);
   940   } else {
   975   } else {
   941     //Looks that Maemo use just these two fields
   976     //Looks that Maemo use just these two fields
  1192         
  1227         
  1193         if(!ossoValidIsOk)
  1228         if(!ossoValidIsOk)
  1194           attrIsOssoValid = paramName.contains("X-OSSO-VALID");
  1229           attrIsOssoValid = paramName.contains("X-OSSO-VALID");
  1195         
  1230         
  1196         if (!attrIsType && !attrIsOssoValid) {
  1231         if (!attrIsType && !attrIsOssoValid) {
  1197           qWarning () << "Skipping attribute parameter checking for" << paramName;
  1232           //qWarning () << "Skipping attribute parameter checking for" << paramName;
  1198           continue;
  1233           continue;
  1199         }
  1234         }
  1200         
  1235         
  1201         GList *values = e_vcard_attribute_param_get_values(p);
  1236         GList *values = e_vcard_attribute_param_get_values(p);
  1202         GList *node;
  1237         GList *node;
  1203         for (node = values; node != NULL; node = g_list_next (node)) {
  1238         for (node = values; node != NULL; node = g_list_next (node)) {
  1204           QString attributeParameterValue = QString::fromLatin1(CONST_CHAR(node->data));
  1239           QString attributeParameterValue = QString::fromLatin1(CONST_CHAR(node->data));
  1205           if (attrIsOssoValid) {
  1240           if (attrIsOssoValid) {
  1206             ossoValidIsOk = (attributeParameterValue == "yes")? true : false;
  1241             ossoValidIsOk = (attributeParameterValue == "yes")? true : false;
  1207             if (!ossoValidIsOk) {
  1242             if (!ossoValidIsOk) {
  1208               qWarning() << "X-OSSO-VALID is false.";
  1243               //qWarning() << "X-OSSO-VALID is false.";
  1209               break;
  1244               break;
  1210             }
  1245             }
  1211           } else if (type.isEmpty()) {
  1246           } else if (type.isEmpty()) {
  1212             type = attributeParameterValue;
  1247             type = attributeParameterValue;
  1213             if (type.isEmpty())
  1248             if (type.isEmpty())
  1231 
  1266 
  1232 QContactOrganization* QContactABook::getOrganizationDetail(EContact *eContact) const
  1267 QContactOrganization* QContactABook::getOrganizationDetail(EContact *eContact) const
  1233 {
  1268 {
  1234   QContactOrganization* rtn = new QContactOrganization;
  1269   QContactOrganization* rtn = new QContactOrganization;
  1235   QVariantMap map;
  1270   QVariantMap map;
  1236   const char* title = CONST_CHAR(e_contact_get(eContact, E_CONTACT_TITLE));
  1271   const char* title = CONST_CHAR(e_contact_get(eContact, E_CONTACT_ORG));
  1237   map[QContactOrganization::FieldTitle] = title;
  1272   map[QContactOrganization::FieldTitle] = title;
  1238   FREE(title);
  1273   FREE(title);
  1239   setDetailValues(map, rtn);
  1274   setDetailValues(map, rtn);
  1240   return rtn;
  1275   return rtn;
  1241 }
  1276 }
  1377 
  1412 
  1378         if(!ossoValidIsOk)
  1413         if(!ossoValidIsOk)
  1379           attrIsOssoValid = paramName.contains("X-OSSO-VALID");
  1414           attrIsOssoValid = paramName.contains("X-OSSO-VALID");
  1380 
  1415 
  1381         if (!attrIsType && !attrIsOssoValid) {
  1416         if (!attrIsType && !attrIsOssoValid) {
  1382           qWarning () << "Skipping attribute parameter checking for" << paramName;
  1417           //qWarning () << "Skipping attribute parameter checking for" << paramName;
  1383           continue;
  1418           continue;
  1384         }
  1419         }
  1385 
  1420 
  1386         GList *values = e_vcard_attribute_param_get_values(p);
  1421         GList *values = e_vcard_attribute_param_get_values(p);
  1387         GList *node;
  1422         GList *node;
  1388         for (node = values; node != NULL; node = g_list_next (node)) {
  1423         for (node = values; node != NULL; node = g_list_next (node)) {
  1389           QString attributeParameterValue = QString::fromLatin1(CONST_CHAR(node->data));
  1424           QString attributeParameterValue = QString::fromLatin1(CONST_CHAR(node->data));
  1390           if (attrIsOssoValid) {
  1425           if (attrIsOssoValid) {
  1391             ossoValidIsOk = (attributeParameterValue == "yes")? true : false;
  1426             ossoValidIsOk = (attributeParameterValue == "yes")? true : false;
  1392             if (!ossoValidIsOk) {
  1427             if (!ossoValidIsOk) {
  1393               qWarning() << "X-OSSO-VALID is false.";
  1428               //qWarning() << "X-OSSO-VALID is false.";
  1394               break;
  1429               break;
  1395             }
  1430             }
  1396           } else if (type.isEmpty()) {
  1431           } else if (type.isEmpty()) {
  1397             type = attributeParameterValue;
  1432             type = attributeParameterValue;
  1398             if (type.isEmpty())
  1433             if (type.isEmpty())
  1489     for (GList *node = g_list_last(attributeList); node != NULL; node = g_list_previous(node)) {
  1524     for (GList *node = g_list_last(attributeList); node != NULL; node = g_list_previous(node)) {
  1490       EVCardAttribute* eAttr = (EVCardAttribute*)node->data;
  1525       EVCardAttribute* eAttr = (EVCardAttribute*)node->data;
  1491       int pos =  g_list_position(attributeList, node);
  1526       int pos =  g_list_position(attributeList, node);
  1492       
  1527       
  1493       if (index > pos){
  1528       if (index > pos){
  1494         qWarning() << "Attribute doesn't found at position" << index;
  1529         //qWarning() << "Attribute doesn't found at position" << index;
  1495         return;
  1530         return;
  1496       }
  1531       }
  1497       
  1532       
  1498       if (index != pos)
  1533       if (index != pos)
  1499         continue;
  1534         continue;
  1566     QCM5_DEBUG << "Modified VCard" << dbgStr;
  1601     QCM5_DEBUG << "Modified VCard" << dbgStr;
  1567     FREE(dbgStr);
  1602     FREE(dbgStr);
  1568   }
  1603   }
  1569 }
  1604 }
  1570 
  1605 
  1571 OssoABookContact* QContactABook::convert(const QContact *contact) const
  1606 OssoABookContact* QContactABook::convert(const QContact *contact, QContactManager::Error* error) const
  1572 {
  1607 {
  1573   Q_CHECK_PTR(contact);
  1608   Q_CHECK_PTR(contact);
  1574   
  1609 
  1575   OssoABookContact* rtn;
  1610   OssoABookContact* rtn;
  1576   
  1611   
  1577   // Get aContact if it exists or create a new one if it doesn't
  1612   // Get aContact if it exists or create a new one if it doesn't
  1578   QContactLocalId id = contact->localId();
  1613   QContactLocalId id = contact->localId();
  1579   QCM5_DEBUG << "Converting QContact id:" << id << " to aContact";
  1614   QCM5_DEBUG << "Converting QContact id:" << id << " to aContact";
  1580   if (id){
  1615   if (id) {
  1581     rtn = getAContact(id);
  1616     rtn = getAContact(id, error);
  1582     // It's not safe to commit changes to a contact that has been modified.
       
  1583     // This problem affects attributes with the same name and parameters such as
       
  1584     // EMail, Address...
       
  1585     QContactTimestamp* ts = getTimestampDetail(E_CONTACT(rtn));
       
  1586     if (*ts != contact->detail<QContactTimestamp>()){
       
  1587       delete ts;
       
  1588       return NULL;
       
  1589     }
       
  1590     delete ts;
       
  1591   } else {
  1617   } else {
  1592     rtn = osso_abook_contact_new();
  1618     rtn = osso_abook_contact_new();
  1593   }
  1619   }
  1594   
  1620   
  1595   QList<QContactDetail> allDetails = contact->details();
  1621   QList<QContactDetail> allDetails = contact->details();
  1669     i.next();
  1695     i.next();
  1670     int index = -1;
  1696     int index = -1;
  1671     QString key = i.key();
  1697     QString key = i.key();
  1672       
  1698       
  1673     if (key == QContactAddress::FieldPostOfficeBox) index = 0;
  1699     if (key == QContactAddress::FieldPostOfficeBox) index = 0;
  1674     else if (key == "Estension") index = 1;
  1700     else if (key == AddressFieldExtension) index = 1;
  1675     else if (key == QContactAddress::FieldStreet) index = 2;
  1701     else if (key == QContactAddress::FieldStreet) index = 2;
  1676     else if (key == QContactAddress::FieldLocality) index = 3;
  1702     else if (key == QContactAddress::FieldLocality) index = 3;
  1677     else if (key == QContactAddress::FieldRegion) index = 4;
  1703     else if (key == QContactAddress::FieldRegion) index = 4;
  1678     else if (key == QContactAddress::FieldPostcode) index = 5;
  1704     else if (key == QContactAddress::FieldPostcode) index = 5;
  1679     else if (key == QContactAddress::FieldCountry) index = 6;  
  1705     else if (key == QContactAddress::FieldCountry) index = 6;  
  1680     else if (key == QContactDetail::FieldContext) continue;
  1706     else if (key == QContactDetail::FieldContext) continue;
  1681     else if (key == QContactDetail::FieldDetailUri) detailUri = i.value().toInt();
  1707     else if (key == QContactDetail::FieldDetailUri) detailUri = i.value().toInt();
  1682     else {
  1708     else {
  1683       qWarning() << "Address contains an invalid field:" << key;
  1709       //qWarning() << "Address contains an invalid field:" << key;
  1684       return;
  1710       return;
  1685     }
  1711     }
  1686     
  1712     
  1687     if (index != -1)
  1713     if (index != -1)
  1688       adrAttrValues[index] = i.value().toString();
  1714       adrAttrValues[index] = i.value().toString();
  1821   
  1847   
  1822   QStringList attrValues;
  1848   QStringList attrValues;
  1823   // Save First and Last name in the N vcard attribute
  1849   // Save First and Last name in the N vcard attribute
  1824   {  
  1850   {  
  1825     QStringList supportedDetailValues;
  1851     QStringList supportedDetailValues;
  1826     supportedDetailValues << QContactName::FieldFirstName << QContactName::FieldLastName;
  1852     supportedDetailValues << QContactName::FieldLastName << QContactName::FieldFirstName;
  1827   
  1853   
  1828     foreach(QString key, supportedDetailValues){
  1854     foreach(QString key, supportedDetailValues){
  1829       attrValues << detail.value(key);
  1855       attrValues << detail.value(key);
  1830     }
  1856     }
  1831   
  1857   
  1832     //REMOVE ME - We don't want to support custom label
  1858     //REMOVE ME - We don't want to support custom label
  1833     if (attrValues[0].isEmpty()){
  1859     if (attrValues[1].isEmpty()){
  1834       qWarning() << "QContactName::FieldFirstName is empty";
  1860       //qWarning() << "QContactName::FieldFirstName is empty";
  1835       attrValues[0] = detail.customLabel();
  1861       attrValues[1] = detail.customLabel();
  1836     }
  1862     }
  1837   
  1863   
  1838     addAttributeToAContact(aContact, EVC_N, attrValues);
  1864     addAttributeToAContact(aContact, EVC_N, attrValues);
  1839   }
  1865   }
  1840   
  1866   
  1905     if (key == QContactDetail::FieldContext ||
  1931     if (key == QContactDetail::FieldContext ||
  1906         key == QContactPhoneNumber::FieldSubTypes){
  1932         key == QContactPhoneNumber::FieldSubTypes){
  1907       QString value = i.value().toString();
  1933       QString value = i.value().toString();
  1908       if (value == QContactPhoneNumber::SubTypeMobile)
  1934       if (value == QContactPhoneNumber::SubTypeMobile)
  1909         value = "CELL";
  1935         value = "CELL";
       
  1936       else if (value == QContactPhoneNumber::SubTypeVoice)
       
  1937         value = "VOICE";
  1910       paramValues << value.toUpper();
  1938       paramValues << value.toUpper();
  1911     } else
  1939     } else
  1912       attrValues << i.value().toString();
  1940       attrValues << i.value().toString();
  1913   }
  1941   }
  1914   
  1942   
  1915   // Avoid unsupported type
  1943   // Avoid unsupported type
  1916   if (paramValues.isEmpty())
  1944   if (paramValues.isEmpty())
  1917     paramValues << "VOICE";
  1945     paramValues << "VOICE";
  1918   
  1946   
  1919   addAttributeToAContact(aContact, EVC_TEL, attrValues, EVC_TYPE, paramValues, true, detail.detailUri().toInt());
  1947   addAttributeToAContact(aContact, EVC_TEL, attrValues, EVC_TYPE, paramValues, false, detail.detailUri().toInt());
  1920 }
  1948 }
  1921 
  1949 
  1922 void QContactABook::setUrlDetail(const OssoABookContact* aContact, const QContactUrl& detail) const
  1950 void QContactABook::setUrlDetail(const OssoABookContact* aContact, const QContactUrl& detail) const
  1923 {
  1951 {
  1924   if (!aContact) return;
  1952   if (!aContact) return;