phonebookengines/contactsmodel/cntplsql/src/cntpplviewmanager.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntplsql/src/cntpplviewmanager.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,396 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#include "cntpplviewmanager.h"
+#include "cntsqlprovider.h"
+#include "dbsqlconstants.h"
+#include "cntpersistenceutility.h"
+
+const TInt KViewSessionsGranularity = 4;
+
+
+/**
+Object factory method.
+*/
+CCntPplViewManager* CCntPplViewManager::NewL(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties)
+	{
+	CCntPplViewManager* manager = new (ELeave) CCntPplViewManager(aContactsFile, aContactProperties);
+	CleanupStack::PushL(manager);
+	manager->ConstructL();
+	CleanupStack::Pop(manager);
+	return manager;
+	}
+
+	
+/**
+CCntPplViewManager first phase constructor.
+*/
+CCntPplViewManager::CCntPplViewManager(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties)
+:  	iContactsFile(aContactsFile),
+	iContactProperties(aContactProperties),
+	iNextViewId(KPLViewSessionIdNull + 1),
+	iViewSessions(KViewSessionsGranularity)
+	{
+	}
+
+	
+/**
+CCntPplViewManager destructor.
+*/
+CCntPplViewManager::~CCntPplViewManager()
+	{
+	iViewSessions.ResetAndDestroy();
+	delete iSelectFullFieldsStmt;
+	}
+
+
+/**
+CCntPplViewManager second phase constructor.
+*/
+void CCntPplViewManager::ConstructL()
+	{
+	/* 
+	Construct select statement:
+	"SELECT contact_id, type_flags, first_name, last_name, company_name, firstname_prn, 
+			lastname_prn, companyname_prn, text_fields_header, text_fields 
+     FROM contact WHERE contact_id == :SeekId"
+	*/
+	TCntSqlStatementType statementType(ESelect, KSqlContactTableName);
+	iSelectFullFieldsStmt = TSqlProvider::GetSqlStatementL(statementType);
+
+	// To select id, type flags, and all fast access fields.	
+	iSelectFullFieldsStmt->SetParamL(KContactId(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactTypeFlags(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactFirstName(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactLastName(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactCompanyName(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactFirstNamePrn(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactLastNamePrn(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactCompanyNamePrn(), KSpace());
+	
+	// Also select text header, and text blob
+	iSelectFullFieldsStmt->SetParamL(KContactTextFieldHeader(), KSpace());
+	iSelectFullFieldsStmt->SetParamL(KContactTextFields(), KSpace());
+	
+	// Add selecting condition
+	HBufC* condition = HBufC::NewLC(KSelectCondition_SearchForEqual().Length() + KContactId().Length());
+	TPtr ptrCondition = condition->Des();
+	ptrCondition.Format(KSelectCondition_SearchForEqual(), &KContactId);
+		
+	iSelectFullFieldsStmt->SetConditionL(ptrCondition);
+	
+	CleanupStack::PopAndDestroy(condition);
+	}
+
+	
+/**
+Create a new view session which is mapping to a local view.
+
+@param aTextDef the text definition for the view
+@param aViewPrefs the view preferences for the view.
+@return the view session id created for the local view.
+*/
+TInt CCntPplViewManager::OpenViewL(const CContactTextDef& aTextDef, const TContactViewPreferences aViewPrefs)
+	{
+	CCntPplViewSession* viewSession = CCntPplViewSession::NewL(iContactsFile, 
+			iContactProperties, *iSelectFullFieldsStmt, iNextViewId, aTextDef, aViewPrefs);	
+	CleanupStack::PushL(viewSession);
+	iViewSessions.AppendL(viewSession);
+	CleanupStack::Pop(viewSession);
+
+	//there is no relationship between the iViewSessions index (subscript) and iNextViewId
+	return iNextViewId++;
+	}
+
+	
+/**
+Close a view session.
+
+@param aViewId the id of the view session to be closed
+*/
+void CCntPplViewManager::CloseView(TInt aViewId)
+	{
+	TInt index = FindViewSessionIndexById(aViewId);
+	if(index != KErrNotFound)
+		{
+		CCntPplViewSession* viewSession = iViewSessions[index];
+		iViewSessions.Remove(index);
+		delete viewSession;	
+		}
+	}
+
+
+/**
+Change a sort order for a view session.
+
+@param aViewId the id of the view session
+@param aTextDef the new sort order/text definition.
+*/
+void CCntPplViewManager::ChangeSortOrderL(TInt aViewId, const CContactTextDef& aTextDef)
+	{
+	FindViewSessionByIdL(aViewId)->ChangeSortOrderL(aTextDef);
+	}
+	
+	
+/**
+Start iteration in a view session.
+
+@param aViewId the id of the view session
+*/
+void CCntPplViewManager::BeginIterateL(TInt aViewId)
+	{
+	FindViewSessionByIdL(aViewId)->BeginIterateL();
+	}
+
+	
+/**
+End iteration in a view session.
+
+@param aViewId the id of the view session
+*/
+void CCntPplViewManager::EndIterateL(TInt aViewId)
+	{
+	FindViewSessionByIdL(aViewId)->EndIterate();
+	}
+
+	
+/**
+Get next view item in a view session.
+
+@param aViewId the id of the view session
+@return the view item got from the database
+@leave KErrNotFound if iterator reachs the end of rows.
+*/
+CViewContact* CCntPplViewManager::NextItemL(TInt aViewId, TContactViewPreferences aViewPrefs)
+	{
+	return FindViewSessionByIdL(aViewId)->NextItemL(aViewPrefs);
+	}
+
+	
+/**
+Get view item by given contact id in a view session.
+
+@param aViewId the id of the view session
+@return the view item got from the database
+@leave KErrNotFound if there is not the row.
+*/
+CViewContact* CCntPplViewManager::ItemAtL(TContactItemId aContactId, TInt aViewId)
+	{
+	return FindViewSessionByIdL(aViewId)->ItemAtL(aContactId);
+	}
+
+	
+/**
+Find a view session by given view session id.
+
+@param aViewId the id of the view session
+@return the view session
+@leave KErrArgument if there is not such a view session.
+*/
+CCntPplViewSession* CCntPplViewManager::FindViewSessionByIdL(TInt aViewId) const
+	{
+	ASSERT(aViewId >= 0);
+	TInt index = FindViewSessionIndexById(aViewId);
+	if(index == KErrNotFound)
+	    {
+		User::Leave(KErrNotFound);
+	    }
+	    
+	return iViewSessions[index];
+	}	
+
+	
+/**
+Find a view session by given view session id.
+
+@param aViewId the id of the view session
+@return the index of view session stored in view session array
+        KNotFoundIndex if there is not such a view session.
+*/
+TInt CCntPplViewManager::FindViewSessionIndexById(TInt aViewId) const 
+	{
+	TInt index = KErrNotFound;
+	TInt count = iViewSessions.Count();
+	for(TInt i = 0; i < count; ++i)
+		{
+		ASSERT(iViewSessions[i] != NULL);
+		if(aViewId == iViewSessions[i]->ViewId())
+			{		
+			index = i;
+			break;
+			}
+		}
+	return index;	
+	}	
+
+
+/**
+CContactDatabase::ReadContactTextDefL() uses a text definition - a way of 
+grouping fields to form a string which represents a contact item - to
+build up a string from a contact item.
+
+When creating the string, the contact item is searched for fields whose type 
+matches one of the fields specified in the text definition.
+
+The contents of the first matching field of each type found in the
+item are read into the string.
+
+These strings may be separated using a field separator, which is also specified 
+in the text definition.  A separator is not appended to the last field used to 
+make up the string.  It is only inserted when there is a following non-empty
+field.
+
+@param aContactId The contact ID for which the text definition is required.
+@param aResult The string representing the contact item. 
+@param aTextDef The text definition which contains the fields that are read 
+and returned in the aResult string.
+
+@return the contact type uid for the specified contact.				  
+*/
+TUid CCntPplViewManager::ReadContactTextDefL(TContactItemId aContactId, TDes &aResult,const CContactTextDef& aTextDef)
+    {
+    if (! iContactsFile.IsOpened())
+    	{
+    	User::Leave(KErrInUse);
+    	}
+    
+	RSqlStatement contactSqlStmt;
+	CleanupClosePushL(contactSqlStmt);
+	
+	/* we have to reload the row from SQL database to cache in text header and text blob */ 	
+	contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(), iSelectFullFieldsStmt->SqlStringL());
+	User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, aContactId)); //Bind item id into the condition.	
+	
+	TInt err = contactSqlStmt.Next();
+	if(err == KSqlAtEnd)
+		{
+		//couldn't find the contact
+		err = KErrNotFound;
+		}			
+		
+	User::LeaveIfError(err);
+	
+	TInt typeFlags = contactSqlStmt.ColumnInt(iSelectFullFieldsStmt->ParameterIndex(KContactTypeFlags()));
+	TUid contactTypeUid = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags);
+	TInt attr = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; 
+	
+	if((attr & EContactAttrsFlags_Deleted) == 0) 
+		{
+		//Only read text def for not deleted contact.
+    	TBuf<KMaxContactTextSeperator> nextSeperator;
+    	TContactTextDefItem textDefItem;
+    	
+    	// Mark the first iteration in the loop.
+    	TBool firstText = ETrue;
+
+    	TInt max = aTextDef.Count();
+     	for(TInt i=0; i<max; ++i)
+    		{
+    		// Recreate the TTextFieldMinimal on each iteration.
+    		CContactDatabase::TTextFieldMinimal textFieldMin;
+    		textDefItem = aTextDef[i];
+    		// Populate the TTextFieldMinimal.
+    		CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), textDefItem.iFieldType, textFieldMin);
+    		// Append the returned text.
+    		if (textFieldMin.Length() > 0)
+    			{
+    			// Only add a seperator after the first text has been appended.
+    			if ((firstText == EFalse) && (aResult.MaxLength() > aResult.Length()))
+    				{
+    				aResult.Append(nextSeperator.Left(Min(aResult.MaxLength() - aResult.Length(), nextSeperator.Length())));	
+    				}
+    			aResult.Append(textFieldMin.Left(Min(aResult.MaxLength() - aResult.Length(),textFieldMin.Length())));
+    			firstText = EFalse; 
+    			}
+    		nextSeperator = textDefItem.iSeperator;
+    		}
+    	
+    	// Add the best match if it was requested.
+    	if(aResult.Length() == 0 && const_cast<CContactTextDef&>(aTextDef).ExactMatchOnly() == EFalse)
+    		{
+    		CContactDatabase::TTextFieldMinimal textFieldMin;
+    		if (aTextDef.FallbackField() != KUidContactFieldNone) 
+    			{
+    			CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), aTextDef.FallbackField(), textFieldMin);
+    			}
+    		if(textFieldMin.Length() == 0) // No results from call to TextFieldL()?
+    			{
+    			CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), KUidContactFieldMatchAll, textFieldMin);
+    			}
+    		aResult.Append(textFieldMin.Left(Min(aResult.MaxLength(),textFieldMin.Length())));
+    		}
+		} //if((attr & EContactAttrsFlags_Deleted) != 0) 
+	
+	CleanupStack::PopAndDestroy(&contactSqlStmt);
+	
+	return contactTypeUid;
+    }
+
+
+/** 
+Retrieve the field text for the given field type and contact item ID.
+
+The behaviour differs when a specific field type is not given i.e. when
+aFieldType is KUidContactFieldMatchAll:
+
+- First tries to find an email for the given contact item ID.
+- If there is no email then it retrieves the first entry in Fast Access fields
+for the given contact item ID.
+- If there is no Fast Access fields then it retrieves the first entry in the
+text fields blob for the given contact item ID.
+
+Text for all other field types are retrieved from the text fields blob.
+
+The caller must determine that the given contact item ID exists before calling
+this method.
+
+@param aContactId The contact ID for which the field text is required.
+@param aFieldType the field type to determine what kind of text client required. 
+@param aText the reference to the buffer of final found field text.
+*/
+void CCntPplViewManager::TextFieldL(TInt aContactId, TFieldType aFieldType, TDes& aText)
+    {
+    if (! iContactsFile.IsOpened())
+    	{
+    	User::Leave(KErrInUse);
+    	}
+    
+	RSqlStatement contactSqlStmt;
+	CleanupClosePushL(contactSqlStmt);
+	
+	/* we have to reload the row from SQL database to cache in text header and text blob */ 	
+	contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(), iSelectFullFieldsStmt->SqlStringL());
+	User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, aContactId)); //Bind item id into the condition.	
+	
+	TInt err = contactSqlStmt.Next();
+	if(err == KSqlAtEnd)
+		{
+		//couldn't find the contact
+		err = KErrNotFound;
+		}			
+		
+	User::LeaveIfError(err);
+	
+    CCntPplViewSession::TextFieldL(contactSqlStmt, *iSelectFullFieldsStmt, iContactProperties.SystemTemplateL(), aFieldType, aText);    
+    
+	CleanupStack::PopAndDestroy(&contactSqlStmt);
+    }
+