qtmobility/plugins/contacts/symbiansim/src/cntsymbiansimengine.cpp
changeset 1 2b40d63a9c3d
child 4 90517678cc4f
equal deleted inserted replaced
0:cfcbf08528c4 1:2b40d63a9c3d
       
     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 <qtcontacts.h>
       
    44 #include <mmtsy_names.h>
       
    45 
       
    46 #include "cntsymbiansimtransformerror.h"
       
    47 #include "cntsimstore.h"
       
    48 #include "cntsimcontactfetchrequest.h"
       
    49 #include "cntsimcontactlocalidfetchrequest.h"
       
    50 #include "cntsimcontactsaverequest.h"
       
    51 #include "cntsimcontactremoverequest.h"
       
    52 #include "cntsimdetaildefinitionfetchrequest.h"
       
    53 
       
    54 #ifdef SYMBIANSIM_BACKEND_USE_ETEL_TESTSERVER
       
    55 #include <mpbutil_etel_test_server.h>
       
    56 #else
       
    57 #include <mpbutil.h>
       
    58 #endif
       
    59 
       
    60 #include <QEventLoop>
       
    61 #include <QTimer>
       
    62 
       
    63 
       
    64 
       
    65 CntSymbianSimEngineData::CntSymbianSimEngineData()
       
    66     :m_simStore(0)
       
    67 {
       
    68     
       
    69 }
       
    70 
       
    71 CntSymbianSimEngineData::~CntSymbianSimEngineData()
       
    72 {
       
    73     if (ref == 0) {
       
    74         // Remove all unfinished requests.
       
    75         // If the client has behaved itself then there should be none left.
       
    76         while (m_asyncRequests.size()) {
       
    77             QMap<QContactAbstractRequest *, CntAbstractSimRequest *>::iterator itr = m_asyncRequests.begin();
       
    78             delete itr.value();
       
    79             m_asyncRequests.remove(itr.key());
       
    80             qWarning("Dangling async request!");
       
    81         }        
       
    82     }
       
    83 }
       
    84 
       
    85 CntSymbianSimEngine::CntSymbianSimEngine(const QMap<QString, QString>& parameters, QContactManager::Error& error)
       
    86 {
       
    87     error = QContactManager::NoError;
       
    88 
       
    89     d = new CntSymbianSimEngineData();
       
    90     d->m_simStore = new CntSimStore(this, parameters.value(KParameterKeySimStoreName));
       
    91 
       
    92     if(d->m_simStore->storeName() == KParameterValueSimStoreNameSdn) {
       
    93         // In case of SDN store we need to check if any SDN contacts exist to
       
    94         // determine if the store is supported or not
       
    95         if(d->m_simStore->storeInfo().iUsedEntries == 0)
       
    96             error = QContactManager::NotSupportedError;
       
    97     }    
       
    98 }
       
    99 
       
   100 CntSymbianSimEngine::CntSymbianSimEngine(const CntSymbianSimEngine &other)
       
   101     :d(other.d)
       
   102 {
       
   103     
       
   104 }
       
   105 
       
   106 CntSymbianSimEngine::~CntSymbianSimEngine()
       
   107 {
       
   108 
       
   109 }
       
   110 
       
   111 void CntSymbianSimEngine::deref()
       
   112 {
       
   113     delete this;
       
   114 }
       
   115 
       
   116 QString CntSymbianSimEngine::managerName() const
       
   117 {
       
   118     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 }
       
   132 
       
   133 /*!
       
   134  * 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.
       
   136  */
       
   137 QList<QContactLocalId> CntSymbianSimEngine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error& error) const
       
   138 {
       
   139     QContactLocalIdFetchRequest req;
       
   140     req.setFilter(filter);
       
   141     req.setSorting(sortOrders);
       
   142     executeRequest(&req, error);
       
   143     return req.ids();
       
   144 }
       
   145 
       
   146 QList<QContact> CntSymbianSimEngine::contacts(const QList<QContactSortOrder>& sortOrders, const QStringList& definitionRestrictions, 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 {
       
   157     QContactFetchRequest req;
       
   158     req.setFilter(filter);
       
   159     req.setSorting(sortOrders);
       
   160     req.setDefinitionRestrictions(definitionRestrictions);
       
   161     executeRequest(&req, error);
       
   162     return req.contacts();
       
   163 }
       
   164 
       
   165 /*!
       
   166  * Reads a contact from the Etel store.
       
   167  *
       
   168  * \param contactId The Id of the contact to be retrieved.
       
   169  * \param definitionRestrictions Definition restrictions.
       
   170  * \param error Qt error code.
       
   171  * \return A QContact for the requested QContactLocalId value or 0 if the read
       
   172  *  operation was unsuccessful (e.g. contact not found).
       
   173  */
       
   174 QContact CntSymbianSimEngine::contact(const QContactLocalId& contactId, const QStringList& definitionRestrictions, QContactManager::Error& error) const
       
   175 {
       
   176     QContactFetchRequest req;
       
   177     QContactLocalIdFilter filter;
       
   178     filter.setIds(QList<QContactLocalId>() << contactId);
       
   179     req.setFilter(filter);
       
   180     req.setDefinitionRestrictions(definitionRestrictions);
       
   181     executeRequest(&req, error);
       
   182     if (req.contacts().count() == 0)
       
   183         return QContact();
       
   184     return req.contacts().at(0); 
       
   185 }
       
   186 
       
   187 QString CntSymbianSimEngine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error& error) const
       
   188 {
       
   189     Q_UNUSED(error);
       
   190 
       
   191     QContactName name = contact.detail(QContactName::DefinitionName);
       
   192     if(!name.customLabel().isEmpty()) {
       
   193         return name.customLabel();
       
   194     } else {
       
   195         // TODO: localize unnamed
       
   196         return QString("Unnamed");
       
   197     }
       
   198 }
       
   199 
       
   200 /*!
       
   201  * Saves the contact 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.
       
   203  *
       
   204  * \param contact Contact to be saved.
       
   205  * \param qtError Qt error code.
       
   206  * \return Error status.
       
   207  */
       
   208 bool CntSymbianSimEngine::saveContact(QContact* contact, 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 {
       
   225     if (!contacts) {
       
   226         error = QContactManager::BadArgumentError;
       
   227         return false;
       
   228     }
       
   229     
       
   230     QContactSaveRequest req;
       
   231     req.setContacts(*contacts);
       
   232     executeRequest(&req, error);
       
   233     if (errorMap)
       
   234         *errorMap = req.errorMap();
       
   235     *contacts = req.contacts();
       
   236     return (error == QContactManager::NoError );    
       
   237 }
       
   238 
       
   239 /*!
       
   240  * Removes the specified contact object from the Etel store.
       
   241  *
       
   242  * \param contactId Id of the contact to be removed.
       
   243  * \param qtError Qt error code.
       
   244  * \return Error status.
       
   245  */
       
   246 bool CntSymbianSimEngine::removeContact(const QContactLocalId& contactId, QContactManager::Error& error)
       
   247 {
       
   248     QContactRemoveRequest req;
       
   249     req.setContactIds(QList<QContactLocalId>() << contactId);
       
   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);
       
   262     if (errorMap)
       
   263         *errorMap = req.errorMap();    
       
   264     return (error == QContactManager::NoError);    
       
   265 }
       
   266 
       
   267 /*!
       
   268  * 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
       
   270  */
       
   271 QMap<QString, QContactDetailDefinition> CntSymbianSimEngine::detailDefinitions(const QString& contactType, QContactManager::Error& error) const
       
   272 {
       
   273     if (!supportedContactTypes().contains(contactType)) {
       
   274         // Should never happen
       
   275         error = QContactManager::NotSupportedError;
       
   276         return QMap<QString, QContactDetailDefinition>();
       
   277     }
       
   278 
       
   279     // Get store information
       
   280     RMobilePhoneBookStore::TMobilePhoneBookInfoV5 storeInfo = d->m_simStore->storeInfo();
       
   281 
       
   282     // the map we will eventually return
       
   283     QMap<QString, QContactDetailDefinition> retn;
       
   284 
       
   285     // local variables for reuse
       
   286     QMap<QString, QContactDetailFieldDefinition> fields;
       
   287     QContactDetailFieldDefinition f;
       
   288     QContactDetailDefinition def;
       
   289     QVariantList subTypes;
       
   290 
       
   291     // sync target
       
   292     def.setName(QContactSyncTarget::DefinitionName);
       
   293     fields.clear();
       
   294     f.setDataType(QVariant::String);
       
   295     subTypes.clear();
       
   296     subTypes << QString(QLatin1String(KSimSyncTarget));
       
   297     f.setAllowableValues(subTypes);
       
   298     fields.insert(QContactSyncTarget::FieldSyncTarget, f);
       
   299     def.setFields(fields);
       
   300     def.setUnique(true);
       
   301     retn.insert(def.name(), def);
       
   302 
       
   303     // type
       
   304     def.setName(QContactType::DefinitionName);
       
   305     fields.clear();
       
   306     f.setDataType(QVariant::String);
       
   307     subTypes.clear();
       
   308     // groups are not supported
       
   309     subTypes << QString(QLatin1String(QContactType::TypeContact));
       
   310     f.setAllowableValues(subTypes);
       
   311     fields.insert(QContactType::FieldType, f); // note: NO CONTEXT!!
       
   312     def.setFields(fields);
       
   313     def.setUnique(true);
       
   314     retn.insert(def.name(), def);
       
   315 
       
   316 /* TODO
       
   317     // guid
       
   318     def.setName(QContactGuid::DefinitionName);
       
   319     fields.clear();
       
   320     f.setDataType(QVariant::String);
       
   321     f.setAllowableValues(QVariantList());
       
   322     fields.insert(QContactGuid::FieldGuid, f);
       
   323     f.setDataType(QVariant::StringList);
       
   324     f.setAllowableValues(contexts);
       
   325     fields.insert(QContactDetail::FieldContext, f);
       
   326     def.setFields(fields);
       
   327     def.setUnique(false);
       
   328     def.setAccessConstraint(QContactDetailDefinition::CreateOnly);
       
   329     retn.insert(def.name(), def);
       
   330 */
       
   331 
       
   332     // display label
       
   333     def.setName(QContactDisplayLabel::DefinitionName);
       
   334     fields.clear();
       
   335     f.setDataType(QVariant::String);
       
   336     f.setAllowableValues(QVariantList());
       
   337     fields.insert(QContactDisplayLabel::FieldLabel, f);
       
   338     def.setFields(fields);
       
   339     def.setUnique(true);
       
   340     retn.insert(def.name(), def);
       
   341 
       
   342     // email support needs to be checked run-time, because it is SIM specific
       
   343     if (storeInfo.iMaxEmailAddr > 0) {
       
   344         def.setName(QContactEmailAddress::DefinitionName);
       
   345         fields.clear();
       
   346         f.setDataType(QVariant::String);
       
   347         f.setAllowableValues(QVariantList());
       
   348         fields.insert(QContactEmailAddress::FieldEmailAddress, f);
       
   349         def.setFields(fields);
       
   350         def.setUnique(true);
       
   351         retn.insert(def.name(), def);
       
   352     }
       
   353 
       
   354     // phone number
       
   355     def.setName(QContactPhoneNumber::DefinitionName);
       
   356     fields.clear();
       
   357     f.setDataType(QVariant::String);
       
   358     f.setAllowableValues(QVariantList());
       
   359     fields.insert(QContactPhoneNumber::FieldNumber, f);
       
   360     // TODO: subtypes supported in case a sim contact can have multiple phone numbers?
       
   361     def.setFields(fields);
       
   362     if (storeInfo.iMaxAdditionalNumbers > 0) {
       
   363         // multiple numbers supported
       
   364         def.setUnique(false);
       
   365     } else {
       
   366         // only one phone number allowed
       
   367         def.setUnique(true);
       
   368     }
       
   369     retn.insert(def.name(), def);
       
   370 
       
   371     // nickname support needs to be checked run-time, because it is SIM specific
       
   372     if (storeInfo.iMaxSecondNames > 0) {
       
   373         def.setName(QContactNickname::DefinitionName);
       
   374         fields.clear();
       
   375         f.setDataType(QVariant::String);
       
   376         f.setAllowableValues(QVariantList());
       
   377         fields.insert(QContactNickname::FieldNickname, f);
       
   378         def.setFields(fields);
       
   379         def.setUnique(true);
       
   380         retn.insert(def.name(), def);
       
   381     }
       
   382 
       
   383     // name
       
   384     def.setName(QContactName::DefinitionName);
       
   385     fields.clear();
       
   386     f.setDataType(QVariant::String);
       
   387     f.setAllowableValues(QVariantList());
       
   388     fields.insert(QContactName::FieldCustomLabel, f);
       
   389     def.setFields(fields);
       
   390     def.setUnique(true);
       
   391     retn.insert(def.name(), def);
       
   392 
       
   393     return retn;
       
   394 }
       
   395 
       
   396 void CntSymbianSimEngine::requestDestroyed(QContactAbstractRequest* req)
       
   397 {
       
   398     if (d->m_asyncRequests.contains(req)) {
       
   399         delete d->m_asyncRequests.take(req); 
       
   400     }
       
   401 }
       
   402 
       
   403 bool CntSymbianSimEngine::startRequest(QContactAbstractRequest* req)
       
   404 {
       
   405     // Don't allow two async requests to be active at the same time.
       
   406     // The RMobilePhoneBookStore cannot handle it.
       
   407     foreach (QContactAbstractRequest* r, d->m_asyncRequests.keys()) {
       
   408         if (r->isActive()) {
       
   409             // TODO: Should we set the error for the request also?
       
   410             return false;
       
   411         }
       
   412     }
       
   413     
       
   414     // Check for existing request and start again
       
   415     if (d->m_asyncRequests.contains(req)) {
       
   416         return d->m_asyncRequests.value(req)->start();
       
   417     }
       
   418     
       
   419     // Existing request not found. Create a new one.
       
   420     CntAbstractSimRequest* simReq = 0;
       
   421     switch (req->type()) 
       
   422     {
       
   423         case QContactAbstractRequest::ContactFetchRequest:
       
   424         {
       
   425             QContactFetchRequest* r = static_cast<QContactFetchRequest*>(req);
       
   426             simReq = new CntSimContactFetchRequest(this, r);
       
   427         }
       
   428         break;
       
   429 
       
   430         case QContactAbstractRequest::ContactLocalIdFetchRequest:
       
   431         {
       
   432             QContactLocalIdFetchRequest* r = static_cast<QContactLocalIdFetchRequest*>(req);
       
   433             simReq = new CntSimContactLocalIdFetchRequest(this, r);
       
   434         }
       
   435         break;
       
   436 
       
   437         case QContactAbstractRequest::ContactSaveRequest:
       
   438         {
       
   439             QContactSaveRequest* r = static_cast<QContactSaveRequest*>(req);
       
   440             simReq = new CntSimContactSaveRequest(this, r);
       
   441         }
       
   442         break;
       
   443 
       
   444         case QContactAbstractRequest::ContactRemoveRequest:
       
   445         {
       
   446             QContactRemoveRequest* r = static_cast<QContactRemoveRequest*>(req);
       
   447             simReq = new CntSimContactRemoveRequest(this, r);
       
   448         }
       
   449         break;
       
   450 
       
   451         case QContactAbstractRequest::DetailDefinitionFetchRequest:
       
   452         {
       
   453             QContactDetailDefinitionFetchRequest* r = static_cast<QContactDetailDefinitionFetchRequest*>(req);
       
   454             simReq = new CntSimDetailDefinitionFetchRequest(this, r);
       
   455         }
       
   456         break;
       
   457 
       
   458         case QContactAbstractRequest::DetailDefinitionSaveRequest:
       
   459         case QContactAbstractRequest::DetailDefinitionRemoveRequest:
       
   460         case QContactAbstractRequest::RelationshipFetchRequest:
       
   461         case QContactAbstractRequest::RelationshipSaveRequest:
       
   462         case QContactAbstractRequest::RelationshipRemoveRequest:
       
   463         // fall through.
       
   464         default: // unknown request type.
       
   465         break;
       
   466     }
       
   467     
       
   468     if (simReq) {
       
   469         d->m_asyncRequests.insert(req, simReq);
       
   470         return simReq->start();
       
   471     }
       
   472         
       
   473     return false;
       
   474 }
       
   475 
       
   476 bool CntSymbianSimEngine::cancelRequest(QContactAbstractRequest* req)
       
   477 {
       
   478     if (d->m_asyncRequests.contains(req))
       
   479         return d->m_asyncRequests.value(req)->cancel();
       
   480     return false;
       
   481 }
       
   482 
       
   483 bool CntSymbianSimEngine::waitForRequestFinished(QContactAbstractRequest* req, int msecs)
       
   484 {
       
   485     if (!d->m_asyncRequests.contains(req)) 
       
   486         return false;
       
   487     
       
   488     if (req->state() != QContactAbstractRequest::ActiveState)
       
   489         return false;
       
   490     
       
   491     QEventLoop *loop = new QEventLoop(this);
       
   492     QObject::connect(req, SIGNAL(resultsAvailable()), loop, SLOT(quit()));
       
   493 
       
   494     // NOTE: zero means wait forever
       
   495     if (msecs > 0)
       
   496         QTimer::singleShot(msecs, loop, SLOT(quit()));
       
   497 
       
   498     loop->exec();
       
   499     loop->disconnect();
       
   500     loop->deleteLater();
       
   501 
       
   502     return (req->state() == QContactAbstractRequest::FinishedState);
       
   503 }
       
   504 
       
   505 /*!
       
   506  * Returns true if the given feature \a feature is supported by the manager,
       
   507  * for the specified type of contact \a contactType
       
   508  */
       
   509 bool CntSymbianSimEngine::hasFeature(QContactManager::ManagerFeature feature, const QString& contactType) const
       
   510 {
       
   511     Q_UNUSED(feature);
       
   512     Q_UNUSED(contactType);
       
   513     // We don't support anything in the ManagerFeature
       
   514     return false;
       
   515 }
       
   516 
       
   517 /*!
       
   518  * Returns the list of data types supported by the manager
       
   519  */
       
   520 QStringList CntSymbianSimEngine::supportedContactTypes() const
       
   521 {
       
   522     // TODO: groups supported by some USIM cards?
       
   523     return QStringList() << QContactType::TypeContact;
       
   524 }
       
   525 
       
   526 void CntSymbianSimEngine::updateDisplayLabel(QContact& contact) const
       
   527 {
       
   528     QContactManager::Error error(QContactManager::NoError);
       
   529     QString label = synthesizedDisplayLabel(contact, error);
       
   530     if(error == QContactManager::NoError) {
       
   531         contact = setContactDisplayLabel(label, contact);
       
   532     }
       
   533 }
       
   534 
       
   535 /*!
       
   536  * 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 
       
   538  * implement the matching asynchronous request.
       
   539  * 
       
   540  * \param req Request to be run.
       
   541  * \param qtError Qt error code.
       
   542  * \return true if succesfull, false if unsuccesfull.
       
   543  */
       
   544 bool CntSymbianSimEngine::executeRequest(QContactAbstractRequest *req, QContactManager::Error& qtError) const
       
   545 {
       
   546     // TODO:
       
   547     // Remove this code when threads-branch is merged to master. Then this code
       
   548     // should not be needed because the default implementation at QContactManager
       
   549     // is using the asynchronous requests in a similar manner to implement
       
   550     // the synchronous functions.
       
   551     
       
   552     // Create a copy engine to workaround this functions const qualifier
       
   553     CntSymbianSimEngine engine(*this);
       
   554     
       
   555     // Mimic the way how async requests are normally run
       
   556     if (engine.startRequest(req))
       
   557         engine.waitForRequestFinished(req, 0); // should we have a timeout?
       
   558     engine.requestDestroyed(req);
       
   559     
       
   560     qtError = req->error();
       
   561     return (qtError == QContactManager::NoError);
       
   562 }
       
   563 
       
   564 QContactManagerEngine* CntSymbianSimFactory::engine(const QMap<QString, QString>& parameters, QContactManager::Error& error)
       
   565 {
       
   566     CntSymbianSimEngine *engine = new CntSymbianSimEngine(parameters, error);
       
   567     if(error != QContactManager::NoError) {
       
   568         delete engine;
       
   569         return 0;
       
   570     }
       
   571     return engine;
       
   572 }
       
   573 
       
   574 QString CntSymbianSimFactory::managerName() const
       
   575 {
       
   576     return CNT_SYMBIANSIM_MANAGER_NAME;
       
   577 }
       
   578 
       
   579 Q_EXPORT_PLUGIN2(mobapicontactspluginsymbiansim, CntSymbianSimFactory);