qtmobility/plugins/contacts/symbian/src/cntsymbiandatabase.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 8 71781823f776
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
    39 **
    39 **
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 //system includes
    41 //system includes
    42 #include <e32base.h>
    42 #include <e32base.h>
    43 #include <s32mem.h>
    43 #include <s32mem.h>
       
    44 #include <cntitem.h>
    44 
    45 
    45 //user includes
    46 //user includes
    46 #include "cntsymbiandatabase.h"
    47 #include "cntsymbiandatabase.h"
    47 #include "cntsymbiantransformerror.h"
    48 #include "cntsymbiantransformerror.h"
    48 #include "qcontactchangeset.h"
    49 #include "qcontactchangeset.h"
    49 #include "qcontactmanagerengine.h"
    50 #include "qcontactmanagerengine.h"
    50 
    51 
    51 // Constant
    52 // Constant
    52 typedef QPair<QContactLocalId, QContactLocalId> QOwnCardPair;
    53 typedef QPair<QContactLocalId, QContactLocalId> QOwnCardPair;
    53 
    54 
    54 CntSymbianDatabase::CntSymbianDatabase(QContactManagerEngine *engine, QContactManager::Error& error) :
    55 CntSymbianDatabase::CntSymbianDatabase(QContactManagerEngine *engine, QContactManager::Error* error) :
       
    56     m_engine(engine),
    55     m_contactDatabase(0),
    57     m_contactDatabase(0),
    56     m_currentOwnCardId(0)
    58     m_currentOwnCardId(0)
    57 {
    59 {
    58     TRAPD(err, m_contactDatabase = CContactDatabase::OpenL())
    60     TRAPD(err, initializeL());
    59 
    61     CntSymbianTransformError::transformError(err, error);
    60     //Database not found, create it
    62 }
    61     if(err == KErrNotFound)
    63 
    62     {
    64 void CntSymbianDatabase::initializeL()
    63         TRAP(err, m_contactDatabase = CContactDatabase::CreateL())
    65 {
    64     }
    66     User::LeaveIfNull(m_engine);
    65 
    67 
    66     //Database opened successfully
    68     TRAPD(err, m_contactDatabase = CContactDatabase::OpenL());
    67     if (err == KErrNone)
    69 
    68     {
    70     // Database not found, create it
       
    71     if(err == KErrNotFound) {
       
    72         m_contactDatabase = CContactDatabase::CreateL();
       
    73     }
       
    74 
       
    75 #ifndef SYMBIAN_BACKEND_USE_SQLITE
    69     // In pre 10.1 platforms the AddObserverL & RemoveObserver functions are not
    76     // In pre 10.1 platforms the AddObserverL & RemoveObserver functions are not
    70     // exported so we need to use CContactChangeNotifier.
    77     // exported so we need to use CContactChangeNotifier.
    71 #ifndef SYMBIAN_BACKEND_USE_SQLITE
    78     TRAP(err, m_contactChangeNotifier = CContactChangeNotifier::NewL(*m_contactDatabase, this));
    72         TRAP(err, m_contactChangeNotifier = CContactChangeNotifier::NewL(*m_contactDatabase, this));
       
    73 #else
    79 #else
    74         TRAP(err, m_contactDatabase->AddObserverL(*this));
    80     TRAP(err, m_contactDatabase->AddObserverL(*this));
    75 #endif
    81 #endif
    76         if (err == KErrNone)
    82 
    77             m_engine = engine;
    83     // Read current own card id (self contact id)
    78 
    84     TContactItemId myCard = m_contactDatabase->OwnCardId();
    79         // Read current own card id (self contact id)
    85     if (myCard > 0)
    80         TContactItemId myCard = m_contactDatabase->OwnCardId();
    86         m_currentOwnCardId = QContactLocalId(myCard);
    81         if (myCard > 0)
    87 
    82             m_currentOwnCardId = QContactLocalId(myCard);
    88     // Currently the group membership check is only used in pre-10.1
    83     }
    89     // platforms. In 10.1 we need to check the performance penalty
    84     CntSymbianTransformError::transformError(err, error);
    90     // caused in the instantiation of QContactManager. If the
       
    91     // performance is too bad, then the MContactDbObserver API needs to
       
    92     // be changed in 10.1 so that we don't need the group membership
       
    93     // buffer in the engine level. In other words events like
       
    94     // EContactDbObserverEventGroupMembersAdded and 
       
    95     // EContactDbObserverEventGroupMembersRemoved need to be added to
       
    96     // MContactDbObserver.
       
    97 #ifndef SYMBIAN_BACKEND_USE_SQLITE
       
    98     updateGroupMembershipsL();
       
    99 #endif
    85 }
   100 }
    86 
   101 
    87 CntSymbianDatabase::~CntSymbianDatabase()
   102 CntSymbianDatabase::~CntSymbianDatabase()
    88 {
   103 {
    89     m_engine = NULL;
   104     m_engine = NULL;
   128     {
   143     {
   129     case EContactDbObserverEventContactAdded:
   144     case EContactDbObserverEventContactAdded:
   130         if(m_contactsEmitted.contains(id))
   145         if(m_contactsEmitted.contains(id))
   131             m_contactsEmitted.removeOne(id);
   146             m_contactsEmitted.removeOne(id);
   132         else
   147         else
   133             changeSet.addedContacts().insert(id);
   148             changeSet.insertAddedContact(id);
   134         break;
   149         break;
   135     case EContactDbObserverEventOwnCardDeleted:
   150     case EContactDbObserverEventOwnCardDeleted:
       
   151         m_currentOwnCardId = QContactLocalId(0);
       
   152         // ...and send contact deleted event
   136     case EContactDbObserverEventContactDeleted:
   153     case EContactDbObserverEventContactDeleted:
   137         if(m_contactsEmitted.contains(id))
   154         if(m_contactsEmitted.contains(id))
   138             m_contactsEmitted.removeOne(id);
   155             m_contactsEmitted.removeOne(id);
   139         else
   156         else
   140             changeSet.removedContacts().insert(id);
   157             changeSet.insertRemovedContact(id);
   141         break;
   158         break;
   142     case EContactDbObserverEventContactChanged:
   159     case EContactDbObserverEventContactChanged:
   143         if(m_contactsEmitted.contains(id))
   160         if(m_contactsEmitted.contains(id))
   144             m_contactsEmitted.removeOne(id);
   161             m_contactsEmitted.removeOne(id);
   145         else
   162         else
   146             changeSet.changedContacts().insert(id);
   163             changeSet.insertChangedContact(id);
   147         break;
   164         break;
   148     case EContactDbObserverEventGroupAdded:
   165     case EContactDbObserverEventGroupAdded:
   149         if(m_contactsEmitted.contains(id))
   166         if(m_contactsEmitted.contains(id)) {
   150             m_contactsEmitted.removeOne(id);
   167             // adding a group triggers also a "changed" event. The work-around
   151         else
   168             // is to leave the id to m_contactsEmitted
   152             changeSet.addedRelationshipsContacts().insert(id);
   169         } else {
       
   170             changeSet.insertAddedContact(id);
       
   171             m_contactsEmitted.append(id);
       
   172         }
   153         break;
   173         break;
   154     case EContactDbObserverEventGroupDeleted:
   174     case EContactDbObserverEventGroupDeleted:
   155         if(m_contactsEmitted.contains(id))
   175         if(m_contactsEmitted.contains(id))
   156             m_contactsEmitted.removeOne(id);
   176             m_contactsEmitted.removeOne(id);
   157         else
   177         else
   158             changeSet.removedRelationshipsContacts().insert(id);
   178             changeSet.insertRemovedContact(id);
   159         break;
   179         break;
   160     case EContactDbObserverEventGroupChanged:
   180     case EContactDbObserverEventGroupChanged:
   161         if(m_contactsEmitted.contains(id))
   181         if(m_contactsEmitted.contains(id))
   162             m_contactsEmitted.removeOne(id);
   182             m_contactsEmitted.removeOne(id);
   163         else
   183         else {
   164             changeSet.changedContacts().insert(id); //group is a contact
   184 #ifndef SYMBIAN_BACKEND_USE_SQLITE
       
   185             // Contact DB observer API does not give information of contacts
       
   186             // possibly added to or removed from the group
       
   187             QSet<QContactLocalId> added;
       
   188             QSet<QContactLocalId> removed;
       
   189             TRAPD(err, updateGroupMembershipsL(id, added, removed));
       
   190             if(err != KErrNone){
       
   191                 changeSet.setDataChanged(true);
       
   192             } else if(removed.count()) {
       
   193                 // The group changed event was caused by removing contacts
       
   194                 // from the group
       
   195                 changeSet.insertRemovedRelationshipsContact(id);
       
   196                 changeSet.insertRemovedRelationshipsContacts(removed.toList());
       
   197             } else if(added.count()) {
       
   198                 // The group changed event was caused by adding contacts
       
   199                 // to the group
       
   200                 changeSet.insertAddedRelationshipsContact(id);
       
   201                 changeSet.insertAddedRelationshipsContacts(added.toList());
       
   202             } else {
       
   203                 // The group changed event was caused by modifying the group
       
   204                 changeSet.insertChangedContact(id);
       
   205             }
       
   206 #else
       
   207             // Currently the group membership check is only used in pre-10.1
       
   208             // platforms. In 10.1 we need to check the performance penalty
       
   209             // caused in the instantiation of QContactManager. If the
       
   210             // performance is too bad, then the MContactDbObserver API needs to
       
   211             // be changed in 10.1 so that we don't need the group membership
       
   212             // buffer in the engine level. In other words events like
       
   213             // EContactDbObserverEventGroupMembersAdded and 
       
   214             // EContactDbObserverEventGroupMembersRemoved need to be added to
       
   215             // MContactDbObserver.
       
   216             changeSet.insertChangedContact(id); //group is a contact
       
   217 #endif
       
   218         }
   165         break;
   219         break;
   166     case EContactDbObserverEventOwnCardChanged:
   220     case EContactDbObserverEventOwnCardChanged:
   167         {
   221         if(m_contactsEmitted.contains(id))
       
   222             m_contactsEmitted.removeOne(id);
       
   223         else {
   168             QOwnCardPair ownCard(m_currentOwnCardId, QContactLocalId(id));
   224             QOwnCardPair ownCard(m_currentOwnCardId, QContactLocalId(id));
   169             changeSet.oldAndNewSelfContactId() = ownCard;
   225             changeSet.setOldAndNewSelfContactId(ownCard);
   170             m_currentOwnCardId = QContactLocalId(id);
   226             m_currentOwnCardId = QContactLocalId(id);
   171             break;
       
   172         }
   227         }
       
   228         break;
   173     default:
   229     default:
   174         break; // ignore other events
   230         break; // ignore other events
   175     }
   231     }
   176 
   232 
   177     changeSet.emitSignals(m_engine);
   233     changeSet.emitSignals(m_engine);
   178 }
   234 }
   179 
   235 
   180 
   236 /*
   181 
   237  * Private implementation for updating the buffer containing the members of all
   182 
   238  * groups.
   183 
   239  */
   184 
   240 void CntSymbianDatabase::updateGroupMembershipsL()
       
   241 {
       
   242     CContactIdArray *groupIds = m_contactDatabase->GetGroupIdListL();
       
   243     for (TInt i(0); i < groupIds->Count(); ++i) {
       
   244         QContactLocalId id = (*groupIds)[i];
       
   245         QSet<QContactLocalId> dummySet;
       
   246         updateGroupMembershipsL(id, dummySet, dummySet);
       
   247     }
       
   248     delete groupIds;
       
   249 }
       
   250 
       
   251 /*
       
   252  * Private implementation for updating the buffer containing the members of a
       
   253  * group.
       
   254  */
       
   255 void CntSymbianDatabase::updateGroupMembershipsL(
       
   256     QContactLocalId groupId,
       
   257     QSet<QContactLocalId> &added,
       
   258     QSet<QContactLocalId> &removed)
       
   259 {
       
   260     QSet<QContactLocalId> groupMembersNew = groupMembersL(groupId);
       
   261     QSet<QContactLocalId> groupMembersOld = m_groupContents.value(groupId);
       
   262 
       
   263     if(groupMembersOld.count() < groupMembersNew.count()) {
       
   264         added = groupMembersNew - groupMembersOld;
       
   265         m_groupContents.remove(groupId);
       
   266         m_groupContents.insert(groupId, groupMembersNew);
       
   267     } else if(groupMembersOld.count() > groupMembersNew.count()) {
       
   268         removed = groupMembersOld - groupMembersNew;
       
   269         m_groupContents.remove(groupId);
       
   270         m_groupContents.insert(groupId, groupMembersNew);
       
   271     }
       
   272 }
       
   273 
       
   274 /*
       
   275  * Private implementation for fetching the members of a group.
       
   276  */
       
   277 QSet<QContactLocalId> CntSymbianDatabase::groupMembersL(QContactLocalId groupId)
       
   278 {
       
   279     QSet<QContactLocalId> groupMembers;
       
   280 
       
   281     CContactItem *contactItem = m_contactDatabase->ReadContactLC(TContactItemId(groupId));
       
   282     Q_ASSERT(contactItem && contactItem->Type() == KUidContactGroup);
       
   283     CContactGroup *group = static_cast<CContactGroup*>(contactItem);
       
   284     
       
   285     const CContactIdArray *idArray = group->ItemsContained();
       
   286     
       
   287     //loop through all the contacts and add them to the list
       
   288     for (int i(0); i < idArray->Count(); i++) {
       
   289         groupMembers.insert((*idArray)[i]);
       
   290     }
       
   291     CleanupStack::PopAndDestroy(contactItem);
       
   292 
       
   293     return groupMembers;
       
   294 }