phonebookui/Phonebook/Engine/src/CPbkContactEngine.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2002 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 *       Represents a connection to the Phonebook contact database
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CPbkContactEngine.h"
       
    22 #include <cntdb.h>       // CContactDatabase class
       
    23 #include <cntitem.h>     // ContactItem class
       
    24 #include <barsc.h>       // RResourceFile
       
    25 #include <barsread.h>    // TResourceReader
       
    26 #include <shareddataclient.h>    // RSharedDataClient
       
    27 #include <featmgr.h>	// Feature manager
       
    28 #include <ecom/ecom.h>
       
    29 #include <PbkUID.h>
       
    30 #include <bautils.h>    // BaflUtils
       
    31 
       
    32 #include <PbkEng.rsg>    // Engine resources
       
    33 #include "CPbkFieldsInfo.h"
       
    34 #include "CPbkFieldInfo.h"
       
    35 #include "CPbkContactItem.h"
       
    36 #include "CPbkContactIter.h"
       
    37 #include "MPbkContactDbObserver.h"
       
    38 #include "CPbkContactChangeNotifier.h"
       
    39 #include "CPbkIdleFinder.h"
       
    40 #include <PbkEngUtils.h>
       
    41 #include <CPbkConstants.h>
       
    42 #include "CPbkEngineExtension.h"
       
    43 
       
    44 #include "CContactDbConnection.h"
       
    45 #include <MPbkContactNameFormat.h>
       
    46 #include "CPbkDeleteContacts.h"
       
    47 #include "CPbkIdleProcessRunner.h"
       
    48 #include "PbkDataCaging.hrh"
       
    49 #include "cpbkenginelocalstorage.h"
       
    50 
       
    51 #include <PbkDebug.h>  // Phonebook debugging support
       
    52 #include "PbkProfiling.h"
       
    53 
       
    54 /// Unnamed namespace for local definitons
       
    55 namespace {
       
    56 
       
    57 // LOCAL CONSTANTS AND MACROS
       
    58 
       
    59 _LIT(KCntModelResFileName, "cntmodel.rsc");
       
    60 _LIT(KCntModelResFileDrive, "z:");
       
    61 _LIT8(KSettingsVisibleCompareStr, "*1*");
       
    62 
       
    63 enum TPanicCode
       
    64     {
       
    65     EPanicContactNotGroup = 1,
       
    66     EPanicPreCond_AddObserverL,
       
    67     EPanicPostCond_AddObserverL,
       
    68     EPanicPreCond_RemoveObserver,
       
    69     EPanicPostCond_RemoveObserver,
       
    70     EPanicObserverNotFoundInRemove,
       
    71     EPanicPreCond_ConstructL,
       
    72     EPanicPreCond_UnnamedTitle,
       
    73     EPanicPreCond_CreateEmptyContactL,
       
    74     EPanicFieldInfoNotFound,
       
    75     EPanicLogic_ConstructL,
       
    76     EPanicSetTlsFails,
       
    77     EPanicSINDHandlerNotFound // obsolete
       
    78     };
       
    79 
       
    80 
       
    81 // ==================== LOCAL FUNCTIONS ====================
       
    82 
       
    83 void Panic(TPanicCode aReason)
       
    84     {
       
    85     _LIT(KPanicText, "CPbkContactEngine");
       
    86     User::Panic(KPanicText, aReason);
       
    87     }
       
    88 
       
    89 /**
       
    90  * Returns true if aError is a fatal database open error.
       
    91  */
       
    92 TBool IsFatalDbOpenError(TInt aError);
       
    93 
       
    94 /**
       
    95  * Removes all information that should not be duplicated from aContactItem.
       
    96  */
       
    97 void RemoveNonDuplicableContactInformation(CContactItem& aContactItem);
       
    98 
       
    99 }  // namespace
       
   100 
       
   101 
       
   102 // ================= MEMBER FUNCTIONS =======================
       
   103 
       
   104 inline CPbkContactEngine::CPbkContactEngine() :
       
   105     iFreeSpaceRequiredToDelete(8*1024)  // 8 kB by default
       
   106     // CBase::operator new(TLeave) will reset other members
       
   107 	{
       
   108 	}
       
   109 
       
   110 EXPORT_C CPbkContactEngine* CPbkContactEngine::NewL(RFs* aFs/*=NULL*/)
       
   111 	{
       
   112 	CPbkContactEngine* self = new(ELeave) CPbkContactEngine;
       
   113 	CleanupStack::PushL(self);
       
   114 	self->ConstructL(NULL, EFalse, aFs);
       
   115 	CleanupStack::Pop(self);
       
   116 	return self;
       
   117 	}
       
   118 
       
   119 EXPORT_C CPbkContactEngine* CPbkContactEngine::NewL
       
   120         (const TDesC& aFileName, TBool aReplace/*=EFalse*/, RFs* aFs/*=NULL*/)
       
   121     {
       
   122 	CPbkContactEngine* self = new(ELeave) CPbkContactEngine;
       
   123 	CleanupStack::PushL(self);
       
   124 	self->ConstructL(&aFileName, aReplace, aFs);
       
   125 	CleanupStack::Pop(self);
       
   126 	return self;
       
   127     }
       
   128 
       
   129 EXPORT_C CPbkContactEngine* CPbkContactEngine::ReplaceL
       
   130         (RFs* aFs/*=NULL*/)
       
   131     {
       
   132 	CPbkContactEngine* self = new(ELeave) CPbkContactEngine;
       
   133 	CleanupStack::PushL(self);
       
   134 	self->ConstructL(NULL, ETrue, aFs);
       
   135 	CleanupStack::Pop(self);
       
   136 	return self;
       
   137     }
       
   138 
       
   139 CPbkContactEngine::~CPbkContactEngine()
       
   140 	{
       
   141     PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkContactEngine(%x)::~CPbkContactEngine"), this);
       
   142 
       
   143     // Check if this is the Tls-registered instance and remove it from Tls
       
   144     CPbkEngineLocalStorage* storage =
       
   145                     reinterpret_cast<CPbkEngineLocalStorage*> (Dll::Tls());
       
   146     if ( storage )
       
   147         {
       
   148         // check that this instance is the same than stored instance
       
   149         if ( &storage->iEngine == this )
       
   150             {
       
   151             // delete the storage instance.
       
   152             delete storage;
       
   153             Dll::SetTls( NULL );
       
   154             }
       
   155 
       
   156         }
       
   157 
       
   158     if (iSharedDataClient)
       
   159         {
       
   160         iSharedDataClient->Close();
       
   161         delete iSharedDataClient;
       
   162         }
       
   163 
       
   164 	delete iDbConnection;
       
   165     delete iObservers;
       
   166     delete iPbkFieldsInfo;
       
   167     delete iPbkConstants;
       
   168 	delete iExtension;
       
   169 
       
   170 	FeatureManager::UnInitializeLib();
       
   171     iOwnFs.Close();
       
   172 
       
   173     // Cleanup ECom session
       
   174     REComSession::FinalClose();
       
   175 	}
       
   176 
       
   177 EXPORT_C CPbkContactEngine* CPbkContactEngine::Static()
       
   178     {
       
   179     CPbkEngineLocalStorage* storage =
       
   180         reinterpret_cast<CPbkEngineLocalStorage*> ( Dll::Tls( ) );
       
   181 
       
   182     if ( storage )
       
   183         {
       
   184         return &storage->iEngine;
       
   185         }
       
   186     else
       
   187         {
       
   188         return NULL;
       
   189         }
       
   190     }
       
   191 
       
   192 inline void CPbkContactEngine::ConnectFsL(RFs* aRfs)
       
   193     {
       
   194     PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkContactEngine::ConnectFsL(0x%x)"), this);
       
   195 
       
   196     if (aRfs)
       
   197         {
       
   198         iFs = *aRfs;
       
   199         }
       
   200     else
       
   201         {
       
   202 	    User::LeaveIfError(iOwnFs.Connect());
       
   203         iFs = iOwnFs;
       
   204         }
       
   205 
       
   206     PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkContactEngine::ConnectFsL(0x%x) succesful"), this);
       
   207     }
       
   208 
       
   209 inline void CPbkContactEngine::ReadResourcesL(TBool& aSettingsVisibility)
       
   210     {
       
   211     PBK_DEBUG_PRINT(PBK_DEBUG_STRING
       
   212 		("CPbkContactEngine::ReadResourcesL(0x%x)"), this);
       
   213     __PBK_PROFILE_START(PbkProfiling::EInitEngineResources);
       
   214 
       
   215     // Open the resource files
       
   216     RResourceFile pbkResFile;
       
   217     PbkEngUtils::FindAndOpenDefaultResourceFileLC(iFs, pbkResFile);
       
   218     RResourceFile cntModelResFile;
       
   219     PbkEngUtils::FindAndOpenResourceFileLC
       
   220         (iFs, KCntModelResFileName, KDC_CONTACTS_RESOURCE_DIR, KCntModelResFileDrive,
       
   221         cntModelResFile);
       
   222 
       
   223     // Read fields info array
       
   224     iPbkFieldsInfo = CPbkFieldsInfo::NewL(pbkResFile, cntModelResFile);
       
   225 
       
   226     // load phonebook constants
       
   227     iPbkConstants = CPbkConstants::NewL(pbkResFile);
       
   228 
       
   229     // read the name ordering settings menu item visibility value:
       
   230     HBufC8* buffer = pbkResFile.AllocReadLC(R_PBK_NAME_ORDERING_SETTINGS_VISIBILITY);
       
   231 
       
   232     if ( buffer->MatchF(KSettingsVisibleCompareStr) == 0 )
       
   233         {
       
   234         aSettingsVisibility = ETrue;
       
   235         }
       
   236 
       
   237     // Close resource files
       
   238     CleanupStack::PopAndDestroy(3);
       
   239 
       
   240     __PBK_PROFILE_END(PbkProfiling::EInitEngineResources);
       
   241     PBK_DEBUG_PRINT(PBK_DEBUG_STRING
       
   242 		("CPbkContactEngine::ReadResourcesL(0x%x) succesful"), this);
       
   243     }
       
   244 
       
   245 inline void CPbkContactEngine::CreateDbConnectionL
       
   246         (const TDesC* aFileName,
       
   247 		TBool aReplace,
       
   248 		TInt& aDbOpenError,
       
   249 		TBool aSettingsVisible)
       
   250     {
       
   251     PBK_DEBUG_PRINT(PBK_DEBUG_STRING
       
   252 		("CPbkContactEngine::CreateDbConnectionL(0x%x)"), this);
       
   253 
       
   254     // Create contact database connection object
       
   255     CContactDbConnection::TParams params;
       
   256     params.iDbFileName = aFileName;
       
   257     params.iReplaceExistingDb = aReplace;
       
   258     params.iContactDbObserver = this;
       
   259     params.iFs = iFs;
       
   260     params.iFieldsInfo = iPbkFieldsInfo;
       
   261     params.iExtension = iExtension;
       
   262     params.iDbOpenError = &aDbOpenError;
       
   263 	params.iUnnamedTitle = &iPbkConstants->UnnamedTitle();
       
   264     params.iEngine = this;
       
   265 
       
   266     iDbConnection = CContactDbConnection::NewL(params, aSettingsVisible);
       
   267 
       
   268     PBK_DEBUG_PRINT(PBK_DEBUG_STRING
       
   269 		("CPbkContactEngine::CreateDbConnectionL(0x%x) succesful"), this);
       
   270     }
       
   271 
       
   272 void CPbkContactEngine::ConstructL
       
   273         (const TDesC* aFileName,
       
   274 		TBool aReplace, RFs* aRfs)
       
   275 	{
       
   276     __ASSERT_DEBUG(
       
   277         !iDbConnection && !iPbkFieldsInfo,
       
   278         Panic(EPanicPreCond_ConstructL));
       
   279 
       
   280     PBK_DEBUG_PRINT(PBK_DEBUG_STRING
       
   281 		("CPbkContactEngine::ConstructL(0x%x)"), this);
       
   282 
       
   283     ConnectFsL(aRfs);
       
   284 
       
   285 	FeatureManager::InitializeLibL();
       
   286 
       
   287 	// Shared data objects have to created after ConnectFsL,
       
   288 	// but before ReadResourcesL
       
   289     iSharedDataClient = new (ELeave) RSharedDataClient;
       
   290     User::LeaveIfError(iSharedDataClient->Connect());
       
   291 
       
   292     iExtension = CPbkEngineExtension::NewL(iFs);
       
   293 
       
   294     TBool settingsVisible(EFalse);
       
   295 
       
   296     ReadResourcesL(settingsVisible);
       
   297     TInt dbOpenError = KErrNone;
       
   298     TRAPD(dbConnectError, CreateDbConnectionL(aFileName, aReplace, dbOpenError, settingsVisible));
       
   299     if (IsFatalDbOpenError(dbOpenError))
       
   300         {
       
   301         __ASSERT_DEBUG(dbOpenError == dbConnectError, Panic(EPanicLogic_ConstructL));
       
   302         // Map all fatal database open errors to KErrCorrupt
       
   303         User::Leave(KErrCorrupt);
       
   304         }
       
   305     if (dbConnectError != KErrNone)
       
   306         {
       
   307         if (dbConnectError == KErrCorrupt)
       
   308             {
       
   309             // Convert KErrCorrupt to another error code to avoid clients
       
   310             // mixing this error up with database corruption
       
   311             dbConnectError = KErrGeneral;
       
   312             }
       
   313         User::Leave(dbConnectError);
       
   314         }
       
   315 
       
   316     if (!Dll::Tls())
       
   317         {
       
   318         CPbkEngineLocalStorage* storage = CPbkEngineLocalStorage::NewL(*this);
       
   319         TInt ret = Dll::SetTls(storage);  // Takes ownership
       
   320         __ASSERT_DEBUG( ret == KErrNone, Panic( EPanicSetTlsFails ) );
       
   321         }
       
   322 
       
   323     PBK_DEBUG_PRINT(PBK_DEBUG_STRING
       
   324 		("CPbkContactEngine::ConstructL(0x%x) succesful"), this);
       
   325 	}
       
   326 
       
   327 EXPORT_C CPbkContactItem* CPbkContactEngine::CreateEmptyContactL()
       
   328     {
       
   329     // Create an empty (ie. no fields) contact card
       
   330     CContactCard* card = CContactCard::NewLC();
       
   331     __ASSERT_DEBUG(card->CardFields().Count()==0,
       
   332         Panic(EPanicPreCond_CreateEmptyContactL));
       
   333 
       
   334     // Loop through Phonebook field infos
       
   335     const TInt count = FieldsInfo().Count();
       
   336     for (TInt i=0; i < count; ++i)
       
   337         {
       
   338         const CPbkFieldInfo* fi = FieldsInfo()[i];
       
   339         if (fi->TemplateField())
       
   340             {
       
   341             // Create a CContactItemField for fields belonging
       
   342 			// to the default template
       
   343             CContactItemField* field = fi->CreateFieldL();
       
   344             CleanupStack::PushL(field);
       
   345             // Add the field to the contact card
       
   346             card->AddFieldL(*field);
       
   347             CleanupStack::Pop(field);
       
   348             }
       
   349         }
       
   350 
       
   351     // Create phonebook contact item from card and return it.
       
   352     CPbkContactItem* pbkItem = CPbkContactItem::NewL(card,
       
   353 		FieldsInfo(), ContactNameFormat());
       
   354     CleanupStack::Pop(); // card
       
   355     return pbkItem;
       
   356     }
       
   357 
       
   358 EXPORT_C const CPbkFieldsInfo& CPbkContactEngine::FieldsInfo()
       
   359     {
       
   360     return *iPbkFieldsInfo;
       
   361     }
       
   362 
       
   363 EXPORT_C RFs& CPbkContactEngine::FsSession() const
       
   364     {
       
   365     return const_cast<RFs&>(iFs);
       
   366     }
       
   367 
       
   368 EXPORT_C CPbkContactIter* CPbkContactEngine::CreateContactIteratorLC
       
   369         (TBool aUseMinimalRead/*=EFalse*/)
       
   370     {
       
   371     iDbConnection->CancelCompress();
       
   372     return CPbkContactIter::NewLC(*this, aUseMinimalRead);
       
   373     }
       
   374 
       
   375 EXPORT_C CPbkContactChangeNotifier*
       
   376     CPbkContactEngine::CreateContactChangeNotifierL
       
   377         (MPbkContactDbObserver *aObserver)
       
   378     {
       
   379     return CPbkContactChangeNotifier::NewL(*this, aObserver);
       
   380     }
       
   381 
       
   382 EXPORT_C const TDesC& CPbkContactEngine::UnnamedTitle() const
       
   383     {
       
   384     __ASSERT_DEBUG(iPbkConstants, Panic(EPanicPreCond_UnnamedTitle));
       
   385     return iPbkConstants->UnnamedTitle();
       
   386     }
       
   387 
       
   388 EXPORT_C TContactItemId CPbkContactEngine::AddNewContactL
       
   389         (CPbkContactItem& aContact, TBool aImmediateNotify/*=EFalse*/)
       
   390     {
       
   391     PBK_DEBUG_PRINT(PBK_DEBUG_STRING
       
   392 	("CPbkContactEngine(%x)::AddNewContactL(aContact=%x, aImmediateNotify=%d)"),
       
   393         this, &aContact, aImmediateNotify);
       
   394 
       
   395     iDbConnection->CancelCompress();
       
   396     // Prepare contact for saving to the DB
       
   397     aContact.PrepareForSaveL();
       
   398     TContactItemId cid = iDbConnection->Database().AddNewContactL
       
   399 		(aContact.ContactItem());
       
   400     // Undo PrepareForSaveL
       
   401     aContact.PrepareAfterLoadL();
       
   402 
       
   403     // Send immediate event
       
   404     SendImmidiateEventToAllObservers(EContactDbObserverEventContactAdded,
       
   405         cid, aImmediateNotify);
       
   406 
       
   407     return cid;
       
   408     }
       
   409 
       
   410 EXPORT_C CPbkContactItem* CPbkContactEngine::ReadContactL
       
   411         (TContactItemId aContactId,
       
   412         const CPbkFieldIdArray* aFieldTypes/*=NULL*/)
       
   413     {
       
   414     CPbkContactItem* item = ReadContactLC(aContactId, aFieldTypes);
       
   415     CleanupStack::Pop();  // item
       
   416     return item;
       
   417     }
       
   418 
       
   419 EXPORT_C CPbkContactItem* CPbkContactEngine::ReadContactLC
       
   420         (TContactItemId aContactId,
       
   421         const CPbkFieldIdArray* aFieldTypes/*=NULL*/)
       
   422     {
       
   423     iDbConnection->CancelCompress();
       
   424     CContactItem* item = NULL;
       
   425     if (aFieldTypes)
       
   426         {
       
   427         CContactItemViewDef* viewDef =
       
   428             FieldsInfo().CreateContactItemViewDefLC(*aFieldTypes);
       
   429         item = iDbConnection->Database().ReadContactL(aContactId, *viewDef);
       
   430         CleanupStack::PopAndDestroy(viewDef);
       
   431         CleanupStack::PushL(item);
       
   432         }
       
   433     else
       
   434         {
       
   435         item = iDbConnection->Database().ReadContactLC(aContactId);
       
   436         }
       
   437     CPbkContactItem* pbkItem = CPbkContactItem::NewL
       
   438         (item, FieldsInfo(), ContactNameFormat());
       
   439     // CPbkContactItem takes ownership of item
       
   440     CleanupStack::Pop(); // item
       
   441     CleanupStack::PushL(pbkItem);
       
   442 
       
   443     // Prep empty fields for use in the application.
       
   444     // See also CommitContactL.
       
   445     pbkItem->PrepareAfterLoadL();
       
   446 
       
   447     iDbConnection->CompressL();
       
   448     return pbkItem;
       
   449     }
       
   450 
       
   451 EXPORT_C CPbkContactItem* CPbkContactEngine::ReadMinimalContactLC
       
   452         (TContactItemId aContactId)
       
   453     {
       
   454     iDbConnection->CancelCompress();
       
   455     CContactItem* item =
       
   456         iDbConnection->Database().ReadMinimalContactLC(aContactId);
       
   457     CPbkContactItem* pbkItem = CPbkContactItem::NewL
       
   458         (item, FieldsInfo(), ContactNameFormat());
       
   459     // CPbkContactItem takes ownership of item
       
   460     CleanupStack::Pop(); // item
       
   461     CleanupStack::PushL(pbkItem);
       
   462 
       
   463     // Prep empty fields for use in the application.
       
   464     // See also CommitContactL.
       
   465     pbkItem->PrepareAfterLoadL();
       
   466 
       
   467     iDbConnection->CompressL();
       
   468     return pbkItem;
       
   469     }
       
   470 
       
   471 EXPORT_C CPbkContactItem* CPbkContactEngine::OpenContactL
       
   472         (TContactItemId aContactId)
       
   473     {
       
   474     PBK_DEBUG_PRINT(
       
   475         PBK_DEBUG_STRING("CPbkContactEngine(%x)::OpenContactL(aContactId=%d)"),
       
   476         this, aContactId);
       
   477 
       
   478     CPbkContactItem* pbkItem = OpenContactLCX(aContactId);
       
   479     CleanupStack::Pop(2);  // pbkItem, lock
       
   480     return pbkItem;
       
   481     }
       
   482 
       
   483 EXPORT_C CPbkContactItem* CPbkContactEngine::OpenContactLCX
       
   484         (TContactItemId aContactId)
       
   485     {
       
   486     PBK_DEBUG_PRINT(
       
   487         PBK_DEBUG_STRING("CPbkContactEngine(%x)::OpenContactLCX(aContactId=%d)"),
       
   488         this, aContactId);
       
   489 
       
   490     iDbConnection->CancelCompress();
       
   491     CContactItem* item = iDbConnection->Database().OpenContactLX(aContactId);
       
   492     CleanupStack::PushL(item);
       
   493     CPbkContactItem* pbkItem =
       
   494         CPbkContactItem::NewL(item, FieldsInfo(), ContactNameFormat());
       
   495     // CPbkContactItem takes ownership of item
       
   496     CleanupStack::Pop(item);
       
   497     CleanupStack::PushL(pbkItem);
       
   498 
       
   499     // Prep empty fields for use in the application.
       
   500     // See also CommitContactL.
       
   501     pbkItem->PrepareAfterLoadL();
       
   502 
       
   503     return pbkItem;
       
   504     }
       
   505 
       
   506 EXPORT_C void CPbkContactEngine::CommitContactL
       
   507         (CPbkContactItem& aContact, TBool aImmediateNotify/*=EFalse*/)
       
   508     {
       
   509     PBK_DEBUG_PRINT(
       
   510         PBK_DEBUG_STRING(
       
   511         "CPbkContactEngine(%x)::CommitContactL(aContact=%x, aImmediateNotify=%d)"),
       
   512         this, &aContact, aImmediateNotify);
       
   513 
       
   514     iDbConnection->CancelCompress();
       
   515     // Prepare contact for saving to the DB
       
   516     aContact.PrepareForSaveL();
       
   517     iDbConnection->Database().CommitContactL(aContact.ContactItem());
       
   518     // Undo PrepareForSaveL
       
   519     aContact.PrepareAfterLoadL();
       
   520 
       
   521     // Send immediate event
       
   522     SendImmidiateEventToAllObservers(EContactDbObserverEventContactChanged,
       
   523         aContact.ContactItem().Id(), aImmediateNotify);
       
   524     }
       
   525 
       
   526 EXPORT_C void CPbkContactEngine::CloseContactL
       
   527         (TContactItemId aContactId)
       
   528     {
       
   529     PBK_DEBUG_PRINT(
       
   530         PBK_DEBUG_STRING("CPbkContactEngine(%x)::CloseContactL(aContactId=%d)"),
       
   531         this, aContactId);
       
   532 
       
   533     iDbConnection->CancelCompress();
       
   534     iDbConnection->Database().CloseContactL(aContactId);
       
   535     }
       
   536 
       
   537 EXPORT_C void CPbkContactEngine::DeleteContactL
       
   538         (TContactItemId aContactId, TBool aImmediateNotify/*=EFalse*/)
       
   539     {
       
   540     PBK_DEBUG_PRINT(
       
   541         PBK_DEBUG_STRING(
       
   542         "ENTER: CPbkContactEngine(%x)::DeleteContactL(aContactId=%d, aImmediateNotify=%d)"),
       
   543         this, aContactId, aImmediateNotify);
       
   544 
       
   545     doDeleteContactL(aContactId);
       
   546 
       
   547     // Send immediate event
       
   548     SendImmidiateEventToAllObservers(EContactDbObserverEventContactDeleted,
       
   549         aContactId, aImmediateNotify);
       
   550     }
       
   551 
       
   552 EXPORT_C void CPbkContactEngine::DeleteContactGroupL
       
   553         (TContactItemId aContactId, TBool aImmediateNotify/*=EFalse*/)
       
   554     {
       
   555     PBK_DEBUG_PRINT(
       
   556         PBK_DEBUG_STRING(
       
   557         "ENTER: CPbkContactEngine(%x)::DeleteContactL(aContactId=%d, aImmediateNotify=%d)"),
       
   558         this, aContactId, aImmediateNotify);
       
   559 
       
   560     doDeleteContactL(aContactId);
       
   561 
       
   562     // Send immediate event
       
   563     SendImmidiateEventToAllObservers(EContactDbObserverEventGroupDeleted,
       
   564         aContactId, aImmediateNotify);
       
   565     }
       
   566 
       
   567 
       
   568 EXPORT_C void CPbkContactEngine::DeleteContactsL
       
   569         (const CContactIdArray& aContactIds, TBool aImmediateNotify/*=EFalse*/)
       
   570     {
       
   571     PBK_DEBUG_PRINT(
       
   572         PBK_DEBUG_STRING(
       
   573         "ENTER: CPbkContactEngine(%x)::DeleteContactsL(count=%d, aImmediateNotify=%d)"),
       
   574         this, aContactIds.Count(), aImmediateNotify);
       
   575 
       
   576     iDbConnection->CancelCompress();
       
   577     iDbConnection->Database().DeleteContactsL(aContactIds);
       
   578 
       
   579     SendImmidiateEventToAllObservers(EContactDbObserverEventUnknownChanges,
       
   580         KNullContactId, aImmediateNotify);
       
   581     }
       
   582 
       
   583 EXPORT_C void CPbkContactEngine::DeleteContactsOnBackgroundL
       
   584         (const CContactIdArray& aContactIds)
       
   585     {
       
   586     iDbConnection->CancelCompress();
       
   587     // Shared data client is connected during construction
       
   588     CPbkDeleteContacts* process = CPbkDeleteContacts::NewLC(*this,aContactIds, *iSharedDataClient);
       
   589     CPbkIdleProcessRunner* runner =
       
   590         CPbkIdleProcessRunner::NewL(CActive::EPriorityIdle);
       
   591     CleanupStack::PushL(runner);
       
   592     runner->SynchronousExecuteL(*process);
       
   593 
       
   594     if (process->DeletedCount() > 0)
       
   595         {
       
   596         SendImmidiateEventToAllObservers(EContactDbObserverEventUnknownChanges,
       
   597             KNullContactId, ETrue);
       
   598         }
       
   599     CleanupStack::PopAndDestroy(2);  // runner, process
       
   600     }
       
   601 
       
   602 EXPORT_C CContactGroup* CPbkContactEngine::CreateContactGroupL
       
   603         (const TDesC& aGroupLabel,
       
   604         TBool aInTransaction)
       
   605     {
       
   606     iDbConnection->CancelCompress();
       
   607     CContactGroup* group =
       
   608         static_cast<CContactGroup*>
       
   609         (iDbConnection->Database().CreateContactGroupL(aGroupLabel, aInTransaction));
       
   610 
       
   611     // Send immediate event
       
   612     SendImmidiateEventToAllObservers(EContactDbObserverEventGroupAdded,
       
   613         group->Id(), ETrue);
       
   614 
       
   615     return group;
       
   616     }
       
   617 
       
   618 EXPORT_C void CPbkContactEngine::AddContactToGroupL
       
   619         (TContactItemId aItemId,
       
   620         TContactItemId aGroupId)
       
   621     {
       
   622     iDbConnection->CancelCompress();
       
   623     iDbConnection->Database().AddContactToGroupL(aItemId, aGroupId);
       
   624     }
       
   625 
       
   626 
       
   627 EXPORT_C void CPbkContactEngine::RemoveContactFromGroupL
       
   628         (TContactItemId aItemId,
       
   629         TContactItemId aGroupId)
       
   630     {
       
   631     iDbConnection->CancelCompress();
       
   632     iDbConnection->Database().RemoveContactFromGroupL(aItemId, aGroupId);
       
   633     }
       
   634 
       
   635 EXPORT_C CContactGroup* CPbkContactEngine::ReadContactGroupL
       
   636         (TContactItemId aId)
       
   637     {
       
   638     iDbConnection->CancelCompress();
       
   639     CContactItem* item = iDbConnection->Database().ReadContactL(aId);
       
   640     __ASSERT_ALWAYS(item->Type() == KUidContactGroup,
       
   641         Panic(EPanicContactNotGroup));
       
   642     return static_cast<CContactGroup*>(item);
       
   643     }
       
   644 
       
   645 EXPORT_C CContactGroup* CPbkContactEngine::OpenContactGroupL
       
   646         (TContactItemId aId)
       
   647     {
       
   648     iDbConnection->CancelCompress();
       
   649     CContactItem* item = iDbConnection->Database().OpenContactL(aId);
       
   650     __ASSERT_ALWAYS(item->Type() == KUidContactGroup,
       
   651         Panic(EPanicContactNotGroup));
       
   652     return static_cast<CContactGroup*>(item);
       
   653     }
       
   654 
       
   655 EXPORT_C CContactGroup* CPbkContactEngine::OpenContactGroupLCX
       
   656         (TContactItemId aId)
       
   657     {
       
   658     iDbConnection->CancelCompress();
       
   659     CContactItem* item = iDbConnection->Database().OpenContactLX(aId);
       
   660     __ASSERT_ALWAYS(item->Type() == KUidContactGroup,
       
   661         Panic(EPanicContactNotGroup));
       
   662     CContactGroup* group = static_cast<CContactGroup*>(item);
       
   663     CleanupStack::PushL(group);
       
   664     return group;
       
   665     }
       
   666 
       
   667 EXPORT_C void CPbkContactEngine::CommitContactGroupL
       
   668         (CContactGroup& aGroup,
       
   669         TBool aImmediateNotify/*=EFalse*/)
       
   670     {
       
   671     iDbConnection->CancelCompress();
       
   672     iDbConnection->Database().CommitContactL(aGroup);
       
   673 
       
   674     SendImmidiateEventToAllObservers(EContactDbObserverEventGroupChanged,
       
   675         aGroup.Id(), aImmediateNotify);
       
   676     }
       
   677 
       
   678 EXPORT_C TContactItemId CPbkContactEngine::DuplicateContactL(TContactItemId aId,
       
   679         TBool aImmediateNotify/*=EFalse*/)
       
   680     {
       
   681     PBK_DEBUG_PRINT(
       
   682         PBK_DEBUG_STRING(
       
   683         "CPbkContactEngine(%x)::DuplicateContactL(aId=%d, aImmediateNotify=%d)"),
       
   684         this, aId, aImmediateNotify);
       
   685 
       
   686     iDbConnection->CancelCompress();
       
   687     CContactItem* item = iDbConnection->Database().ReadContactLC(
       
   688         aId, *iDbConnection->Database().AllFieldsView());
       
   689     // remove all non duplicable contact information
       
   690     RemoveNonDuplicableContactInformation(*item);
       
   691 
       
   692     TContactItemId dupId = iDbConnection->Database().AddNewContactL(*item);
       
   693     CleanupStack::PopAndDestroy();  // item
       
   694 
       
   695     // Send immediate event
       
   696     SendImmidiateEventToAllObservers(EContactDbObserverEventContactAdded,
       
   697         dupId, aImmediateNotify);
       
   698     return dupId;
       
   699     }
       
   700 
       
   701 EXPORT_C void CPbkContactEngine::SetFieldAsSpeedDialL
       
   702         (CPbkContactItem& aItem,
       
   703         TInt aFieldIndex,
       
   704         TInt aSpeedDialPosition)
       
   705     {
       
   706     iDbConnection->CancelCompress();
       
   707     // find correct CContactItemField index
       
   708     CContactItemField& field = aItem.CardFields()[aFieldIndex].ItemField();
       
   709     for (TInt i = 0; i < aItem.ContactItem().CardFields().Count(); ++i)
       
   710         {
       
   711         if (&field == &(aItem.ContactItem().CardFields()[i]))
       
   712             {
       
   713             aFieldIndex = i;
       
   714             break;
       
   715             }
       
   716         }
       
   717 
       
   718     // Prepare contact for saving to the DB
       
   719     aItem.PrepareForSaveL();
       
   720 
       
   721     iDbConnection->Database().SetFieldAsSpeedDialL(
       
   722         aItem.ContactItem(), aFieldIndex, aSpeedDialPosition);
       
   723 
       
   724     // Undo PrepareForSaveL
       
   725     aItem.PrepareAfterLoadL();
       
   726 
       
   727     // update the aItem's field set
       
   728     aItem.UpdateFieldSetL(*iPbkFieldsInfo);
       
   729 
       
   730     // CContactDatabase::SetFieldAsSpeedDialL does not send notifications
       
   731     // Send immediate event
       
   732     SendImmidiateEventToAllObservers(EContactDbObserverEventContactChanged,
       
   733         aItem.Id(), ETrue);
       
   734     }
       
   735 
       
   736 EXPORT_C CContactDatabase& CPbkContactEngine::Database()
       
   737     {
       
   738     return iDbConnection->Database();
       
   739     }
       
   740 
       
   741 EXPORT_C CContactViewBase& CPbkContactEngine::AllContactsView()
       
   742     {
       
   743     return iDbConnection->AllContactsView();
       
   744     }
       
   745 
       
   746 EXPORT_C CContactViewBase& CPbkContactEngine::AllGroupsViewL()
       
   747     {
       
   748     return iDbConnection->AllGroupsViewL();
       
   749     }
       
   750 
       
   751 EXPORT_C CContactViewBase& CPbkContactEngine::FilteredContactsViewL
       
   752         (TInt aFilter)
       
   753     {
       
   754     return iDbConnection->FilteredContactsViewL(aFilter);
       
   755     }
       
   756 
       
   757 EXPORT_C HBufC* CPbkContactEngine::GetContactTitleL
       
   758         (const CPbkContactItem& aItem) const
       
   759     {
       
   760     // Delegate call to iContactNameFormatter
       
   761     return ContactNameFormat().GetContactTitleL(aItem);
       
   762     }
       
   763 
       
   764 EXPORT_C void CPbkContactEngine::SetCompressUi(MPbkCompressUi* aCompressUi)
       
   765     {
       
   766     iDbConnection->SetCompressUi(aCompressUi);
       
   767     }
       
   768 
       
   769 EXPORT_C TBool CPbkContactEngine::CheckCompress()
       
   770     {
       
   771     return iDbConnection->CheckCompress();
       
   772     }
       
   773 
       
   774 EXPORT_C void CPbkContactEngine::CompressL()
       
   775     {
       
   776     iDbConnection->CompressL();
       
   777     }
       
   778 
       
   779 EXPORT_C void CPbkContactEngine::CancelCompress()
       
   780     {
       
   781     iDbConnection->CancelCompress();
       
   782     }
       
   783 
       
   784 EXPORT_C void CPbkContactEngine::CheckFileSystemSpaceAndCompressL()
       
   785     {
       
   786     iDbConnection->CheckFileSystemSpaceAndCompressL();
       
   787     }
       
   788 
       
   789 EXPORT_C HBufC* CPbkContactEngine::GetContactTitleOrNullL
       
   790         (const MPbkFieldDataArray& aContactData)
       
   791     {
       
   792     // Delegate call to iContactNameFormatter
       
   793     return ContactNameFormat().GetContactTitleOrNullL(aContactData);
       
   794     }
       
   795 
       
   796 EXPORT_C TBool CPbkContactEngine::IsTitleField(TPbkFieldId aFieldId) const
       
   797     {
       
   798     // Delegate call to iContactNameFormatter
       
   799     return ContactNameFormat().IsTitleField(aFieldId);
       
   800     }
       
   801 
       
   802 EXPORT_C MPbkContactNameFormat& CPbkContactEngine::ContactNameFormat() const
       
   803     {
       
   804     return iDbConnection->ContactNameFormatter();
       
   805     }
       
   806 
       
   807 EXPORT_C TContactItemId CPbkContactEngine::GetSpeedDialFieldL
       
   808         (TInt aSpeedDialPosition,
       
   809         TDes& aPhoneNumber) const
       
   810     {
       
   811     iDbConnection->CancelCompress();
       
   812     return iDbConnection->Database().GetSpeedDialFieldL
       
   813         (aSpeedDialPosition,aPhoneNumber);
       
   814     }
       
   815 
       
   816 EXPORT_C void CPbkContactEngine::RemoveSpeedDialFieldL
       
   817         (TContactItemId aContactId,
       
   818         TInt aSpeedDialPosition)
       
   819     {
       
   820     iDbConnection->CancelCompress();
       
   821     iDbConnection->Database().RemoveSpeedDialFieldL(
       
   822         aContactId, aSpeedDialPosition);
       
   823     }
       
   824 
       
   825 EXPORT_C TBool CPbkContactEngine::IsSpeedDialAssigned
       
   826         (const CPbkContactItem& aItem, TInt aFieldIndex) const
       
   827     {
       
   828     const CContentType& contentType =
       
   829         aItem.CardFields()[aFieldIndex].ItemField().ContentType();
       
   830     TBool result = EFalse;
       
   831 
       
   832     const TInt fieldtypeCount = contentType.FieldTypeCount();
       
   833     for (TInt i = 0; i < fieldtypeCount; ++i)
       
   834         {
       
   835         TFieldType fieldType = contentType.FieldType(i);
       
   836         switch (fieldType.iUid)
       
   837             {
       
   838             case KUidSpeedDialOneValue:			// FALLTHROUGH
       
   839             case KUidSpeedDialTwoValue:			// FALLTHROUGH
       
   840             case KUidSpeedDialThreeValue:		// FALLTHROUGH
       
   841             case KUidSpeedDialFourValue:		// FALLTHROUGH
       
   842             case KUidSpeedDialFiveValue:		// FALLTHROUGH
       
   843             case KUidSpeedDialSixValue:			// FALLTHROUGH
       
   844             case KUidSpeedDialSevenValue:		// FALLTHROUGH
       
   845             case KUidSpeedDialEightValue:		// FALLTHROUGH
       
   846             case KUidSpeedDialNineValue:
       
   847 				{
       
   848                 result = ETrue;
       
   849                 break;
       
   850 				}
       
   851             }
       
   852         }
       
   853     return result;
       
   854     }
       
   855 
       
   856 EXPORT_C CContactIdArray* CPbkContactEngine::MatchPhoneNumberL
       
   857         (const TDesC& aNumber, const TInt aMatchLengthFromRight)
       
   858     {
       
   859     iDbConnection->CancelCompress();
       
   860     return iDbConnection->Database().MatchPhoneNumberL
       
   861         (aNumber,aMatchLengthFromRight);
       
   862     }
       
   863 
       
   864 EXPORT_C CContactIdArray* CPbkContactEngine::FindLC
       
   865         (const TDesC& aText,
       
   866         const CPbkFieldIdArray* aFieldTypes/*=NULL*/)
       
   867     {
       
   868     iDbConnection->CancelCompress();
       
   869     CContactItemFieldDef* fieldDef =
       
   870         FieldsInfo().CreateContactItemFieldDefLC(aFieldTypes);
       
   871 
       
   872     // Call contact db's FindLC
       
   873     CContactIdArray* result = iDbConnection->Database().FindLC(aText, fieldDef);
       
   874     CleanupStack::Pop();  // result
       
   875 
       
   876     // Cleanup and return
       
   877     CleanupStack::PopAndDestroy(fieldDef);
       
   878     CleanupStack::PushL(result);
       
   879     return result;
       
   880     }
       
   881 
       
   882 EXPORT_C CPbkIdleFinder* CPbkContactEngine::FindAsyncL
       
   883         (const TDesC& aText,
       
   884         const CPbkFieldIdArray* aFieldTypes/*=NULL*/,
       
   885         MIdleFindObserver* aObserver/*=NULL*/)
       
   886     {
       
   887     iDbConnection->CancelCompress();
       
   888     CContactItemFieldDef* fieldDef =
       
   889         FieldsInfo().CreateContactItemFieldDefLC(aFieldTypes);
       
   890 
       
   891     // Call contact db's FindAsyncL
       
   892     CIdleFinder* finder =
       
   893         iDbConnection->Database().FindAsyncL(aText, fieldDef, aObserver);
       
   894     CleanupStack::PushL(finder);
       
   895 
       
   896     // Pack result and fieldDef array into a CPbkIdleFinder
       
   897     CPbkIdleFinder* pbkFinder = new(ELeave) CPbkIdleFinder(finder, fieldDef);
       
   898 
       
   899     // Cleanup and return
       
   900     CleanupStack::Pop(2);  // finder, fieldDef
       
   901     return pbkFinder;
       
   902     }
       
   903 
       
   904 /**
       
   905  * Distributes CContactDatabase observer events in Phonebook.
       
   906  */
       
   907 void CPbkContactEngine::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
       
   908     {
       
   909     PBK_DEBUG_PRINT(
       
   910         PBK_DEBUG_STRING(
       
   911         "CPbkContactEngine(%x)::HandleDatabaseEventL(), type=%d, id=%d, conn=%d"),
       
   912         this, aEvent.iType, aEvent.iContactId, aEvent.iConnectionId);
       
   913 
       
   914     // Forward the event to all observers of this engine object
       
   915     SendEventToAllObservers(aEvent);
       
   916     }
       
   917 
       
   918 void CPbkContactEngine::SendEventToAllObservers
       
   919         (const TContactDbObserverEvent& aEvent)
       
   920     {
       
   921     if (iObservers)
       
   922         {
       
   923         TInt i;
       
   924 
       
   925         // First forward the standard event to all observers
       
   926         for (i = iObservers->Count()-1; i >= 0; --i)
       
   927             {
       
   928             #ifndef _DEBUG
       
   929             TRAP_IGNORE((*iObservers)[i]->HandleDatabaseEventL(aEvent));
       
   930             #else
       
   931             TRAPD(ignore, (*iObservers)[i]->HandleDatabaseEventL(aEvent));
       
   932             if (ignore != KErrNone)
       
   933                 {
       
   934                 RDebug::Print(
       
   935                     _L("Leave %d occured in MPbkContactDbObserver(%x)::HandleDatabaseEventL()"),
       
   936                     ignore, (*iObservers)[i]);
       
   937                 }
       
   938             #endif
       
   939             }
       
   940 
       
   941         // Next tell all observers that all observers have had their
       
   942         // HandleDatabaseEventL function called.
       
   943         for (i = iObservers->Count()-1; i >= 0; --i)
       
   944             {
       
   945             #ifndef _DEBUG
       
   946             TRAP_IGNORE((*iObservers)[i]->DatabaseEventHandledL(aEvent));
       
   947             #else
       
   948             TRAPD(ignore, (*iObservers)[i]->DatabaseEventHandledL(aEvent));
       
   949             if (ignore != KErrNone)
       
   950                 {
       
   951                 RDebug::Print(
       
   952                     _L("Leave %d occured in MPbkContactDbObserver(%x)::DatabaseEventHandledL()"),
       
   953                     ignore, (*iObservers)[i]);
       
   954                 }
       
   955             #endif
       
   956             }
       
   957         }
       
   958 
       
   959     PBK_DEBUG_PRINT(
       
   960         PBK_DEBUG_STRING(
       
   961         "CPbkContactEngine(%x)::SendEventToAllObservers() executed. type=%d, id=%d, conn=%d"),
       
   962         this, aEvent.iType, aEvent.iContactId, aEvent.iConnectionId);
       
   963     }
       
   964 
       
   965 void CPbkContactEngine::SendImmidiateEventToAllObservers
       
   966         (TContactDbObserverEventType aEventType,
       
   967         TContactItemId aContactId,
       
   968         TBool aSendEvent)
       
   969     {
       
   970     if (aSendEvent)
       
   971         {
       
   972         TContactDbObserverEvent event;
       
   973         event.iType = aEventType;
       
   974         event.iContactId = aContactId;
       
   975         event.iConnectionId = iDbConnection->Database().ConnectionId();
       
   976         SendEventToAllObservers(event);
       
   977         }
       
   978     }
       
   979 
       
   980 void CPbkContactEngine::AddObserverL(MPbkContactDbObserver* aObserver)
       
   981     {
       
   982     // PreCond
       
   983     __ASSERT_DEBUG(aObserver, Panic(EPanicPreCond_AddObserverL));
       
   984 
       
   985     if (!iObservers)
       
   986         {
       
   987         iObservers = new(ELeave) CArrayPtrFlat<MPbkContactDbObserver>(4);
       
   988         }
       
   989 
       
   990     PBK_DEBUG_ONLY(const TInt old_Count=iObservers->Count());
       
   991 
       
   992     iObservers->AppendL(aObserver);
       
   993 
       
   994     PBK_DEBUG_PRINT(
       
   995         PBK_DEBUG_STRING("CPbkContactEngine(%x)::AddObserverL(%x), count = %d"),
       
   996         this, aObserver, iObservers->Count());
       
   997 
       
   998     // PostCond
       
   999     __ASSERT_DEBUG(iObservers->Count()==old_Count+1 &&
       
  1000                    (*iObservers)[iObservers->Count()-1]==aObserver,
       
  1001                    Panic(EPanicPostCond_AddObserverL));
       
  1002     }
       
  1003 
       
  1004 void CPbkContactEngine::RemoveObserver(MPbkContactDbObserver* aObserver)
       
  1005     {
       
  1006     // PreCond
       
  1007     __ASSERT_DEBUG(iObservers && aObserver,
       
  1008         Panic(EPanicPreCond_RemoveObserver));
       
  1009 
       
  1010     const TInt count = iObservers->Count();
       
  1011     for (TInt i = 0; i < count; ++i)
       
  1012         {
       
  1013         if ((*iObservers)[i] == aObserver)
       
  1014             {
       
  1015             PBK_DEBUG_ONLY(const TInt old_Count=iObservers->Count());
       
  1016 
       
  1017             iObservers->Delete(i);
       
  1018 
       
  1019 
       
  1020             PBK_DEBUG_PRINT(
       
  1021                 PBK_DEBUG_STRING(
       
  1022                 "CPbkContactEngine(%x)::RemoveObserver(%x), count = %d"),
       
  1023                 this, aObserver, iObservers->Count());
       
  1024 
       
  1025             // PostCond
       
  1026             __ASSERT_DEBUG(iObservers->Count()==old_Count-1,
       
  1027                    Panic(EPanicPostCond_RemoveObserver));
       
  1028             return;
       
  1029             }
       
  1030         }
       
  1031 
       
  1032     // Illegal state
       
  1033     __ASSERT_DEBUG(EFalse, Panic(EPanicObserverNotFoundInRemove));
       
  1034     }
       
  1035 
       
  1036 void CPbkContactEngine::doDeleteContactL(TContactItemId aContactId)
       
  1037     {
       
  1038     iDbConnection->CancelCompress();
       
  1039     CContactDatabase& db = iDbConnection->Database();
       
  1040     const TInt sizeBefore = db.FileSize();
       
  1041 
       
  1042     iSharedDataClient->RequestFreeDiskSpaceLC(iFreeSpaceRequiredToDelete);
       
  1043     db.DeleteContactL(aContactId);
       
  1044     CleanupStack::PopAndDestroy();  // RequestFreeDiskSpaceLC
       
  1045 
       
  1046     // Calculate how much database grew rounded to next kB
       
  1047     const TInt KB = 1024;
       
  1048     TInt sizeDiff = db.FileSize() - sizeBefore + KB;
       
  1049     sizeDiff -= sizeDiff % KB;
       
  1050     if (sizeDiff > iFreeSpaceRequiredToDelete)
       
  1051         {
       
  1052         // Update maximum size required
       
  1053         iFreeSpaceRequiredToDelete = sizeDiff;
       
  1054         }
       
  1055     }
       
  1056 
       
  1057 EXPORT_C void CPbkContactEngine::SetNameDisplayOrderL
       
  1058 		(TPbkNameOrder aNameOrder)
       
  1059 	{
       
  1060 	// change sort order
       
  1061 	iDbConnection->SetNameDisplayOrderL(aNameOrder);
       
  1062 	}
       
  1063 
       
  1064 EXPORT_C CPbkContactEngine::TPbkNameOrder
       
  1065         CPbkContactEngine::NameDisplayOrderL()
       
  1066 	{
       
  1067 	// retrieve sort order from sort order manager
       
  1068 	return iDbConnection->NameDisplayOrder();
       
  1069 	}
       
  1070 
       
  1071 EXPORT_C CPbkConstants* CPbkContactEngine::Constants()
       
  1072     {
       
  1073     return iPbkConstants;
       
  1074     }
       
  1075 
       
  1076 const CPbkSortOrderManager& CPbkContactEngine::SortOrderManager() const
       
  1077     {
       
  1078     return iDbConnection->SortOrderManager();
       
  1079     }
       
  1080 
       
  1081 EXPORT_C void CPbkContactEngine::SetNameSeparatorL(TChar aSeparator)
       
  1082     {
       
  1083     iDbConnection->SetNameSeparatorL(aSeparator);
       
  1084     }
       
  1085 
       
  1086 EXPORT_C TChar CPbkContactEngine::NameSeparator() const
       
  1087     {
       
  1088     return iDbConnection->NameSeparator();
       
  1089     }
       
  1090 
       
  1091 // ==================== LOCAL FUNCTIONS ====================
       
  1092 
       
  1093 namespace {
       
  1094 
       
  1095 TBool IsFatalDbOpenError(TInt aError)
       
  1096     {
       
  1097     switch (aError)
       
  1098         {
       
  1099         case KErrNone:              //FALLTHROUGH
       
  1100         case KErrCancel:            //FALLTHROUGH
       
  1101         case KErrNoMemory:          //FALLTHROUGH
       
  1102         case KErrDied:              //FALLTHROUGH
       
  1103         case KErrInUse:             //FALLTHROUGH
       
  1104         case KErrServerTerminated:  //FALLTHROUGH
       
  1105         case KErrServerBusy:        //FALLTHROUGH
       
  1106         case KErrNotReady:          //FALLTHROUGH
       
  1107         case KErrAccessDenied:      //FALLTHROUGH
       
  1108         case KErrLocked:            //FALLTHROUGH
       
  1109         case KErrWrite:             //FALLTHROUGH
       
  1110         case KErrDisMounted:        //FALLTHROUGH
       
  1111         case KErrDiskFull:          //FALLTHROUGH
       
  1112         case KErrAbort:             //FALLTHROUGH
       
  1113         case KErrBadPower:          //FALLTHROUGH
       
  1114         case KErrDirFull:           //FALLTHROUGH
       
  1115         case KErrHardwareNotAvailable:
       
  1116             {
       
  1117             return EFalse;
       
  1118             }
       
  1119 
       
  1120         // All error codes not handled above end up here, especially
       
  1121         // KErrCorrupt.
       
  1122         default:
       
  1123             {
       
  1124             return ETrue;
       
  1125             }
       
  1126         }
       
  1127     }
       
  1128 
       
  1129 TBool IsNonDuplicableFieldType(TFieldType aFieldType)
       
  1130     {
       
  1131     switch (aFieldType.iUid)
       
  1132         {
       
  1133         case KUidContactsVoiceDialFieldValue:	//FALLTHROUGH
       
  1134         case KUidSpeedDialOneValue:				//FALLTHROUGH
       
  1135         case KUidSpeedDialTwoValue:				//FALLTHROUGH
       
  1136         case KUidSpeedDialThreeValue:			//FALLTHROUGH
       
  1137         case KUidSpeedDialFourValue:			//FALLTHROUGH
       
  1138         case KUidSpeedDialFiveValue:			//FALLTHROUGH
       
  1139         case KUidSpeedDialSixValue:				//FALLTHROUGH
       
  1140         case KUidSpeedDialSevenValue:			//FALLTHROUGH
       
  1141         case KUidSpeedDialEightValue:			//FALLTHROUGH
       
  1142         case KUidSpeedDialNineValue:
       
  1143             {
       
  1144             return ETrue;
       
  1145             }
       
  1146 
       
  1147         default:
       
  1148             {
       
  1149             return EFalse;
       
  1150             }
       
  1151         }
       
  1152     }
       
  1153 
       
  1154 void RemoveNonDuplicableContactInformation(CContactItem& aContactItem)
       
  1155     {
       
  1156     // Remove all non duplicable field types from all fields
       
  1157     const TInt fieldCount = aContactItem.CardFields().Count();
       
  1158     for (TInt fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
       
  1159         {
       
  1160         CContactItemField& field = aContactItem.CardFields()[fieldIndex];
       
  1161         const CContentType& contentType = field.ContentType();
       
  1162         TBool typeRemoved;
       
  1163         do
       
  1164             {
       
  1165             typeRemoved = EFalse;
       
  1166 		    const TInt typeCount = contentType.FieldTypeCount();
       
  1167             for (TInt typeIndex = 0; typeIndex < typeCount; ++typeIndex)
       
  1168                 {
       
  1169                 const TFieldType type = contentType.FieldType(typeIndex);
       
  1170                 if (IsNonDuplicableFieldType(type))
       
  1171                     {
       
  1172                     field.RemoveFieldType(type);
       
  1173                     typeRemoved = ETrue;
       
  1174                     break;
       
  1175                     }
       
  1176                 }
       
  1177             }
       
  1178         while (typeRemoved);
       
  1179         }
       
  1180     }
       
  1181 
       
  1182 }  // namespace
       
  1183 
       
  1184 //  End of File