phonebookui/phonebookservices/src/cntservices.cpp
branchRCL_3
changeset 62 5b6f26637ad3
equal deleted inserted replaced
58:d4f567ce2e7c 62:5b6f26637ad3
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description:
       
    15  *
       
    16  */
       
    17 
       
    18 #include "cntservices.h"
       
    19 #include "cntglobal.h"
       
    20 #include "cntdebug.h"
       
    21 #include <cntabstractviewmanager.h>
       
    22 #include "cntserviceviewmanager.h"
       
    23 #include "cntimageutility.h"
       
    24 #include "cntserviceviewparams.h"
       
    25 #include <cntservicescontact.h>
       
    26 
       
    27 #include <hbview.h>
       
    28 #include <hblistview.h>
       
    29 #include <qversitreader.h>
       
    30 #include <qversitcontactimporter.h>
       
    31 #include <qversitdocument.h>
       
    32 #include <xqserviceprovider.h>
       
    33 #include <cntabstractengine.h>
       
    34 
       
    35 #include <QApplication>
       
    36 #include <QPixmap>
       
    37 #include <QFile>
       
    38 #include <QUrl>
       
    39 #include <QTextCodec>
       
    40 
       
    41 const int Latin1CharSetMIB = 4;
       
    42 
       
    43 CntServices::CntServices() :
       
    44 mViewManager(NULL),
       
    45 mCurrentProvider(NULL),
       
    46 mIsQuittable(true)
       
    47 {
       
    48     CNT_ENTRY
       
    49 
       
    50     // Definition names supported in symbian back-end
       
    51     m_definitionNames << QContactName::DefinitionName;
       
    52     m_definitionNames << QContactNickname::DefinitionName;
       
    53     m_definitionNames << QContactPhoneNumber::DefinitionName;
       
    54     m_definitionNames << QContactEmailAddress::DefinitionName;
       
    55     m_definitionNames << QContactAddress::DefinitionName;
       
    56     m_definitionNames << QContactUrl::DefinitionName;
       
    57     m_definitionNames << QContactBirthday::DefinitionName;
       
    58     m_definitionNames << QContactOrganization::DefinitionName;
       
    59     m_definitionNames << QContactSyncTarget::DefinitionName;
       
    60     m_definitionNames << QContactNote::DefinitionName;
       
    61     m_definitionNames << QContactFamily::DefinitionName;
       
    62     m_definitionNames << QContactAvatar::DefinitionName;
       
    63     m_definitionNames << QContactAnniversary::DefinitionName;
       
    64     m_definitionNames << QContactGeoLocation::DefinitionName;
       
    65     m_definitionNames << QContactGender::DefinitionName;
       
    66     m_definitionNames << QContactOnlineAccount::DefinitionName;
       
    67     
       
    68     CNT_EXIT
       
    69 }
       
    70 
       
    71 
       
    72 CntServices::~CntServices()
       
    73 {
       
    74     CNT_LOG
       
    75 }
       
    76 
       
    77 
       
    78 void CntServices::setEngine( CntAbstractEngine& aEngine )
       
    79 {
       
    80     CNT_LOG
       
    81     mEngine = &aEngine;
       
    82     mViewManager = &mEngine->viewManager();
       
    83     CntServiceViewManager* srvMng = static_cast<CntServiceViewManager*>(mViewManager);
       
    84     connect(srvMng, SIGNAL(applicationClosed()), this, SLOT(terminateService()));
       
    85 }
       
    86 /*
       
    87 void CntServices::setViewManager( CntAbstractViewManager& aViewManager )
       
    88 {
       
    89     CNT_LOG
       
    90     mViewManager = &aViewManager;
       
    91     CntServiceViewManager* srvMng = static_cast<CntServiceViewManager*>(mViewManager);
       
    92     connect(srvMng, SIGNAL(applicationClosed()), this, SLOT(terminateService()));
       
    93 }
       
    94 */
       
    95 
       
    96 void CntServices::singleFetch(
       
    97     const QString &title, const QString &action,
       
    98     CntAbstractServiceProvider& aServiceProvider )
       
    99 {
       
   100     CNT_ENTRY
       
   101     mCurrentProvider = &aServiceProvider;
       
   102 
       
   103     CntViewParameters params;
       
   104     params.insert(EViewId, serviceContactFetchView);
       
   105     params.insert(ESelectedAction, action);
       
   106     params.insert(KCntServiceViewParamTitle, title);
       
   107     // SINGLE fetch
       
   108     params.insert(ESelectionMode, HbAbstractItemView::SingleSelection);
       
   109 
       
   110     mViewManager->changeView(params);
       
   111     CNT_EXIT
       
   112 }
       
   113 
       
   114 
       
   115 void CntServices::multiFetch(
       
   116     const QString &title, const QString &action,
       
   117     CntAbstractServiceProvider& aServiceProvider )
       
   118 {
       
   119     CNT_ENTRY
       
   120     mCurrentProvider = &aServiceProvider;
       
   121 
       
   122     CntViewParameters params;
       
   123     params.insert(EViewId, serviceContactFetchView);
       
   124     params.insert(ESelectedAction, action);
       
   125     params.insert(KCntServiceViewParamTitle, title);
       
   126     // MULTI fetch
       
   127     params.insert(ESelectionMode, HbAbstractItemView::MultiSelection);
       
   128     mViewManager->changeView(params);
       
   129     CNT_EXIT
       
   130 }
       
   131 
       
   132 void CntServices::editCreateNew(const QString &definitionName, const QString &value,
       
   133     CntAbstractServiceProvider& aServiceProvider, bool defaultForOnlineAccountIsImpp )
       
   134 {
       
   135     CNT_ENTRY
       
   136     editCreateNew( definitionName, value, QString(), aServiceProvider, defaultForOnlineAccountIsImpp);
       
   137     CNT_EXIT
       
   138 }
       
   139 
       
   140 void CntServices::editCreateNew(const QString &definitionName, const QString &value, const QString& subType,
       
   141     CntAbstractServiceProvider& aServiceProvider, bool defaultForOnlineAccountIsImpp )
       
   142 {
       
   143     CNT_ENTRY
       
   144     mCurrentProvider = &aServiceProvider;
       
   145 
       
   146     QContact contact;
       
   147     
       
   148     if (definitionName == QContactPhoneNumber::DefinitionName)
       
   149     {
       
   150         QContactPhoneNumber phoneNumber;
       
   151         phoneNumber.setNumber(value);
       
   152         if (!subType.isEmpty())
       
   153         {
       
   154             phoneNumber.setSubTypes(subType);
       
   155         }
       
   156         else
       
   157         {
       
   158             phoneNumber.setSubTypes(QContactPhoneNumber::SubTypeMobile); // Mobile is the default if subtype is not given.
       
   159         }
       
   160          contact.saveDetail(&phoneNumber);
       
   161     }
       
   162     else if (definitionName == QContactEmailAddress::DefinitionName)
       
   163     {
       
   164         QContactEmailAddress email;
       
   165         email.setEmailAddress(value);
       
   166         // Email addresses can't have subtypes.
       
   167         contact.saveDetail(&email);
       
   168     }
       
   169     else if (definitionName == QContactOnlineAccount::DefinitionName)
       
   170     {
       
   171         QContactOnlineAccount account;
       
   172         fillOnlineAccount( account, value, subType, defaultForOnlineAccountIsImpp);
       
   173         contact.saveDetail(&account);
       
   174     }    
       
   175 
       
   176     // Launch editor now
       
   177     CntViewParameters params;
       
   178     params.insert(EViewId, serviceEditView);
       
   179     QVariant var;
       
   180     var.setValue(contact);
       
   181     params.insert(ESelectedContact, var);
       
   182     mViewManager->changeView(params);
       
   183     CNT_EXIT
       
   184 }
       
   185 
       
   186 
       
   187 void CntServices::editCreateNewFromVCard(const QString &fileName,
       
   188     CntAbstractServiceProvider& aServiceProvider )
       
   189 {
       
   190     CNT_ENTRY
       
   191     mCurrentProvider = &aServiceProvider;
       
   192 
       
   193     CntImageUtility imageUtility;
       
   194     QContact contact;
       
   195     QVersitReader reader;
       
   196     QFile inputFile(fileName);
       
   197     if (!inputFile.open(QIODevice::ReadOnly))
       
   198         return;
       
   199     
       
   200     // Versit parser default codec is UTF-8
       
   201     // Check if decoding text to unicode is possible, else use Latin-1 text codec
       
   202     QByteArray ba = inputFile.readAll();
       
   203     if(!ba.isEmpty())
       
   204         {
       
   205         QTextCodec *c = QTextCodec::codecForUtfText(ba);
       
   206         // Text codec returned is Latin-1, set default to Latin-1
       
   207         if(c->mibEnum()==Latin1CharSetMIB)
       
   208             reader.setDefaultCodec(QTextCodec::codecForName("ISO 8859-1"));
       
   209         }
       
   210     inputFile.close();
       
   211     
       
   212     QFile vCardFile(fileName);
       
   213     if (!vCardFile.open(QIODevice::ReadOnly))
       
   214         return;
       
   215     reader.setDevice(&vCardFile);
       
   216     reader.startReading();
       
   217     reader.waitForFinished();
       
   218     // Use the resulting document(s)...
       
   219     QVersitContactImporter importer;
       
   220     QList<QVersitDocument> versitDocuments = reader.results();
       
   221     if(versitDocuments.count() > 0 
       
   222        && importer.importDocuments(versitDocuments))
       
   223         {
       
   224         QList<QContact> contacts = importer.contacts();
       
   225         if(contacts.count() > 0)
       
   226             contact = contacts.first();
       
   227         }
       
   228     vCardFile.close();
       
   229     
       
   230     // Save thumbnail images
       
   231     QList<QContactThumbnail> details = contact.details<QContactThumbnail>();
       
   232     for (int i = 0;i < details.count();i++)
       
   233         {
       
   234         if (!details.at(i).thumbnail().isNull())
       
   235             {
       
   236             QString imagepath;
       
   237             QPixmap pixmap = QPixmap::fromImage(details.at(i).thumbnail());
       
   238             if(imageUtility.createImage(pixmap,imagepath))
       
   239                 {
       
   240                 // Update contact detail
       
   241                 QContactAvatar detail=details.at(i);
       
   242                 detail.setImageUrl(imagepath);
       
   243                 contact.saveDetail(&detail);
       
   244                 }
       
   245             }
       
   246         }
       
   247     
       
   248     removeNotSupportedDetails(contact);
       
   249     removeNotSupportedFields(contact);
       
   250 
       
   251     // Launch editor now
       
   252     CntViewParameters params;
       
   253     params.insert(EViewId, serviceEditView);
       
   254     QVariant var;
       
   255     var.setValue(contact);
       
   256     params.insert(ESelectedContact, var);
       
   257     mViewManager->changeView(params);
       
   258     CNT_EXIT
       
   259 }
       
   260 
       
   261 void CntServices::editUpdateExisting(const QString &definitionName, const QString &value,
       
   262     CntAbstractServiceProvider& aServiceProvider, bool defaultForOnlineAccountIsImpp )
       
   263 {
       
   264     CNT_ENTRY
       
   265     editUpdateExisting( definitionName, value, QString(), aServiceProvider, defaultForOnlineAccountIsImpp );
       
   266     CNT_EXIT
       
   267 }
       
   268 
       
   269 void CntServices::editUpdateExisting(const QString &definitionName, const QString &value, const QString& subType,
       
   270     CntAbstractServiceProvider& aServiceProvider, bool defaultForOnlineAccountIsImpp )
       
   271 {
       
   272     CNT_ENTRY
       
   273     mCurrentProvider = &aServiceProvider;
       
   274 
       
   275     QContactDetail detail;
       
   276     
       
   277     if (definitionName == QContactPhoneNumber::DefinitionName)
       
   278     {
       
   279         QContactPhoneNumber phoneNumber;
       
   280         phoneNumber.setNumber(value);
       
   281         if (!subType.isEmpty())
       
   282         {        
       
   283             phoneNumber.setSubTypes(subType);
       
   284         }
       
   285         else
       
   286         {
       
   287             phoneNumber.setSubTypes(QContactPhoneNumber::SubTypeMobile);    
       
   288         }
       
   289         detail = phoneNumber;
       
   290     }
       
   291     else if (definitionName == QContactEmailAddress::DefinitionName)
       
   292     {
       
   293         QContactEmailAddress email;
       
   294         email.setEmailAddress(value);
       
   295         // Email addresses can't have subtypes.
       
   296         detail = email;
       
   297     }
       
   298     else if (definitionName == QContactOnlineAccount::DefinitionName)
       
   299     {
       
   300         QContactOnlineAccount account;
       
   301         fillOnlineAccount( account, value, subType, defaultForOnlineAccountIsImpp);
       
   302         detail = account;
       
   303     }
       
   304 
       
   305     CntViewParameters params;
       
   306     params.insert(EViewId, serviceContactSelectionView);
       
   307     QVariant var;
       
   308     var.setValue(detail);
       
   309     params.insert(ESelectedDetail, var);
       
   310     mViewManager->changeView(params);
       
   311     CNT_EXIT
       
   312 }
       
   313 
       
   314 void CntServices::editExisting(int contactId,
       
   315 CntAbstractServiceProvider& aServiceProvider)
       
   316 {
       
   317     CNT_ENTRY
       
   318     mCurrentProvider = &aServiceProvider;
       
   319 
       
   320     // Give parameters for launching editor.
       
   321     CntViewParameters params;
       
   322     params.insert(EViewId, serviceEditView);
       
   323 
       
   324     QContact contact = contactManager()->contact(contactId);
       
   325     QVariant varContact;
       
   326     varContact.setValue(contact);
       
   327     params.insert(ESelectedContact, varContact);
       
   328     mViewManager->changeView(params);
       
   329     CNT_EXIT
       
   330 }
       
   331 
       
   332 
       
   333 void CntServices::launchContactCard(int aContactId,
       
   334     CntAbstractServiceProvider& aServiceProvider )
       
   335 {
       
   336     CNT_ENTRY
       
   337     mCurrentProvider = &aServiceProvider;
       
   338 
       
   339     QContact contact = contactManager()->contact(aContactId);
       
   340 
       
   341     // Launch Contact Card view
       
   342     CntViewParameters params;
       
   343     params.insert(EViewId, serviceContactCardView);
       
   344     QVariant var;
       
   345     var.setValue(contact);
       
   346     params.insert(ESelectedContact, var);
       
   347     mViewManager->changeView( params );
       
   348     CNT_EXIT
       
   349 }
       
   350 
       
   351 
       
   352 void CntServices::launchTemporaryContactCard(const QString &definitionName, const QString &value,
       
   353     CntAbstractServiceProvider& aServiceProvider )
       
   354 {
       
   355     CNT_ENTRY
       
   356     mCurrentProvider = &aServiceProvider;
       
   357 
       
   358     QContact contact;
       
   359     QContactDetail detail;
       
   360     
       
   361     QContactName name;
       
   362     name.setFirstName(hbTrId("txt_phob_list_unknown"));
       
   363     contact.saveDetail(&name);
       
   364     
       
   365     if (definitionName == QContactPhoneNumber::DefinitionName)
       
   366     {
       
   367         QContactPhoneNumber phoneNumber;
       
   368         phoneNumber.setNumber(value);
       
   369         phoneNumber.setSubTypes(QContactPhoneNumber::SubTypeMobile);
       
   370         contact.saveDetail(&phoneNumber);
       
   371         detail = phoneNumber;
       
   372     }
       
   373     else if (definitionName == QContactEmailAddress::DefinitionName)
       
   374     {
       
   375         QContactEmailAddress email;
       
   376         email.setEmailAddress(value);
       
   377         contact.saveDetail(&email);
       
   378         detail = email;
       
   379     }
       
   380     else if (definitionName == QContactOnlineAccount::DefinitionName)
       
   381     {
       
   382         QContactOnlineAccount account;
       
   383         account.setAccountUri(value);
       
   384         account.setSubTypes(QContactOnlineAccount::SubTypeSipVoip);
       
   385         contact.saveDetail(&account);
       
   386         detail = account;
       
   387     }
       
   388 
       
   389     // Launch the view
       
   390     CntViewParameters params;
       
   391     params.insert(EViewId, serviceAssignContactCardView);
       
   392     QVariant var;
       
   393     var.setValue(contact);
       
   394     params.insert(ESelectedContact, var);
       
   395     QVariant varDetail;
       
   396     varDetail.setValue(detail);
       
   397     params.insert(ESelectedDetail, varDetail);
       
   398     mViewManager->changeView(params);
       
   399     CNT_EXIT
       
   400 }
       
   401 
       
   402 void CntServices::launchGroupMemberView(int aContactId,
       
   403     CntAbstractServiceProvider& aServiceProvider )
       
   404 {
       
   405     CNT_ENTRY
       
   406     mCurrentProvider = &aServiceProvider;
       
   407 
       
   408     QContact contact = contactManager()->contact(aContactId);
       
   409 
       
   410     // Launch Group member view
       
   411     CntViewParameters params;
       
   412     params.insert(EViewId, serviceGroupMemberView);
       
   413     QVariant var;
       
   414     var.setValue(contact);
       
   415     params.insert(ESelectedGroupContact, var);
       
   416     mViewManager->changeView( params );
       
   417     CNT_EXIT
       
   418 }
       
   419 
       
   420 void CntServices::setQuittable(bool quittable)
       
   421 {
       
   422     mIsQuittable = quittable;
       
   423 }
       
   424 
       
   425 void CntServices::quitApp()
       
   426 {
       
   427     CNT_ENTRY
       
   428    
       
   429     // Only embedded applications should be exited once a client
       
   430     // disconnects. At the moments QtHighWay has unresolved issues
       
   431     // when closing non-embedded applications. Error ou1cimx1#472852
       
   432     // has more info
       
   433     if ( mIsQuittable ) 
       
   434     {
       
   435        qApp->quit();
       
   436     }   
       
   437     CNT_EXIT
       
   438 }
       
   439 
       
   440 void CntServices::removeNotSupportedDetails(QContact& contact)
       
   441 {
       
   442     CNT_ENTRY
       
   443     // Check definition map, remove details not supported
       
   444     for (int i=0; i < contact.details().count(); i++)
       
   445     {
       
   446         if (!m_definitionNames.contains(contact.details().at(i).definitionName()))
       
   447         {
       
   448             QContactDetail detail= contact.details().at(i);
       
   449             contact.removeDetail(&detail);
       
   450         }
       
   451     }
       
   452     CNT_EXIT
       
   453 }
       
   454 
       
   455 void CntServices::removeNotSupportedFields(QContact& contact)
       
   456 {
       
   457     CNT_ENTRY
       
   458     QList<QContactDetail>   removeList;
       
   459     
       
   460     // Not all fields are supported in symbian back-end
       
   461     // Remove not supported fields
       
   462     for (int i=0; i < contact.details().count(); i++)
       
   463     {
       
   464         QContactDetail detail = contact.details().at(i);
       
   465         if(detail.definitionName() == QContactAddress::DefinitionName)
       
   466         {
       
   467             QContactAddress addrDetail = static_cast<QContactAddress>(detail);
       
   468             
       
   469             // Sub-types not supported
       
   470             if(detail.removeValue(QContactAddress::FieldSubTypes))
       
   471                 contact.saveDetail(&detail);
       
   472         }
       
   473         else if(detail.definitionName() == QContactAnniversary::DefinitionName)
       
   474         {
       
   475             QContactAnniversary annivDetail = static_cast<QContactAnniversary>(detail);
       
   476             
       
   477             // Sub-types not supported
       
   478             if(detail.removeValue(QContactAnniversary::FieldSubType))
       
   479                 contact.saveDetail(&detail);
       
   480             
       
   481             // Context not supported
       
   482             if(detail.removeValue(QContactDetail::FieldContext))
       
   483                 contact.saveDetail(&detail);
       
   484         }
       
   485         else if(detail.definitionName() == QContactPhoneNumber::DefinitionName)
       
   486         {
       
   487             QContactPhoneNumber phoneDetail = static_cast<QContactPhoneNumber>(detail);
       
   488             
       
   489             if(phoneDetail.subTypes().size() > 0 )
       
   490             {
       
   491                 // Sub-types not supported
       
   492                 if(phoneDetail.subTypes().contains(QContactPhoneNumber::SubTypeVoice)
       
   493                    || phoneDetail.subTypes().contains(QContactPhoneNumber::SubTypeMessagingCapable))
       
   494                 {
       
   495                     // Default to subtype mobile
       
   496                     QStringList l;
       
   497                     l << QLatin1String(QContactPhoneNumber::SubTypeMobile);
       
   498                     detail.setValue(QContactPhoneNumber::FieldSubTypes, l);
       
   499                     contact.saveDetail(&detail);
       
   500                 }
       
   501             }
       
   502         }
       
   503         else if(detail.definitionName() == QContactUrl::DefinitionName)
       
   504         {
       
   505             QContactUrl urlDetail = static_cast<QContactUrl>(detail);
       
   506             
       
   507             QString stype=QContactUrl::SubTypeHomePage;
       
   508             if(urlDetail.subType().compare(stype) != 0)
       
   509             {
       
   510                 detail.removeValue(QContactUrl::FieldSubType);
       
   511                 contact.saveDetail(&detail);
       
   512             }
       
   513         }
       
   514     }
       
   515     CNT_EXIT
       
   516 }
       
   517 
       
   518 void CntServices::fillOnlineAccount( QContactOnlineAccount& account, const QString& value,
       
   519     const QString& subType, bool defaultForOnlineAccountIsImpp )
       
   520     {
       
   521         // The value should normally consist of two parts:
       
   522         //    <service provider>:<user ID>
       
   523         // for eg. "serviceprovider:jack@serviceprovider.com"
       
   524         QStringList accountDetails = value.split(":");
       
   525         if (accountDetails.count() == 1)
       
   526         {
       
   527             // For some reason it only had one part, so we're assuming it's the user ID.
       
   528             account.setAccountUri(accountDetails.at(0));
       
   529         }
       
   530         else if (accountDetails.count() >= 2)
       
   531         {
       
   532             account.setServiceProvider(accountDetails.at(0));        
       
   533             account.setAccountUri(accountDetails.at(1)); // the user ID
       
   534         }
       
   535 
       
   536         if (!subType.isEmpty())
       
   537         {        
       
   538             account.setSubTypes(subType);
       
   539         }
       
   540         else
       
   541         {
       
   542             if (defaultForOnlineAccountIsImpp)
       
   543             {
       
   544                 account.setSubTypes( QContactOnlineAccount::SubTypeImpp );
       
   545             }
       
   546             else
       
   547             {
       
   548                 account.setSubTypes( QContactOnlineAccount::SubTypeSipVoip );
       
   549             }
       
   550         }
       
   551     }
       
   552 
       
   553 // This method is inherited from CntAbstractServiceProvider
       
   554 void CntServices::CompleteServiceAndCloseApp(const QVariant& retValue)
       
   555 {
       
   556     CNT_ENTRY
       
   557     if (  mCurrentProvider )
       
   558     {
       
   559         mCurrentProvider->CompleteServiceAndCloseApp( retValue );
       
   560     }
       
   561     CNT_EXIT
       
   562 }
       
   563 
       
   564 // This method is inherited from CntAbstractServiceProvider
       
   565 void CntServices::overrideReturnValue(const QVariant& retValue)
       
   566 {
       
   567     CNT_ENTRY
       
   568     if (  mCurrentProvider )
       
   569     {
       
   570         mCurrentProvider->overrideReturnValue( retValue );
       
   571     }
       
   572     CNT_EXIT
       
   573 }
       
   574 
       
   575 // This method is inherited from CntAbstractServiceProvider
       
   576 bool CntServices::allowSubViewsExit()
       
   577 {
       
   578     bool allow = true;
       
   579     if (  mCurrentProvider )
       
   580     {
       
   581         allow = mCurrentProvider->allowSubViewsExit();
       
   582     }
       
   583     
       
   584     return allow;
       
   585 }
       
   586 
       
   587 void CntServices::terminateService()
       
   588 {
       
   589     CNT_ENTRY
       
   590     if (  mCurrentProvider )
       
   591     {
       
   592         // Complete the service with KCntServicesTerminated return value
       
   593         QVariant var(KCntServicesTerminated);
       
   594         mCurrentProvider->CompleteServiceAndCloseApp( var );
       
   595     }
       
   596     CNT_EXIT
       
   597 }
       
   598 
       
   599 QContactManager* CntServices::contactManager()
       
   600 {
       
   601     if ( mEngine )
       
   602         return &mEngine->contactManager(SYMBIAN_BACKEND);
       
   603     return NULL;
       
   604 }
       
   605 
       
   606 Q_IMPLEMENT_USER_METATYPE(CntServicesContact)
       
   607 Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(CntServicesContactList)
       
   608