phonebookengines_old/contactsmodel/cntplsql/src/cntpplviewsession.cpp
changeset 40 b46a585f6909
equal deleted inserted replaced
37:fd64c38c277d 40:b46a585f6909
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19  @released
       
    20 */
       
    21 #include "cntpplviewmanager.h"
       
    22 #include "dbsqlconstants.h"
       
    23 #include "cntpersistenceutility.h"
       
    24 #include <cntfldst.h>
       
    25 
       
    26 const TInt KCachedPrepareTimeOut = 1000000; //1 second
       
    27 
       
    28 /**
       
    29 Object factory method.
       
    30 */
       
    31 CCntPplViewSession* CCntPplViewSession::NewL(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, const CContactTextDef& aTextDef, const TContactViewPreferences aViewPrefs)
       
    32 	{
       
    33 	CCntPplViewSession* viewSession = new (ELeave) CCntPplViewSession(aContactsFile, aContactProperties, aSelectAllFields, aViewId, aViewPrefs);
       
    34 	CleanupStack::PushL(viewSession);
       
    35 	viewSession->ConstructL(aTextDef);
       
    36 	CleanupStack::Pop(viewSession);
       
    37 	return viewSession;
       
    38 	}
       
    39 
       
    40 	
       
    41 /**
       
    42 CCntPplViewSession first phase constructor.
       
    43 */
       
    44 CCntPplViewSession::CCntPplViewSession(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, TContactViewPreferences aViewPrefs)
       
    45 :  	CTimer(CActive::EPriorityIdle),
       
    46     iViewId(aViewId),
       
    47 	iContactProperties(aContactProperties),
       
    48     iContactsFile(aContactsFile),
       
    49 	iSqlSmtSelectAllFieldsById(aSelectAllFields),
       
    50 	iViewPrefs(aViewPrefs)
       
    51 	{
       
    52 	CActiveScheduler::Add(this);
       
    53 	}
       
    54 
       
    55 	
       
    56 /**
       
    57 CCntPplViewSession destructor.
       
    58 */
       
    59 CCntPplViewSession::~CCntPplViewSession()
       
    60 	{
       
    61 	Deque();
       
    62 	
       
    63 	if(iRSqlStatement)
       
    64 		{
       
    65 		iRSqlStatement->Close();
       
    66 		delete iRSqlStatement;
       
    67 		}
       
    68 	
       
    69 	if(iCachedSqlStatement)
       
    70 		{
       
    71 		iCachedSqlStatement->Close();
       
    72 		delete iCachedSqlStatement;
       
    73 		}
       
    74 	
       
    75 	delete iCntSqlStatement;
       
    76 	delete iTextDef;
       
    77 	}
       
    78 
       
    79 	
       
    80 /**
       
    81 CCntPplViewSession second phase constructor.
       
    82 */
       
    83 void CCntPplViewSession::ConstructL(const CContactTextDef& aTextDef)
       
    84 	{
       
    85 	//Constructing iCntSqlStatement, iTextDef, and iIsFastAccessFieldsOnly
       
    86 	//by simply call ChangeSortOrderL
       
    87 	CTimer::ConstructL();
       
    88 	ChangeSortOrderL(aTextDef);
       
    89 	}	
       
    90 
       
    91 	
       
    92 /**
       
    93 Change the sorting order/text definition. It should be always called when 
       
    94 there is not an iteration started in persistence layer.
       
    95 
       
    96 @param aTextDef the new text definition to be used in the view session.
       
    97 */
       
    98 void CCntPplViewSession::ChangeSortOrderL(const CContactTextDef& aTextDef)
       
    99 	{
       
   100 	//Cleanup the cached Prepare statement as the sort order will be changed
       
   101 	Cancel();
       
   102     CleanupCachedPrepareStatement();
       
   103 	
       
   104 	//Copy the text definition
       
   105 	CContactTextDef* textDef = CContactTextDef::NewLC();
       
   106 	const TInt KTextDefCount = aTextDef.Count();
       
   107 	for (TInt index = 0; index < KTextDefCount; ++index)
       
   108 		{
       
   109 		textDef->AppendL(TContactTextDefItem(aTextDef.At(index).iFieldType));
       
   110 		}
       
   111 	
       
   112 	// Create select statement on contact table
       
   113 	TCntSqlStatementType statementType(ESelect, KSqlContactTableName());
       
   114 	CCntSqlStatement* sqlSmt = TSqlProvider::GetSqlStatementL(statementType);
       
   115 	CleanupStack::PushL(sqlSmt);
       
   116 	
       
   117 	// Always select id, type flags.	
       
   118 	sqlSmt->SetParamL(KContactId(), KSpace());
       
   119 	sqlSmt->SetParamL(KContactTypeFlags(), KSpace());
       
   120 	
       
   121 	//Go through text definition to construct select statement.
       
   122 	TBool isFastAccessOnly = ETrue;
       
   123 	for(TInt ii = 0; ii < KTextDefCount; ++ii)
       
   124 		{
       
   125 		const TDesC& KColunmName = TCntPersistenceUtility::GetFastAccessColumnNameById(aTextDef.At(ii).iFieldType.iUid);
       
   126 		if(KColunmName.Length() > 0) 
       
   127 			{
       
   128 			sqlSmt->SetParamL(KColunmName, KSpace());
       
   129 			}
       
   130 		else
       
   131 			{
       
   132 			isFastAccessOnly = EFalse;		
       
   133 			}
       
   134 		}
       
   135 	
       
   136 	if(!isFastAccessOnly)
       
   137 		{
       
   138 		//Fields in text blob are needed, add text fields header and
       
   139         //text blob columns in the select statement.		
       
   140 		sqlSmt->SetParamL(KContactTextFieldHeader(), KSpace());
       
   141 		sqlSmt->SetParamL(KContactTextFields(), KSpace());
       
   142 		}
       
   143 
       
   144 	CleanupStack::Pop(2, textDef); // sqlSmt, textDef.
       
   145 	
       
   146 	delete iCntSqlStatement;
       
   147 	iCntSqlStatement = sqlSmt;
       
   148 	
       
   149 	delete iTextDef;
       
   150 	iTextDef = textDef;
       
   151 	
       
   152 	iIsFastAccessFieldsOnly = isFastAccessOnly;
       
   153 	}
       
   154 	
       
   155 
       
   156 /**
       
   157 Preparing sql statement for the coming iteration requests from upper layer.
       
   158 Caller has the responsibilty of controling the lifecycle of the iteration 
       
   159 session -- when it starts and stop.  
       
   160 */
       
   161 void CCntPplViewSession::BeginIterateL()
       
   162 	{
       
   163 	if (! iContactsFile.IsOpened())
       
   164 		{
       
   165 		User::Leave(KErrInUse);
       
   166 		}
       
   167 	
       
   168 	if(iRSqlStatement)
       
   169 		{
       
   170 		iRSqlStatement->Close();
       
   171 		delete iRSqlStatement;
       
   172 		iRSqlStatement = NULL;
       
   173 		}
       
   174 	
       
   175 	//Create a new sqlstatment to start a iteration	
       
   176 	iRSqlStatement = new (ELeave) RSqlStatement();
       
   177 	
       
   178 	// we don't need condition for iterating database.
       
   179 	iCntSqlStatement->ClearCondition();
       
   180 	
       
   181 	iRSqlStatement->PrepareL(iContactsFile.NamedDatabase(), iCntSqlStatement->SqlStringL());
       
   182 	}
       
   183 
       
   184 	
       
   185 /**
       
   186 Stop iteration by releasing iteration sql statement.
       
   187 */
       
   188 void CCntPplViewSession::EndIterate()
       
   189 	{
       
   190 	if(iRSqlStatement)
       
   191 		{
       
   192 		iRSqlStatement->Close();
       
   193 		delete iRSqlStatement;
       
   194 		iRSqlStatement = NULL;
       
   195 		}
       
   196 	}
       
   197 
       
   198 	
       
   199 /**
       
   200 Get next view contact object from iterating sql statement.
       
   201 
       
   202 @return CViewContact object or NULL if iteration reachs end of rows.
       
   203 */
       
   204 CViewContact* CCntPplViewSession::NextItemL(TContactViewPreferences aViewPrefs)
       
   205 	{
       
   206 	if(!iRSqlStatement)
       
   207 		{
       
   208 		//Iteration has not started
       
   209 		BeginIterateL();	
       
   210 		}
       
   211 	
       
   212 	return CreateViewItemL(*iRSqlStatement, *iCntSqlStatement, aViewPrefs);
       
   213 	}
       
   214 
       
   215 	
       
   216 /**
       
   217 Get view contact object based on given contact id.
       
   218 
       
   219 @return CViewContact object or NULL if there is not such a contact.
       
   220 */
       
   221 CViewContact* CCntPplViewSession::ItemAtL(TContactItemId aContactId)
       
   222 	{
       
   223 	//Cancel the timer so that the cached Prepare statement would not be deleted.
       
   224 	Cancel();
       
   225 	
       
   226 	CViewContact* viewContact = NULL;
       
   227 	
       
   228 	TRAPD(err, viewContact = doItemAtL(aContactId));
       
   229     if(err != KErrNone)
       
   230         {
       
   231         CleanupCachedPrepareStatement();
       
   232     	User::Leave(err);	
       
   233         }
       
   234     	
       
   235 	//Reset the timer
       
   236 	After(KCachedPrepareTimeOut);
       
   237 	return viewContact;
       
   238 	}
       
   239 
       
   240 
       
   241 /**
       
   242 The method to do the real work of get view contact object based on given contact id.
       
   243 
       
   244 @return CViewContact object or NULL if there is not such a contact.
       
   245 */
       
   246 CViewContact* CCntPplViewSession::doItemAtL(TContactItemId aContactId)
       
   247     {
       
   248     if (! iContactsFile.IsOpened())
       
   249     	{
       
   250     	User::Leave(KErrInUse);
       
   251     	}
       
   252     
       
   253 	if(!iCachedSqlStatement)
       
   254 		{
       
   255 		//iCacheSqlStatement is just for ItemAt while iRSqlStatement is used for iteration 
       
   256 		//and maintained by BeginIterateL and EndIterateL.
       
   257     	iCntSqlStatement->SetConditionL(KSelectCondition_SearchForContactId()); 
       
   258 		
       
   259 		//Create a new sqlstatment and cache its Prepare statement.	
       
   260 		iCachedSqlStatement = new (ELeave) RSqlStatement();
       
   261 		iCachedSqlStatement->PrepareL(iContactsFile.NamedDatabase(),  iCntSqlStatement->SqlStringL());
       
   262 		}
       
   263 		
       
   264 	User::LeaveIfError(iCachedSqlStatement->BindInt(KFirstIndex, aContactId)); //Bind item id into the condition.	
       
   265 
       
   266 	CViewContact* viewContact = CreateViewItemL(*iCachedSqlStatement, *iCntSqlStatement, iViewPrefs);
       
   267 	
       
   268 	// Adding this to the cleanup stack, because coverity recons that "iCachedSqlStatement->Reset();" can leave, and it's probably right
       
   269 	CleanupStack::PushL(viewContact);
       
   270 	iCachedSqlStatement->Reset();
       
   271 
       
   272 	// Pop it back off the cleanup stack, and hand over ownership
       
   273 	CleanupStack::Pop(viewContact);
       
   274 	return viewContact;
       
   275     }
       
   276 
       
   277 
       
   278 /**
       
   279 Clean up the cached prepare statement.
       
   280 */
       
   281 void CCntPplViewSession::CleanupCachedPrepareStatement()
       
   282     {
       
   283 	if(iCachedSqlStatement)
       
   284 		{
       
   285 		iCachedSqlStatement->Close();
       
   286 		delete iCachedSqlStatement;
       
   287 		iCachedSqlStatement = NULL;
       
   288 		}
       
   289     }
       
   290 
       
   291 /**
       
   292 CTimer callback funtion, the cached Prepare statement would be de-cached if ItemAtL is not called
       
   293 during the time interval defined by KCachedPrepareTimeOut.
       
   294 */
       
   295 void CCntPplViewSession::RunL()
       
   296 	{
       
   297 	CleanupCachedPrepareStatement();
       
   298 	}
       
   299 	
       
   300 	
       
   301 /**
       
   302 Create view contact object based on given sql statement.
       
   303 
       
   304 @return CViewContact object or NULL the contact is not found.
       
   305 */
       
   306 CViewContact* CCntPplViewSession::CreateViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs)
       
   307 	{
       
   308 	if (! iContactsFile.IsOpened())
       
   309 		{
       
   310 		User::Leave(KErrInUse);
       
   311 		}
       
   312 	
       
   313 	CViewContact* viewContact = InitialiseViewItemL(aSqlStmt, aCntSqlStmt, aViewPrefs);
       
   314 	if(!viewContact)
       
   315 		{
       
   316 		//Couldn't find the contact.
       
   317 		return NULL;
       
   318 		}
       
   319 	
       
   320 	CleanupStack::PushL(viewContact);
       
   321 	if(viewContact->ContactType() == CViewContact::EContactItem)
       
   322 		{
       
   323 		FillViewItemL(*viewContact, aSqlStmt, aViewPrefs);
       
   324 		}
       
   325 	
       
   326 	TUid typeUid = GetContactFieldMatchUid(*viewContact, aViewPrefs);	
       
   327 	if(typeUid != KUidContactFieldNone)
       
   328 		{
       
   329 		RSqlStatement contactSqlStmt;
       
   330 		CleanupClosePushL(contactSqlStmt);
       
   331 		
       
   332 		/* we have to reload the row from SQL database to cache in text header and text blob */ 	
       
   333 		contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(),  iSqlSmtSelectAllFieldsById.SqlStringL());
       
   334 		User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, viewContact->Id())); //Bind item id into the condition.	
       
   335 		
       
   336 		TInt err = contactSqlStmt.Next();
       
   337 		if(err == KSqlAtEnd)
       
   338 			{
       
   339 			//Should never be here, we found it in InitialiseViewItemL 
       
   340 			//but couldn't find the same contact in same database.
       
   341 			CleanupStack::PopAndDestroy(viewContact);
       
   342 			return NULL;
       
   343 			}			
       
   344 			
       
   345 		User::LeaveIfError(err);
       
   346 		
       
   347 		/* set first field with possible content for group or unsorted contact */	
       
   348 		CContactDatabase::TTextFieldMinimal buf;
       
   349 		TextFieldL(contactSqlStmt, iSqlSmtSelectAllFieldsById, iContactProperties.SystemTemplateL(), typeUid, buf);
       
   350 		viewContact->SetFirstFieldForBlankContactL(buf);
       
   351 		CleanupStack::PopAndDestroy(&contactSqlStmt);
       
   352 		} //if(typeUid != 0)
       
   353 	
       
   354 	CleanupStack::Pop(viewContact);
       
   355 	return viewContact;
       
   356 	}
       
   357 
       
   358 	
       
   359 /**
       
   360 Filling content for the given view contact object.
       
   361 
       
   362 @param aViewContact reference to the view contact object to be filled
       
   363 @param aSqlStmt the sql statement which contains the retrieved content for the view object. 
       
   364 */
       
   365 void CCntPplViewSession::FillViewItemL(CViewContact& aViewContact, RSqlStatement& aSqlStmt, const TContactViewPreferences& aViewPrefs)
       
   366 	{
       
   367 	if(iIsFastAccessFieldsOnly)
       
   368 		{
       
   369 		//The view gets fields only from fast access columns	
       
   370 		const TInt KTextDefCount = iTextDef->Count();
       
   371 		for(TInt index = 0; index < KTextDefCount; ++index)
       
   372 			{
       
   373 			const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(iTextDef->At(index).iFieldType.iUid);
       
   374 			ASSERT(KColumnName.Length() > 0);
       
   375 			
       
   376 			TPtrC fieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName));
       
   377    			AddFieldInViewContactL(aViewContact, fieldPtrC, aViewPrefs);
       
   378 			} //for
       
   379 		}
       
   380 	else
       
   381 		{
       
   382 		TBool searchFastAccessFields = EFalse;
       
   383 		
       
   384 		// iTextDef contains the fields that should be included in the view.
       
   385 		// The array of all the field objects in a contact item is returned from
       
   386 		// the Contacts table.  
       
   387 		RPointerArray<CContactItemField> fields;
       
   388 		CleanupStack::PushL(TCleanupItem(TCntPersistenceUtility::ResetAndDestroyRPointerArray, &fields));
       
   389 		
       
   390 		TPtrC8 textHeader;
       
   391 		aSqlStmt.ColumnBinary(iCntSqlStatement->ParameterIndex(KContactTextFieldHeader()), textHeader);
       
   392 		RDesReadStream textHeaderStream(textHeader);
       
   393 		CleanupClosePushL(textHeaderStream);
       
   394         CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream);
       
   395         
       
   396     	RStoreReadStream textHeaderStoreStream;
       
   397     	textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root());
       
   398         
       
   399 		TPtrC textFieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KContactTextFields()));
       
   400 		HBufC* textFieldsBuf = textFieldPtrC.AllocLC();
       
   401 			
       
   402 		TCntPersistenceUtility::ReadTextBlobL(textHeaderStoreStream, textFieldsBuf, *iTextDef, iContactProperties.SystemTemplateL(), fields, searchFastAccessFields);
       
   403 		CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf
       
   404 		
       
   405 		// Loop through fields, checking for fields from fast access fields, and add 
       
   406 		// the fields to the view contact object.
       
   407 		const TInt KFieldsNumMax = fields.Count();
       
   408 		for(TInt fieldsIndex = 0; fieldsIndex < KFieldsNumMax; ++fieldsIndex)
       
   409 			{
       
   410 			// this doesn't own the instance stored in fields array.
       
   411 			CContactItemField* itemField = fields[fieldsIndex];
       
   412 
       
   413 			if(itemField == NULL)
       
   414 				{
       
   415 				aViewContact.AddFieldL(KNullDesC);
       
   416 				continue;
       
   417 				}
       
   418 
       
   419 			// The array of fields retrieved from the text fields blob does not
       
   420 			// contain the text data Fast Access fields. If the searchFastAccessFields 
       
   421 			// flags have been set then get the data from Fast Access columns
       
   422 			// before adding the data to the view.
       
   423 			TPtrC fieldText;
       
   424 			if(searchFastAccessFields && itemField->ContentType().FieldTypeCount() > 0)
       
   425 				{
       
   426 				//Check the field name of the first field type(key field type) 
       
   427 				//in the field's field types array
       
   428     			const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(itemField->ContentType().FieldType(0).iUid);
       
   429 				if(KColumnName.Length() > 0)
       
   430 					{
       
   431 					//this is a fast access field.
       
   432 					fieldText.Set(aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName)));
       
   433 					}
       
   434 				else
       
   435 					{
       
   436 					fieldText.Set(itemField->TextStorage()->Text());
       
   437 					}					
       
   438 				}
       
   439 			else
       
   440 				{
       
   441 				fieldText.Set(itemField->TextStorage()->Text());
       
   442 				}
       
   443 			
       
   444 			AddFieldInViewContactL(aViewContact, fieldText, aViewPrefs);
       
   445 			}
       
   446 		
       
   447 		CleanupStack::PopAndDestroy(&fields);
       
   448 		}
       
   449 	}
       
   450 
       
   451 	
       
   452 /**
       
   453 Initialise requested view contact object based on given parameters:
       
   454  1. search the contact in contact table.
       
   455  2. fill in contact type and hint to the view contact object.
       
   456 
       
   457 @param aSqlStmt      reference to a RSqlStatement to be read in data 
       
   458 @return initialized CViewContact object or NULL if reached end of rows.
       
   459 */
       
   460 CViewContact* CCntPplViewSession::InitialiseViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs)
       
   461 	{
       
   462 	CViewContact* viewContact = NULL;
       
   463 	
       
   464     while(viewContact == NULL)
       
   465 	    {
       
   466     	TInt err = aSqlStmt.Next();
       
   467     	 
       
   468     	if(err == KSqlAtEnd)
       
   469     	    {
       
   470     	    return NULL;
       
   471     	    }
       
   472     	    
       
   473        	User::LeaveIfError(err);
       
   474        	
       
   475     	TInt typeFlags = aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactTypeFlags()));
       
   476     	TUid contactTypeUid = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags);
       
   477     	
       
   478         if(!ContactCorrectType(contactTypeUid, aViewPrefs))
       
   479             {
       
   480             //The contact type doesn't match the view prefreference
       
   481             continue;
       
   482             }
       
   483     	
       
   484     	viewContact = CViewContact::NewLC(KNullContactId);
       
   485     	
       
   486     	/* Got a row and add common fields for both Groups and Contact view items. */
       
   487     	viewContact->SetId(aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactId())));
       
   488     	viewContact->SetContactHint(TCntPersistenceUtility::TypeFlagsToHint(typeFlags));
       
   489     	viewContact->SetContactTypeUid(contactTypeUid);
       
   490     	
       
   491     	
       
   492     	if(contactTypeUid == KUidContactGroup)
       
   493     		{
       
   494     		// Groups don't require all the field types to be set.
       
   495     		viewContact->SetContactType(CViewContact::EGroup);
       
   496     		}
       
   497     	else
       
   498     		{
       
   499     		// All other contact types do require field types to be set.
       
   500     		viewContact->SetContactType(CViewContact::EContactItem);
       
   501     		}
       
   502 
       
   503     	CleanupStack::Pop(viewContact);		
       
   504 	    }
       
   505    	
       
   506 	return viewContact;    
       
   507 	}	
       
   508 
       
   509 	
       
   510 /**
       
   511 Check if the retrieved view contact is group or unsorted contact, if so return suitable field 
       
   512 match uid in order to fill in a possible text for the contact: 
       
   513 For group contact    -- find template label.
       
   514 For unsorted contact -- find first not none field.
       
   515 
       
   516 @param aViewContact     reference to the retrieved view contact object.
       
   517 @param aViewPreferences the view preferences made by client.
       
   518  
       
   519 @return suitable match uid or KUidContactFieldNone if it's not group or unsorted contact.
       
   520 */
       
   521 TUid CCntPplViewSession::GetContactFieldMatchUid(const CViewContact& aViewContact, const TContactViewPreferences& aViewPreferences)	
       
   522 	{
       
   523 	TUid typeUid = KUidContactFieldNone;
       
   524 	if(aViewContact.ContactType() == CViewContact::EGroup && (aViewPreferences & (EGroupsOnly | EContactAndGroups)))
       
   525 		{
       
   526 		// Check for group view contact type.  This type of view contact uses the
       
   527 		// template label field to populate the first view contact field.
       
   528 		typeUid = KUidContactFieldTemplateLabel;
       
   529 		}
       
   530 	else if(!aViewContact.IsSortable() && (aViewPreferences & (EIgnoreUnSorted | EUnSortedAtBeginning | EUnSortedAtEnd)) == 0)		
       
   531 		{
       
   532 		// None of the sort fields contained any data.  We want this contact to
       
   533 		// be sorted by the first bit of text we find so we need to retrieve the
       
   534 		// first text available from the contact and use this to populate the
       
   535 		// first view contact field.
       
   536 		typeUid = KUidContactFieldMatchAll;
       
   537 		}
       
   538 	return typeUid;	
       
   539 	}
       
   540 
       
   541 	
       
   542 /**
       
   543 Refine the field content and add the refined content to the given view contact object.
       
   544  
       
   545 @param aViewContact     reference to the retrieved view contact object.
       
   546 @param aFieldPtrC    	The actual field content read from database.
       
   547 @param aViewPreferences The view preferences for how to format the content. 
       
   548 */
       
   549 void CCntPplViewSession::AddFieldInViewContactL(CViewContact& aViewContact, TPtrC& aFieldPtrC, const TContactViewPreferences& aViewPreferences)
       
   550 	{
       
   551 	_LIT(KBlank," ");
       
   552 	
       
   553 	// Truncate to 64 if necessary.
       
   554 	TPtr ptr(const_cast<TUint16*>(aFieldPtrC.Ptr()), KTextFieldMinimalLength);
       
   555 	if(aFieldPtrC.Length() > KTextFieldMinimalLength) 
       
   556 		{
       
   557 		ptr.SetLength(KTextFieldMinimalLength); 
       
   558 		}
       
   559 	else
       
   560 		{
       
   561 		ptr.SetLength(aFieldPtrC.Length());
       
   562 		}
       
   563 		
       
   564 	// Add the field to the view.
       
   565 	if((ptr.Length() == 0) ||
       
   566 	   (ptr.Length() == 1 && (aViewPreferences & ESingleWhiteSpaceIsEmptyField) && ptr.Compare(KBlank)==KErrNone))
       
   567 		{
       
   568 		/* empty field */
       
   569 		aViewContact.AddFieldL(KNullDesC);
       
   570 		} 
       
   571 	else
       
   572 		{
       
   573 		aViewContact.AddFieldL(ptr);
       
   574 		}
       
   575 	}
       
   576 
       
   577 /** 
       
   578 Retrieve the field text for the given field type and contact item ID.
       
   579 
       
   580 The behaviour differs when a specific field type is not given i.e. when
       
   581 aFieldType is KUidContactFieldMatchAll:
       
   582 
       
   583 - First tries to find an email for the given contact item ID.
       
   584 - If there is no email then it retrieves the first entry in Fast Access fields
       
   585 for the given contact item ID.
       
   586 - If there is no Fast Access fields then it retrieves the first entry in the
       
   587 text fields blob for the given contact item ID.
       
   588 
       
   589 Text for all other field types are retrieved from the text fields blob.
       
   590 
       
   591 The caller must determine that the given contact item ID exists before calling
       
   592 this method.
       
   593 */
       
   594 void CCntPplViewSession::TextFieldL(RSqlStatement& aSqlStatement, const CCntSqlStatement& aCntSqlStmt, const CContactTemplate& aSystemTemplate, TFieldType aFieldType, TDes& aText)
       
   595 	{
       
   596 	TPtrC8 textHeader;
       
   597 	aSqlStatement.ColumnBinary(aCntSqlStmt.ParameterIndex(KContactTextFieldHeader()), textHeader);
       
   598 	RDesReadStream textHeaderStream(textHeader);
       
   599 	CleanupClosePushL(textHeaderStream);	
       
   600     CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream);
       
   601     
       
   602 	RStoreReadStream textHeaderStoreStream;
       
   603    	textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root());
       
   604 
       
   605 	TPtrC textFieldPtrC = aSqlStatement.ColumnTextL(aCntSqlStmt.ParameterIndex(KContactTextFields()));
       
   606 	HBufC* textFieldsBuf = textFieldPtrC.AllocLC();
       
   607 	
       
   608 	if(aFieldType == KUidContactFieldMatchAll)
       
   609 		{
       
   610 		if (TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText) == EFalse)
       
   611 			{
       
   612 			CContactDatabase::TTextFieldMinimal	fastAccessText;
       
   613 			if (HasTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, fastAccessText))
       
   614 				{
       
   615 				aText.Copy(fastAccessText);		
       
   616 				}
       
   617 			}
       
   618 		} 
       
   619 	else
       
   620 		{
       
   621 		if (SpecificTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, aFieldType, aText) == EFalse)
       
   622 			{
       
   623 			TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText);
       
   624 			}
       
   625 		}
       
   626 		
       
   627 	CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf
       
   628 	}
       
   629 
       
   630 
       
   631 /**
       
   632 The first text field in the Fast Access fields is found and returned via the
       
   633 parameter aText.
       
   634 
       
   635 @param aCntItemId The contact ID for which the first text field is required.
       
   636 @param aText On return contains the text for the field of the first Identity
       
   637 text field.
       
   638 
       
   639 @return ETrue if a Fast Access text field was found, EFalse otherwise.
       
   640 */
       
   641 TBool CCntPplViewSession::HasTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, TDes& aText)
       
   642 	{
       
   643 	for(TInt ii = EGivenName; ii <= ECompanyNamePrn; ++ii)
       
   644 		{
       
   645 		const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(KFastAccessFieldUids[ii]);
       
   646 		TPtrC identText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
       
   647 		if(identText.Length() > 0)
       
   648 			{
       
   649 			TCntPersistenceUtility::CopyMinFieldText(identText, aText);
       
   650 			return ETrue;
       
   651 			}
       
   652 		}
       
   653 	return EFalse;
       
   654 	}
       
   655 
       
   656 	
       
   657 /**
       
   658 Checks if the given field type is in the Fast Access fields and if so the field text
       
   659 is returned via the parameter aText.
       
   660 
       
   661 @param aCntItemId The contact ID for which the specific text field is required.
       
   662 @param aText On return contains the field text for the first Fast Access fields
       
   663 with field type aFieldType.
       
   664 @param aFieldType The specific field requested.
       
   665 
       
   666 @return ETrue if the specific fast access text field was found, EFalse otherwise.
       
   667 */
       
   668 TBool CCntPplViewSession::SpecificTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, const TFieldType aFieldType, TDes& aText)
       
   669 	{
       
   670     const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(aFieldType.iUid);
       
   671 	if(KColumnName.Length() > 0)
       
   672 		{
       
   673 		// This is a fast access field.
       
   674 		TPtrC fastAccessText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
       
   675 		TCntPersistenceUtility::CopyMinFieldText(fastAccessText, aText);
       
   676 		return ETrue;
       
   677 		}
       
   678 	return EFalse;
       
   679 	}
       
   680 
       
   681 	
       
   682 /**
       
   683 Get view session id
       
   684 
       
   685 @return the view session id assigned to the session.
       
   686 */
       
   687 TInt CCntPplViewSession::ViewId() const
       
   688 	{
       
   689 	return iViewId;
       
   690 	}
       
   691 
       
   692 
       
   693 TBool CCntPplViewSession::ContactCorrectType(TUid aContactTypeUid, TContactViewPreferences aTypeToInclude)
       
   694 	{
       
   695 	TBool correctType(EFalse);
       
   696 	if (aContactTypeUid==KUidContactCard || aContactTypeUid==KUidContactOwnCard)
       
   697 		{
       
   698 		// Ignore Unsorted Contacts flags & White Space flag
       
   699 		// catch non- contact views
       
   700 		// Should be EContactsOnly, EContactAndGroups & EICCEntriesAndContacts
       
   701 		if (0 == ((aTypeToInclude & ~(ESingleWhiteSpaceIsEmptyField | EIgnoreUnSorted | EUnSortedAtBeginning | EUnSortedAtEnd))
       
   702 				& (EGroupsOnly | EICCEntriesOnly))) // Ignore 'UnSorted' flags, exclude Groups Only & ICC Only 
       
   703 			{
       
   704 			correctType = ETrue;
       
   705 			}
       
   706 		}
       
   707 	else if (aContactTypeUid == KUidContactGroup)
       
   708 		{
       
   709 		if (aTypeToInclude & (EGroupsOnly | EContactAndGroups))
       
   710 			{
       
   711 			correctType = ETrue;
       
   712 			}
       
   713 		}
       
   714 	else if (aContactTypeUid == KUidContactICCEntry)
       
   715 		{
       
   716 		if (aTypeToInclude & (EICCEntriesOnly | EICCEntriesAndContacts))
       
   717 			{
       
   718 			correctType = ETrue;
       
   719 			}
       
   720 		}
       
   721 	return correctType;
       
   722 	}
       
   723 
       
   724