plugins/contacts/symbiansim/src/cntsymbiansimengine.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "cntsymbiansimengine.h"
       
    43 #include "cntsymbiansimtransformerror.h"
       
    44 #include "cntsimstore.h"
       
    45 #include "cntsimcontactfetchrequest.h"
       
    46 #include "cntsimcontactlocalidfetchrequest.h"
       
    47 #include "cntsimcontactsaverequest.h"
       
    48 #include "cntsimcontactremoverequest.h"
       
    49 #include "cntsimdetaildefinitionfetchrequest.h"
       
    50 #include <qtcontacts.h>
       
    51 
       
    52 #include <QEventLoop>
       
    53 #include <QTimer>
       
    54 #include <QDebug>
       
    55 
       
    56 #include <centralrepository.h>
       
    57 
       
    58 // Telephony Configuration API
       
    59 // Keys under this category are used in defining telephony configuration.
       
    60 const TUid KCRUidTelConfiguration = {0x102828B8};
       
    61 // Amount of digits to be used in contact matching.
       
    62 // This allows a customer to variate the amount of digits to be matched.
       
    63 const TUint32 KTelMatchDigits                               = 0x00000001;
       
    64 // Default match length
       
    65 const TInt KDefaultMatchLength(7);
       
    66 
       
    67 
       
    68 CntSymbianSimEngineData::CntSymbianSimEngineData()
       
    69     :m_simStore(0)
       
    70 {
       
    71     
       
    72 }
       
    73 
       
    74 CntSymbianSimEngineData::~CntSymbianSimEngineData()
       
    75 {
       
    76     if (ref == 0) {
       
    77         // Remove all unfinished requests.
       
    78         // If the client has behaved itself then there should be none left.
       
    79         while (m_asyncRequests.size()) {
       
    80             QMap<QContactAbstractRequest *, CntAbstractSimRequest *>::iterator itr = m_asyncRequests.begin();
       
    81             delete itr.value();
       
    82             m_asyncRequests.remove(itr.key());
       
    83             qWarning("Dangling async request!");
       
    84         }        
       
    85     }
       
    86 }
       
    87 
       
    88 CntSymbianSimEngine::CntSymbianSimEngine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
       
    89 {
       
    90     *error = QContactManager::NoError;
       
    91 
       
    92     d = new CntSymbianSimEngineData();
       
    93     d->m_simStore = new CntSimStore(this, parameters.value(KParameterKeySimStoreName), error);
       
    94     if (*error != QContactManager::NoError) {
       
    95         //qDebug() << "Failed to open SIM store" << error;
       
    96         return;
       
    97     }
       
    98     
       
    99     // Get phone number match length from cenrep
       
   100     d->m_phoneNumberMatchLen = KDefaultMatchLength;
       
   101     TRAP_IGNORE(getMatchLengthL(d->m_phoneNumberMatchLen)); // ignore error and use default value
       
   102 
       
   103     if(d->m_simStore->storeInfo().m_storeName == KParameterValueSimStoreNameSdn) {
       
   104         // In case of SDN store we need to check if any SDN contacts exist to
       
   105         // determine if the store is supported or not
       
   106         if(d->m_simStore->storeInfo().m_usedEntries == 0)
       
   107             *error = QContactManager::NotSupportedError;
       
   108     }    
       
   109 }
       
   110 
       
   111 CntSymbianSimEngine::CntSymbianSimEngine(const CntSymbianSimEngine &other)
       
   112     :d(other.d)
       
   113 {
       
   114     
       
   115 }
       
   116 
       
   117 CntSymbianSimEngine::~CntSymbianSimEngine()
       
   118 {
       
   119 
       
   120 }
       
   121 
       
   122 QString CntSymbianSimEngine::managerName() const
       
   123 {
       
   124     return CNT_SYMBIANSIM_MANAGER_NAME;
       
   125 }
       
   126 
       
   127 /*!
       
   128  * Returns a list of the ids of contacts that match the supplied \a filter, sorted according to the given \a sortOrders.
       
   129  * Any error that occurs will be stored in \a error. Uses the generic (slow) filtering of QContactManagerEngine.
       
   130  */
       
   131 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
       
   132 {
       
   133     QContactLocalIdFetchRequest req;
       
   134     req.setFilter(filter);
       
   135     req.setSorting(sortOrders);
       
   136     executeRequest(&req, error);
       
   137     return req.ids();
       
   138 }
       
   139 
       
   140 QList<QContact> CntSymbianSimEngine::contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
       
   141 {
       
   142     QContactFetchRequest req;
       
   143     req.setFilter(filter);
       
   144     req.setSorting(sortOrders);
       
   145     req.setFetchHint(fetchHint);
       
   146     executeRequest(&req, error);
       
   147     return req.contacts();
       
   148 }
       
   149 
       
   150 /*!
       
   151  * Reads a contact from the Etel store.
       
   152  *
       
   153  * \param contactId The Id of the contact to be retrieved.
       
   154  * \param definitionRestrictions Definition restrictions.
       
   155  * \param error Qt error code.
       
   156  * \return A QContact for the requested QContactLocalId value or 0 if the read
       
   157  *  operation was unsuccessful (e.g. contact not found).
       
   158  */
       
   159 QContact CntSymbianSimEngine::contact(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
       
   160 {
       
   161     QContactFetchRequest req;
       
   162     QContactLocalIdFilter filter;
       
   163     filter.setIds(QList<QContactLocalId>() << contactId);
       
   164     req.setFilter(filter);
       
   165     req.setFetchHint(fetchHint);
       
   166     executeRequest(&req, error);
       
   167     if (req.contacts().count() == 0)
       
   168         return QContact();
       
   169     return req.contacts().at(0); 
       
   170 }
       
   171 
       
   172 QString CntSymbianSimEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error* error) const
       
   173 {
       
   174     Q_UNUSED(error);
       
   175 
       
   176     QContactName name = contact.detail(QContactName::DefinitionName);
       
   177     if(!name.customLabel().isEmpty()) {
       
   178         return name.customLabel();
       
   179     } else {
       
   180         return QString("");
       
   181     }
       
   182 }
       
   183 
       
   184 /*!
       
   185  * Saves the contacts to the Etel store. Only part of the contact's details
       
   186  * can be saved, and some fields may be trimmed to fit to the SIM card.
       
   187  *
       
   188  * \param contacts Contact to be saved.
       
   189  * \param qtError Qt error code.
       
   190  * \return Error status.
       
   191  */
       
   192 bool CntSymbianSimEngine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
   193 {
       
   194     if (!contacts) {
       
   195         *error = QContactManager::BadArgumentError;
       
   196         return false;
       
   197     }
       
   198     
       
   199     QContactSaveRequest req;
       
   200     req.setContacts(*contacts);
       
   201     executeRequest(&req, error);
       
   202     if (errorMap)
       
   203         *errorMap = req.errorMap();
       
   204     *contacts = req.contacts();
       
   205     return (*error == QContactManager::NoError );
       
   206 }
       
   207 
       
   208 /*!
       
   209  * Removes the specified contact object from the Etel store.
       
   210  *
       
   211  * \param contactId Id of the contact to be removed.
       
   212  * \param qtError Qt error code.
       
   213  * \return Error status.
       
   214  */
       
   215 bool CntSymbianSimEngine::removeContacts(const QList<QContactLocalId>& contactIds, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
       
   216 {
       
   217     QContactRemoveRequest req;
       
   218     req.setContactIds(contactIds);
       
   219     executeRequest(&req, error);
       
   220     if (errorMap)
       
   221         *errorMap = req.errorMap();    
       
   222     return (*error == QContactManager::NoError);
       
   223 }
       
   224 
       
   225 /*!
       
   226  * Returns a map of identifier to detail definition which are valid for contacts whose type is the given \a contactType
       
   227  * which are valid for the contacts in this store
       
   228  */
       
   229 QMap<QString, QContactDetailDefinition> CntSymbianSimEngine::detailDefinitions(const QString& contactType, QContactManager::Error* error) const
       
   230 {
       
   231     if (!supportedContactTypes().contains(contactType)) {
       
   232         // Should never happen
       
   233         *error = QContactManager::NotSupportedError;
       
   234         return QMap<QString, QContactDetailDefinition>();
       
   235     }
       
   236 
       
   237     // Get store information
       
   238     SimStoreInfo storeInfo = d->m_simStore->storeInfo();
       
   239 
       
   240     // the map we will eventually return
       
   241     QMap<QString, QContactDetailDefinition> retn;
       
   242 
       
   243     // local variables for reuse
       
   244     QMap<QString, QContactDetailFieldDefinition> fields;
       
   245     QContactDetailFieldDefinition f;
       
   246     QContactDetailDefinition def;
       
   247     QVariantList subTypes;
       
   248 
       
   249     // sync target
       
   250     def.setName(QContactSyncTarget::DefinitionName);
       
   251     fields.clear();
       
   252     f.setDataType(QVariant::String);
       
   253     subTypes.clear();
       
   254     subTypes << QString(QLatin1String(KSimSyncTarget));
       
   255     f.setAllowableValues(subTypes);
       
   256     fields.insert(QContactSyncTarget::FieldSyncTarget, f);
       
   257     def.setFields(fields);
       
   258     def.setUnique(true);
       
   259     retn.insert(def.name(), def);
       
   260 
       
   261     // type
       
   262     def.setName(QContactType::DefinitionName);
       
   263     fields.clear();
       
   264     f.setDataType(QVariant::String);
       
   265     subTypes.clear();
       
   266     // groups are not supported
       
   267     subTypes << QString(QLatin1String(QContactType::TypeContact));
       
   268     f.setAllowableValues(subTypes);
       
   269     fields.insert(QContactType::FieldType, f); // note: NO CONTEXT!!
       
   270     def.setFields(fields);
       
   271     def.setUnique(true);
       
   272     retn.insert(def.name(), def);
       
   273 
       
   274 /* TODO
       
   275     // guid
       
   276     def.setName(QContactGuid::DefinitionName);
       
   277     fields.clear();
       
   278     f.setDataType(QVariant::String);
       
   279     f.setAllowableValues(QVariantList());
       
   280     fields.insert(QContactGuid::FieldGuid, f);
       
   281     f.setDataType(QVariant::StringList);
       
   282     f.setAllowableValues(contexts);
       
   283     fields.insert(QContactDetail::FieldContext, f);
       
   284     def.setFields(fields);
       
   285     def.setUnique(false);
       
   286     def.setAccessConstraint(QContactDetailDefinition::CreateOnly);
       
   287     retn.insert(def.name(), def);
       
   288 */
       
   289 
       
   290     // display label
       
   291     def.setName(QContactDisplayLabel::DefinitionName);
       
   292     fields.clear();
       
   293     f.setDataType(QVariant::String);
       
   294     f.setAllowableValues(QVariantList());
       
   295     fields.insert(QContactDisplayLabel::FieldLabel, f);
       
   296     def.setFields(fields);
       
   297     def.setUnique(true);
       
   298     retn.insert(def.name(), def);
       
   299 
       
   300     // email support needs to be checked run-time, because it is SIM specific
       
   301     if (storeInfo.m_emailSupported) {
       
   302         def.setName(QContactEmailAddress::DefinitionName);
       
   303         fields.clear();
       
   304         f.setDataType(QVariant::String);
       
   305         f.setAllowableValues(QVariantList());
       
   306         fields.insert(QContactEmailAddress::FieldEmailAddress, f);
       
   307         def.setFields(fields);
       
   308         def.setUnique(true);
       
   309         retn.insert(def.name(), def);
       
   310     }
       
   311 
       
   312     // phone number
       
   313     def.setName(QContactPhoneNumber::DefinitionName);
       
   314     fields.clear();
       
   315     f.setDataType(QVariant::String);
       
   316     f.setAllowableValues(QVariantList());
       
   317     fields.insert(QContactPhoneNumber::FieldNumber, f);
       
   318     // TODO: subtypes supported in case a sim contact can have multiple phone numbers?
       
   319     def.setFields(fields);
       
   320     if (storeInfo.m_additionalNumberSupported) {
       
   321         // multiple numbers supported
       
   322         def.setUnique(false);
       
   323     } else {
       
   324         // only one phone number allowed
       
   325         def.setUnique(true);
       
   326     }
       
   327     retn.insert(def.name(), def);
       
   328 
       
   329     // nickname support needs to be checked run-time, because it is SIM specific
       
   330     if (storeInfo.m_secondNameSupported) {
       
   331         def.setName(QContactNickname::DefinitionName);
       
   332         fields.clear();
       
   333         f.setDataType(QVariant::String);
       
   334         f.setAllowableValues(QVariantList());
       
   335         fields.insert(QContactNickname::FieldNickname, f);
       
   336         def.setFields(fields);
       
   337         def.setUnique(true);
       
   338         retn.insert(def.name(), def);
       
   339     }
       
   340 
       
   341     // name
       
   342     def.setName(QContactName::DefinitionName);
       
   343     fields.clear();
       
   344     f.setDataType(QVariant::String);
       
   345     f.setAllowableValues(QVariantList());
       
   346     fields.insert(QContactName::FieldCustomLabel, f);
       
   347     def.setFields(fields);
       
   348     def.setUnique(true);
       
   349     retn.insert(def.name(), def);
       
   350 
       
   351     return retn;
       
   352 }
       
   353 
       
   354 void CntSymbianSimEngine::requestDestroyed(QContactAbstractRequest* req)
       
   355 {
       
   356     if (d->m_asyncRequests.contains(req)) {
       
   357         delete d->m_asyncRequests.take(req); 
       
   358     }
       
   359 }
       
   360 
       
   361 bool CntSymbianSimEngine::startRequest(QContactAbstractRequest* req)
       
   362 {
       
   363     // Don't allow two async requests to be active at the same time.
       
   364     // The RMobilePhoneBookStore cannot handle it.
       
   365     foreach (QContactAbstractRequest* r, d->m_asyncRequests.keys()) {
       
   366         if (r->isActive()) {
       
   367             // TODO: Should we set the error for the request also?
       
   368             return false;
       
   369         }
       
   370     }
       
   371     
       
   372     // Check for existing request and start again
       
   373     if (d->m_asyncRequests.contains(req)) {
       
   374         return d->m_asyncRequests.value(req)->start();
       
   375     }
       
   376     
       
   377     // Existing request not found. Create a new one.
       
   378     CntAbstractSimRequest* simReq = 0;
       
   379     switch (req->type()) 
       
   380     {
       
   381         case QContactAbstractRequest::ContactFetchRequest:
       
   382         {
       
   383             QContactFetchRequest* r = static_cast<QContactFetchRequest*>(req);
       
   384             simReq = new CntSimContactFetchRequest(this, r);
       
   385         }
       
   386         break;
       
   387 
       
   388         case QContactAbstractRequest::ContactLocalIdFetchRequest:
       
   389         {
       
   390             QContactLocalIdFetchRequest* r = static_cast<QContactLocalIdFetchRequest*>(req);
       
   391             simReq = new CntSimContactLocalIdFetchRequest(this, r);
       
   392         }
       
   393         break;
       
   394 
       
   395         case QContactAbstractRequest::ContactSaveRequest:
       
   396         {
       
   397             QContactSaveRequest* r = static_cast<QContactSaveRequest*>(req);
       
   398             simReq = new CntSimContactSaveRequest(this, r);
       
   399         }
       
   400         break;
       
   401 
       
   402         case QContactAbstractRequest::ContactRemoveRequest:
       
   403         {
       
   404             QContactRemoveRequest* r = static_cast<QContactRemoveRequest*>(req);
       
   405             simReq = new CntSimContactRemoveRequest(this, r);
       
   406         }
       
   407         break;
       
   408 
       
   409         case QContactAbstractRequest::DetailDefinitionFetchRequest:
       
   410         {
       
   411             QContactDetailDefinitionFetchRequest* r = static_cast<QContactDetailDefinitionFetchRequest*>(req);
       
   412             simReq = new CntSimDetailDefinitionFetchRequest(this, r);
       
   413         }
       
   414         break;
       
   415 
       
   416         case QContactAbstractRequest::DetailDefinitionSaveRequest:
       
   417         case QContactAbstractRequest::DetailDefinitionRemoveRequest:
       
   418         case QContactAbstractRequest::RelationshipFetchRequest:
       
   419         case QContactAbstractRequest::RelationshipSaveRequest:
       
   420         case QContactAbstractRequest::RelationshipRemoveRequest:
       
   421         // fall through.
       
   422         default: // unknown request type.
       
   423         break;
       
   424     }
       
   425     
       
   426     if (simReq) {
       
   427         d->m_asyncRequests.insert(req, simReq);
       
   428         return simReq->start();
       
   429     }
       
   430         
       
   431     return false;
       
   432 }
       
   433 
       
   434 bool CntSymbianSimEngine::cancelRequest(QContactAbstractRequest* req)
       
   435 {
       
   436     if (d->m_asyncRequests.contains(req))
       
   437         return d->m_asyncRequests.value(req)->cancel();
       
   438     return false;
       
   439 }
       
   440 
       
   441 bool CntSymbianSimEngine::waitForRequestFinished(QContactAbstractRequest* req, int msecs)
       
   442 {
       
   443     if (!d->m_asyncRequests.contains(req)) 
       
   444         return false;
       
   445     
       
   446     if (req->state() != QContactAbstractRequest::ActiveState)
       
   447         return false;
       
   448     
       
   449     QEventLoop *loop = new QEventLoop(this);
       
   450     QObject::connect(req, SIGNAL(resultsAvailable()), loop, SLOT(quit()));
       
   451 
       
   452     // NOTE: zero means wait forever
       
   453     if (msecs > 0)
       
   454         QTimer::singleShot(msecs, loop, SLOT(quit()));
       
   455 
       
   456     loop->exec();
       
   457     loop->disconnect();
       
   458     loop->deleteLater();
       
   459 
       
   460     return (req->state() == QContactAbstractRequest::FinishedState);
       
   461 }
       
   462 
       
   463 /*!
       
   464  * Returns true if the given feature \a feature is supported by the manager,
       
   465  * for the specified type of contact \a contactType
       
   466  */
       
   467 bool CntSymbianSimEngine::hasFeature(QContactManager::ManagerFeature feature, const QString& contactType) const
       
   468 {
       
   469     Q_UNUSED(feature);
       
   470     Q_UNUSED(contactType);
       
   471     // We don't support anything in the ManagerFeature
       
   472     return false;
       
   473 }
       
   474 
       
   475 /*!
       
   476   Returns a whether the supplied \a filter can be implemented
       
   477   natively by this engine.  If not, the base class implementation
       
   478   will emulate the functionality.
       
   479  */
       
   480 bool CntSymbianSimEngine::isFilterSupported(const QContactFilter& filter) const
       
   481 {
       
   482     if (filter.type() == QContactFilter::ContactDetailFilter) {
       
   483         QContactDetailFilter f(filter);
       
   484         if (f.detailDefinitionName() == QContactPhoneNumber::DefinitionName && 
       
   485             f.detailFieldName() == QContactPhoneNumber::FieldNumber &&
       
   486             f.matchFlags() == QContactFilter::MatchPhoneNumber)
       
   487             return true;
       
   488     }
       
   489     return false;
       
   490 }
       
   491 
       
   492 /*!
       
   493  * Returns the list of data types supported by the manager
       
   494  */
       
   495 QStringList CntSymbianSimEngine::supportedContactTypes() const
       
   496 {
       
   497     // TODO: groups supported by some USIM cards?
       
   498     return QStringList() << QContactType::TypeContact;
       
   499 }
       
   500 
       
   501 void CntSymbianSimEngine::updateDisplayLabel(QContact& contact) const
       
   502 {
       
   503     QContactManager::Error error(QContactManager::NoError);
       
   504     QString label = synthesizedDisplayLabel(contact, &error);
       
   505     if(error == QContactManager::NoError) {
       
   506         setContactDisplayLabel(&contact, label);
       
   507     }
       
   508 }
       
   509 
       
   510 void CntSymbianSimEngine::setReadOnlyAccessConstraint(QContactDetail* detail) const
       
   511 {
       
   512     setDetailAccessConstraints(detail, QContactDetail::ReadOnly); 
       
   513 }
       
   514 
       
   515 
       
   516 /*!
       
   517   Returns true if the supplied contact \a contact matches the supplied filter \a filter.
       
   518  */
       
   519 bool CntSymbianSimEngine::filter(const QContactFilter &filter, const QContact &contact)
       
   520 {
       
   521     // Special handling for phonenumber matching:
       
   522     // Matching is done from the right by using a configurable number of digits.
       
   523     // Default number of digits is 7. So for example if we filter with number
       
   524     // +358505555555 the filter should match to +358505555555 and 0505555555.
       
   525     if (filter.type() == QContactFilter::ContactDetailFilter) 
       
   526     {
       
   527         QContactDetailFilter f(filter);
       
   528         if (f.detailDefinitionName() == QContactPhoneNumber::DefinitionName && 
       
   529             f.detailFieldName() == QContactPhoneNumber::FieldNumber &&
       
   530             f.matchFlags() == QContactFilter::MatchPhoneNumber) 
       
   531         {
       
   532             QString matchNumber = f.value().toString().right(d->m_phoneNumberMatchLen);
       
   533             QList<QContactPhoneNumber> pns = contact.details<QContactPhoneNumber>();
       
   534             foreach (QContactPhoneNumber pn, pns) {
       
   535                 QString number = pn.number().right(d->m_phoneNumberMatchLen);
       
   536                 if (number == matchNumber)
       
   537                     return true;
       
   538             }
       
   539             return false;
       
   540         }
       
   541     }
       
   542     return QContactManagerEngine::testFilter(filter, contact);
       
   543 }
       
   544 
       
   545 /*!
       
   546  * Executes an asynchronous request so that it will appear synchronous. This is
       
   547  * used internally in all synchronous functions. This way we only need to 
       
   548  * implement the matching asynchronous request.
       
   549  * 
       
   550  * \param req Request to be run.
       
   551  * \param qtError Qt error code.
       
   552  * \return true if succesfull, false if unsuccesfull.
       
   553  */
       
   554 bool CntSymbianSimEngine::executeRequest(QContactAbstractRequest *req, QContactManager::Error* qtError) const
       
   555 {
       
   556     *qtError = QContactManager::NoError;
       
   557     
       
   558     // TODO:
       
   559     // Remove this code when threads-branch is merged to master. Then this code
       
   560     // should not be needed because the default implementation at QContactManager
       
   561     // is using the asynchronous requests in a similar manner to implement
       
   562     // the synchronous functions.
       
   563     
       
   564     // Create a copy engine to workaround this functions const qualifier
       
   565     CntSymbianSimEngine engine(*this);
       
   566     
       
   567     // Mimic the way how async requests are normally run
       
   568     if (!engine.startRequest(req)) {
       
   569         *qtError = QContactManager::LockedError;
       
   570     } else {
       
   571         if (!engine.waitForRequestFinished(req, 0)) // no timeout
       
   572             *qtError = QContactManager::UnspecifiedError;
       
   573     }
       
   574     engine.requestDestroyed(req);
       
   575     
       
   576     if (req->error())
       
   577         *qtError = req->error();
       
   578     
       
   579     return (*qtError == QContactManager::NoError);
       
   580 }
       
   581 
       
   582 /*
       
   583  * Get the match length setting used in MatchPhoneNumber type filtering.
       
   584  * \a matchLength Phone number digits to be used in matching (counted from
       
   585  * right).
       
   586  */
       
   587 void CntSymbianSimEngine::getMatchLengthL(int &matchLength)
       
   588 {
       
   589     //Get number of digits used to match
       
   590     CRepository* repository = CRepository::NewL(KCRUidTelConfiguration);
       
   591     CleanupStack::PushL(repository);
       
   592     User::LeaveIfError(repository->Get(KTelMatchDigits, matchLength));
       
   593     CleanupStack::PopAndDestroy(repository);
       
   594 }
       
   595 
       
   596 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
       
   597 {
       
   598     CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error);
       
   599     if(*error != QContactManager::NoError) {
       
   600         delete engine;
       
   601         return 0;
       
   602     }
       
   603     return engine;
       
   604 }
       
   605 
       
   606 QString CntSymbianSimFactory::managerName() const
       
   607 {
       
   608     return CNT_SYMBIANSIM_MANAGER_NAME;
       
   609 }
       
   610 
       
   611 Q_EXPORT_PLUGIN2(qtcontacts_symbiansim, CntSymbianSimFactory);