qtmobility/plugins/contacts/symbiansim/src/cntsymbiansimengine.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 5 453da2cfceef
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
    38 ** $QT_END_LICENSE$
    38 ** $QT_END_LICENSE$
    39 **
    39 **
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 #include "cntsymbiansimengine.h"
    42 #include "cntsymbiansimengine.h"
    43 #include <qtcontacts.h>
       
    44 #include <mmtsy_names.h>
       
    45 
       
    46 #include "cntsymbiansimtransformerror.h"
    43 #include "cntsymbiansimtransformerror.h"
    47 #include "cntsimstore.h"
    44 #include "cntsimstore.h"
    48 #include "cntsimcontactfetchrequest.h"
    45 #include "cntsimcontactfetchrequest.h"
    49 #include "cntsimcontactlocalidfetchrequest.h"
    46 #include "cntsimcontactlocalidfetchrequest.h"
    50 #include "cntsimcontactsaverequest.h"
    47 #include "cntsimcontactsaverequest.h"
    51 #include "cntsimcontactremoverequest.h"
    48 #include "cntsimcontactremoverequest.h"
    52 #include "cntsimdetaildefinitionfetchrequest.h"
    49 #include "cntsimdetaildefinitionfetchrequest.h"
    53 
    50 #include <qtcontacts.h>
    54 #ifdef SYMBIANSIM_BACKEND_USE_ETEL_TESTSERVER
       
    55 #include <mpbutil_etel_test_server.h>
       
    56 #else
       
    57 #include <mpbutil.h>
       
    58 #endif
       
    59 
    51 
    60 #include <QEventLoop>
    52 #include <QEventLoop>
    61 #include <QTimer>
    53 #include <QTimer>
    62 
    54 #include <QDebug>
    63 
    55 
       
    56 const int KRequestTimeout = 30000; // in ms
    64 
    57 
    65 CntSymbianSimEngineData::CntSymbianSimEngineData()
    58 CntSymbianSimEngineData::CntSymbianSimEngineData()
    66     :m_simStore(0)
    59     :m_simStore(0)
    67 {
    60 {
    68     
    61     
    80             qWarning("Dangling async request!");
    73             qWarning("Dangling async request!");
    81         }        
    74         }        
    82     }
    75     }
    83 }
    76 }
    84 
    77 
    85 CntSymbianSimEngine::CntSymbianSimEngine(const QMap<QString, QString>& parameters, QContactManager::Error& error)
    78 CntSymbianSimEngine::CntSymbianSimEngine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
    86 {
    79 {
    87     error = QContactManager::NoError;
    80     *error = QContactManager::NoError;
    88 
    81 
    89     d = new CntSymbianSimEngineData();
    82     d = new CntSymbianSimEngineData();
    90     d->m_simStore = new CntSimStore(this, parameters.value(KParameterKeySimStoreName));
    83     d->m_simStore = new CntSimStore(this, parameters.value(KParameterKeySimStoreName), error);
       
    84     if (*error != QContactManager::NoError) {
       
    85         //qDebug() << "Failed to open SIM store" << error;
       
    86         return;
       
    87     }
    91 
    88 
    92     if(d->m_simStore->storeName() == KParameterValueSimStoreNameSdn) {
    89     if(d->m_simStore->storeName() == KParameterValueSimStoreNameSdn) {
    93         // In case of SDN store we need to check if any SDN contacts exist to
    90         // In case of SDN store we need to check if any SDN contacts exist to
    94         // determine if the store is supported or not
    91         // determine if the store is supported or not
    95         if(d->m_simStore->storeInfo().iUsedEntries == 0)
    92         if(d->m_simStore->storeInfo().iUsedEntries == 0)
    96             error = QContactManager::NotSupportedError;
    93             *error = QContactManager::NotSupportedError;
    97     }    
    94     }    
    98 }
    95 }
    99 
    96 
   100 CntSymbianSimEngine::CntSymbianSimEngine(const CntSymbianSimEngine &other)
    97 CntSymbianSimEngine::CntSymbianSimEngine(const CntSymbianSimEngine &other)
   101     :d(other.d)
    98     :d(other.d)
   106 CntSymbianSimEngine::~CntSymbianSimEngine()
   103 CntSymbianSimEngine::~CntSymbianSimEngine()
   107 {
   104 {
   108 
   105 
   109 }
   106 }
   110 
   107 
   111 void CntSymbianSimEngine::deref()
       
   112 {
       
   113     delete this;
       
   114 }
       
   115 
       
   116 QString CntSymbianSimEngine::managerName() const
   108 QString CntSymbianSimEngine::managerName() const
   117 {
   109 {
   118     return CNT_SYMBIANSIM_MANAGER_NAME;
   110     return CNT_SYMBIANSIM_MANAGER_NAME;
   119 }
       
   120 
       
   121 /*!
       
   122  * Returns a list of the ids of contacts that match the supplied \a filter.
       
   123  * Any error that occurs will be stored in \a error.
       
   124  */
       
   125 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const
       
   126 {
       
   127     QContactLocalIdFetchRequest req;
       
   128     req.setSorting(sortOrders);
       
   129     executeRequest(&req, error);
       
   130     return req.ids();
       
   131 }
   111 }
   132 
   112 
   133 /*!
   113 /*!
   134  * Returns a list of the ids of contacts that match the supplied \a filter, sorted according to the given \a sortOrders.
   114  * Returns a list of the ids of contacts that match the supplied \a filter, sorted according to the given \a sortOrders.
   135  * Any error that occurs will be stored in \a error. Uses the generic (slow) filtering of QContactManagerEngine.
   115  * Any error that occurs will be stored in \a error. Uses the generic (slow) filtering of QContactManagerEngine.
   136  */
   116  */
   137 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const
   117 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
   138 {
   118 {
   139     QContactLocalIdFetchRequest req;
   119     QContactLocalIdFetchRequest req;
   140     req.setFilter(filter);
   120     req.setFilter(filter);
   141     req.setSorting(sortOrders);
   121     req.setSorting(sortOrders);
   142     executeRequest(&req, error);
   122     executeRequest(&req, error);
   143     return req.ids();
   123     return req.ids();
   144 }
   124 }
   145 
   125 
   146 QList<QContact> CntSymbianSimEngine::contacts(const QList<QContactSortOrder>& sortOrders, const QStringList& definitionRestrictions, QContactManager::Error& error) const
   126 QList<QContact> CntSymbianSimEngine::contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
   147 {
       
   148     QContactFetchRequest req;
       
   149     req.setSorting(sortOrders);
       
   150     req.setDefinitionRestrictions(definitionRestrictions);
       
   151     executeRequest(&req, error);
       
   152     return req.contacts();
       
   153 }
       
   154 
       
   155 QList<QContact> CntSymbianSimEngine::contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, const QStringList& definitionRestrictions, QContactManager::Error& error) const
       
   156 {
   127 {
   157     QContactFetchRequest req;
   128     QContactFetchRequest req;
   158     req.setFilter(filter);
   129     req.setFilter(filter);
   159     req.setSorting(sortOrders);
   130     req.setSorting(sortOrders);
   160     req.setDefinitionRestrictions(definitionRestrictions);
   131     req.setFetchHint(fetchHint);
   161     executeRequest(&req, error);
   132     executeRequest(&req, error);
   162     return req.contacts();
   133     return req.contacts();
   163 }
   134 }
   164 
   135 
   165 /*!
   136 /*!
   169  * \param definitionRestrictions Definition restrictions.
   140  * \param definitionRestrictions Definition restrictions.
   170  * \param error Qt error code.
   141  * \param error Qt error code.
   171  * \return A QContact for the requested QContactLocalId value or 0 if the read
   142  * \return A QContact for the requested QContactLocalId value or 0 if the read
   172  *  operation was unsuccessful (e.g. contact not found).
   143  *  operation was unsuccessful (e.g. contact not found).
   173  */
   144  */
   174 QContact CntSymbianSimEngine::contact(const QContactLocalId& contactId, const QStringList& definitionRestrictions, QContactManager::Error& error) const
   145 QContact CntSymbianSimEngine::contact(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
   175 {
   146 {
   176     QContactFetchRequest req;
   147     QContactFetchRequest req;
   177     QContactLocalIdFilter filter;
   148     QContactLocalIdFilter filter;
   178     filter.setIds(QList<QContactLocalId>() << contactId);
   149     filter.setIds(QList<QContactLocalId>() << contactId);
   179     req.setFilter(filter);
   150     req.setFilter(filter);
   180     req.setDefinitionRestrictions(definitionRestrictions);
   151     req.setFetchHint(fetchHint);
   181     executeRequest(&req, error);
   152     executeRequest(&req, error);
   182     if (req.contacts().count() == 0)
   153     if (req.contacts().count() == 0)
   183         return QContact();
   154         return QContact();
   184     return req.contacts().at(0); 
   155     return req.contacts().at(0); 
   185 }
   156 }
   186 
   157 
   187 QString CntSymbianSimEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error& error) const
   158 QString CntSymbianSimEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error* error) const
   188 {
   159 {
   189     Q_UNUSED(error);
   160     Q_UNUSED(error);
   190 
   161 
   191     QContactName name = contact.detail(QContactName::DefinitionName);
   162     QContactName name = contact.detail(QContactName::DefinitionName);
   192     if(!name.customLabel().isEmpty()) {
   163     if(!name.customLabel().isEmpty()) {
   196         return QString("Unnamed");
   167         return QString("Unnamed");
   197     }
   168     }
   198 }
   169 }
   199 
   170 
   200 /*!
   171 /*!
   201  * Saves the contact to the Etel store. Only part of the contact's details
   172  * Saves the contacts to the Etel store. Only part of the contact's details
   202  * can be saved, and some fields may be trimmed to fit to the SIM card.
   173  * can be saved, and some fields may be trimmed to fit to the SIM card.
   203  *
   174  *
   204  * \param contact Contact to be saved.
   175  * \param contacts Contact to be saved.
   205  * \param qtError Qt error code.
   176  * \param qtError Qt error code.
   206  * \return Error status.
   177  * \return Error status.
   207  */
   178  */
   208 bool CntSymbianSimEngine::saveContact(QContact* contact, QContactManager::Error& error)
   179 bool CntSymbianSimEngine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
   209 {
       
   210     if (!contact) {
       
   211         error = QContactManager::BadArgumentError;
       
   212         return false;
       
   213     }
       
   214     
       
   215     QContactSaveRequest req;
       
   216     req.setContacts(QList<QContact>() << *contact);
       
   217     executeRequest(&req, error);
       
   218     if (req.contacts().count())
       
   219         *contact = req.contacts().at(0);
       
   220     return (error == QContactManager::NoError);
       
   221 }
       
   222 
       
   223 bool CntSymbianSimEngine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error& error)
       
   224 {
   180 {
   225     if (!contacts) {
   181     if (!contacts) {
   226         error = QContactManager::BadArgumentError;
   182         *error = QContactManager::BadArgumentError;
   227         return false;
   183         return false;
   228     }
   184     }
   229     
   185     
   230     QContactSaveRequest req;
   186     QContactSaveRequest req;
   231     req.setContacts(*contacts);
   187     req.setContacts(*contacts);
   232     executeRequest(&req, error);
   188     executeRequest(&req, error);
   233     if (errorMap)
   189     if (errorMap)
   234         *errorMap = req.errorMap();
   190         *errorMap = req.errorMap();
   235     *contacts = req.contacts();
   191     *contacts = req.contacts();
   236     return (error == QContactManager::NoError );    
   192     return (*error == QContactManager::NoError );
   237 }
   193 }
   238 
   194 
   239 /*!
   195 /*!
   240  * Removes the specified contact object from the Etel store.
   196  * Removes the specified contact object from the Etel store.
   241  *
   197  *
   242  * \param contactId Id of the contact to be removed.
   198  * \param contactId Id of the contact to be removed.
   243  * \param qtError Qt error code.
   199  * \param qtError Qt error code.
   244  * \return Error status.
   200  * \return Error status.
   245  */
   201  */
   246 bool CntSymbianSimEngine::removeContact(const QContactLocalId& contactId, QContactManager::Error& error)
   202 bool CntSymbianSimEngine::removeContacts(const QList<QContactLocalId>& contactIds, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
   247 {
   203 {
   248     QContactRemoveRequest req;
   204     QContactRemoveRequest req;
   249     req.setContactIds(QList<QContactLocalId>() << contactId);
   205     req.setContactIds(contactIds);
   250     return executeRequest(&req, error);
       
   251 }
       
   252 
       
   253 bool CntSymbianSimEngine::removeContacts(QList<QContactLocalId>* contactIds, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error& error)
       
   254 {
       
   255     if (!contactIds) {
       
   256         error = QContactManager::BadArgumentError;
       
   257         return false;
       
   258     }    
       
   259     QContactRemoveRequest req;
       
   260     req.setContactIds(*contactIds);
       
   261     executeRequest(&req, error);
   206     executeRequest(&req, error);
   262     if (errorMap)
   207     if (errorMap)
   263         *errorMap = req.errorMap();    
   208         *errorMap = req.errorMap();    
   264     return (error == QContactManager::NoError);    
   209     return (*error == QContactManager::NoError);
   265 }
   210 }
   266 
   211 
   267 /*!
   212 /*!
   268  * Returns a map of identifier to detail definition which are valid for contacts whose type is the given \a contactType
   213  * Returns a map of identifier to detail definition which are valid for contacts whose type is the given \a contactType
   269  * which are valid for the contacts in this store
   214  * which are valid for the contacts in this store
   270  */
   215  */
   271 QMap<QString, QContactDetailDefinition> CntSymbianSimEngine::detailDefinitions(const QString& contactType, QContactManager::Error& error) const
   216 QMap<QString, QContactDetailDefinition> CntSymbianSimEngine::detailDefinitions(const QString& contactType, QContactManager::Error* error) const
   272 {
   217 {
   273     if (!supportedContactTypes().contains(contactType)) {
   218     if (!supportedContactTypes().contains(contactType)) {
   274         // Should never happen
   219         // Should never happen
   275         error = QContactManager::NotSupportedError;
   220         *error = QContactManager::NotSupportedError;
   276         return QMap<QString, QContactDetailDefinition>();
   221         return QMap<QString, QContactDetailDefinition>();
   277     }
   222     }
   278 
   223 
   279     // Get store information
   224     // Get store information
   280     RMobilePhoneBookStore::TMobilePhoneBookInfoV5 storeInfo = d->m_simStore->storeInfo();
   225     TSimStoreInfo storeInfo = d->m_simStore->storeInfo();
   281 
   226 
   282     // the map we will eventually return
   227     // the map we will eventually return
   283     QMap<QString, QContactDetailDefinition> retn;
   228     QMap<QString, QContactDetailDefinition> retn;
   284 
   229 
   285     // local variables for reuse
   230     // local variables for reuse
   338     def.setFields(fields);
   283     def.setFields(fields);
   339     def.setUnique(true);
   284     def.setUnique(true);
   340     retn.insert(def.name(), def);
   285     retn.insert(def.name(), def);
   341 
   286 
   342     // email support needs to be checked run-time, because it is SIM specific
   287     // email support needs to be checked run-time, because it is SIM specific
       
   288 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
   343     if (storeInfo.iMaxEmailAddr > 0) {
   289     if (storeInfo.iMaxEmailAddr > 0) {
   344         def.setName(QContactEmailAddress::DefinitionName);
   290         def.setName(QContactEmailAddress::DefinitionName);
   345         fields.clear();
   291         fields.clear();
   346         f.setDataType(QVariant::String);
   292         f.setDataType(QVariant::String);
   347         f.setAllowableValues(QVariantList());
   293         f.setAllowableValues(QVariantList());
   348         fields.insert(QContactEmailAddress::FieldEmailAddress, f);
   294         fields.insert(QContactEmailAddress::FieldEmailAddress, f);
   349         def.setFields(fields);
   295         def.setFields(fields);
   350         def.setUnique(true);
   296         def.setUnique(true);
   351         retn.insert(def.name(), def);
   297         retn.insert(def.name(), def);
   352     }
   298     }
       
   299 #endif
   353 
   300 
   354     // phone number
   301     // phone number
   355     def.setName(QContactPhoneNumber::DefinitionName);
   302     def.setName(QContactPhoneNumber::DefinitionName);
   356     fields.clear();
   303     fields.clear();
   357     f.setDataType(QVariant::String);
   304     f.setDataType(QVariant::String);
   358     f.setAllowableValues(QVariantList());
   305     f.setAllowableValues(QVariantList());
   359     fields.insert(QContactPhoneNumber::FieldNumber, f);
   306     fields.insert(QContactPhoneNumber::FieldNumber, f);
   360     // TODO: subtypes supported in case a sim contact can have multiple phone numbers?
   307     // TODO: subtypes supported in case a sim contact can have multiple phone numbers?
   361     def.setFields(fields);
   308     def.setFields(fields);
       
   309 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
   362     if (storeInfo.iMaxAdditionalNumbers > 0) {
   310     if (storeInfo.iMaxAdditionalNumbers > 0) {
   363         // multiple numbers supported
   311         // multiple numbers supported
   364         def.setUnique(false);
   312         def.setUnique(false);
   365     } else {
   313     } else {
   366         // only one phone number allowed
   314         // only one phone number allowed
   367         def.setUnique(true);
   315         def.setUnique(true);
   368     }
   316     }
       
   317 #else
       
   318     // only one phone number allowed
       
   319     def.setUnique(true);
       
   320 #endif
   369     retn.insert(def.name(), def);
   321     retn.insert(def.name(), def);
   370 
   322 
   371     // nickname support needs to be checked run-time, because it is SIM specific
   323     // nickname support needs to be checked run-time, because it is SIM specific
       
   324 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
   372     if (storeInfo.iMaxSecondNames > 0) {
   325     if (storeInfo.iMaxSecondNames > 0) {
   373         def.setName(QContactNickname::DefinitionName);
   326         def.setName(QContactNickname::DefinitionName);
   374         fields.clear();
   327         fields.clear();
   375         f.setDataType(QVariant::String);
   328         f.setDataType(QVariant::String);
   376         f.setAllowableValues(QVariantList());
   329         f.setAllowableValues(QVariantList());
   377         fields.insert(QContactNickname::FieldNickname, f);
   330         fields.insert(QContactNickname::FieldNickname, f);
   378         def.setFields(fields);
   331         def.setFields(fields);
   379         def.setUnique(true);
   332         def.setUnique(true);
   380         retn.insert(def.name(), def);
   333         retn.insert(def.name(), def);
   381     }
   334     }
       
   335 #endif
   382 
   336 
   383     // name
   337     // name
   384     def.setName(QContactName::DefinitionName);
   338     def.setName(QContactName::DefinitionName);
   385     fields.clear();
   339     fields.clear();
   386     f.setDataType(QVariant::String);
   340     f.setDataType(QVariant::String);
   524 }
   478 }
   525 
   479 
   526 void CntSymbianSimEngine::updateDisplayLabel(QContact& contact) const
   480 void CntSymbianSimEngine::updateDisplayLabel(QContact& contact) const
   527 {
   481 {
   528     QContactManager::Error error(QContactManager::NoError);
   482     QContactManager::Error error(QContactManager::NoError);
   529     QString label = synthesizedDisplayLabel(contact, error);
   483     QString label = synthesizedDisplayLabel(contact, &error);
   530     if(error == QContactManager::NoError) {
   484     if(error == QContactManager::NoError) {
   531         contact = setContactDisplayLabel(label, contact);
   485         setContactDisplayLabel(&contact, label);
   532     }
   486     }
       
   487 }
       
   488 
       
   489 void CntSymbianSimEngine::setReadOnlyAccessConstraint(QContactDetail* detail) const
       
   490 {
       
   491     setDetailAccessConstraints(detail, QContactDetail::ReadOnly); 
   533 }
   492 }
   534 
   493 
   535 /*!
   494 /*!
   536  * Executes an asynchronous request so that it will appear synchronous. This is
   495  * Executes an asynchronous request so that it will appear synchronous. This is
   537  * used internally in all synchronous functions. This way we only need to 
   496  * used internally in all synchronous functions. This way we only need to 
   539  * 
   498  * 
   540  * \param req Request to be run.
   499  * \param req Request to be run.
   541  * \param qtError Qt error code.
   500  * \param qtError Qt error code.
   542  * \return true if succesfull, false if unsuccesfull.
   501  * \return true if succesfull, false if unsuccesfull.
   543  */
   502  */
   544 bool CntSymbianSimEngine::executeRequest(QContactAbstractRequest *req, QContactManager::Error& qtError) const
   503 bool CntSymbianSimEngine::executeRequest(QContactAbstractRequest *req, QContactManager::Error* qtError) const
   545 {
   504 {
       
   505     *qtError = QContactManager::NoError;
       
   506     
   546     // TODO:
   507     // TODO:
   547     // Remove this code when threads-branch is merged to master. Then this code
   508     // Remove this code when threads-branch is merged to master. Then this code
   548     // should not be needed because the default implementation at QContactManager
   509     // should not be needed because the default implementation at QContactManager
   549     // is using the asynchronous requests in a similar manner to implement
   510     // is using the asynchronous requests in a similar manner to implement
   550     // the synchronous functions.
   511     // the synchronous functions.
   551     
   512     
   552     // Create a copy engine to workaround this functions const qualifier
   513     // Create a copy engine to workaround this functions const qualifier
   553     CntSymbianSimEngine engine(*this);
   514     CntSymbianSimEngine engine(*this);
   554     
   515     
   555     // Mimic the way how async requests are normally run
   516     // Mimic the way how async requests are normally run
   556     if (engine.startRequest(req))
   517     if (!engine.startRequest(req)) {
   557         engine.waitForRequestFinished(req, 0); // should we have a timeout?
   518         *qtError = QContactManager::LockedError;
       
   519     } else {
       
   520         if (!engine.waitForRequestFinished(req, KRequestTimeout))
       
   521             *qtError = QContactManager::UnspecifiedError; // timeout occurred
       
   522     }
   558     engine.requestDestroyed(req);
   523     engine.requestDestroyed(req);
   559     
   524     
   560     qtError = req->error();
   525     if (req->error())
   561     return (qtError == QContactManager::NoError);
   526         *qtError = req->error();
   562 }
   527     
   563 
   528     return (*qtError == QContactManager::NoError);
   564 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error& error)
   529 }
       
   530 
       
   531 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
   565 {
   532 {
   566     CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error);
   533     CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error);
   567     if(error != QContactManager::NoError) {
   534     if(*error != QContactManager::NoError) {
   568         delete engine;
   535         delete engine;
   569         return 0;
   536         return 0;
   570     }
   537     }
   571     return engine;
   538     return engine;
   572 }
   539 }