phonebookengines/contactsmodel/cntview/ConcView.cpp
changeset 0 e686773b3f54
child 24 0ba2181d7c28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntview/ConcView.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,376 @@
+// Copyright (c) 2001-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:
+//
+
+#include <cntview.h>
+#include "CNTSTD.H"
+
+//#define CNTVIEW_API_PROFILING
+
+
+//
+// CContactConcatenatedView.
+//
+
+CContactConcatenatedView::~CContactConcatenatedView()
+	{
+	CloseComponentViews();
+	}
+
+CContactConcatenatedView::CContactConcatenatedView(const CContactDatabase& aDb) : CContactViewBase(aDb)
+	{
+	}
+
+EXPORT_C CContactConcatenatedView* CContactConcatenatedView::NewL(MContactViewObserver& aObserver,const CContactDatabase& aDb,RPointerArray<CContactViewBase>& aComponentViews)
+/** Allocates and constructs a new CContactConcatenatedView object,
+
+@param aObserver An observer that receives notifications when this view is 
+ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
+event when the view is ready. An attempt to use the view before this notification 
+causes a panic.
+@param aDb The database that contains the contact items.
+@param aComponentViews An array of pointers to the component views to append 
+to this view. The concatenated view creates its own copy of this array and 
+sets itself to be the observer of each of the component views, unless an error 
+occurs, in which case the function leaves.
+@return The newly constructed concatenated view object. */
+	{
+#ifdef CNTVIEW_API_PROFILING
+	RDebug::Print(_L("[CNTMODEL] CContactConcatenatedView::NewL()\n"));
+#endif
+	CContactConcatenatedView* self=new(ELeave) CContactConcatenatedView(aDb);
+	CleanupStack::PushL(self);
+	self->ConstructL(aObserver,aComponentViews);
+	CleanupStack::Pop(); // self.
+	return self;
+	}
+
+/*
+ * This is a reserved virtual exported function that is used for BC proofing 
+ * against present and future additions of new exported virtual functions.
+ @return Any return values of the helper functions called from this function or NULL.
+ */
+TAny* CContactConcatenatedView::CContactViewBase_Reserved_1(TFunction aFunction,TAny* aParams)
+	{
+	return CContactViewBase::CContactViewBase_Reserved_1(aFunction,aParams);
+	}
+void CContactConcatenatedView::ConstructL(MContactViewObserver& aObserver,RPointerArray<CContactViewBase>& aComponentViews)
+	{
+	CContactViewBase::ConstructL();
+	OpenL(aObserver);
+	CopyComponentViewsL(aComponentViews);
+	OpenComponentViewsL();
+	}
+
+void CContactConcatenatedView::CopyComponentViewsL(RPointerArray<CContactViewBase>& aComponentViews)
+	{
+	const TInt numComponentViews=aComponentViews.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		User::LeaveIfError(iComponentView.Append(TComponentView(*aComponentViews[ii],EInitializing)));
+		}
+	}
+
+void CContactConcatenatedView::OpenComponentViewsL()
+	{
+	TInt err=KErrNone;
+	const TInt numComponentViews=iComponentView.Count();
+	TInt ii;
+	for (ii=0;ii<numComponentViews;++ii)
+		{
+		err=iComponentView[ii].iView.Open(*this);
+		if (err)
+			{
+			goto cleanup;
+			}
+		}
+	return;
+
+cleanup:
+	for (TInt jj=0;jj<ii;++jj)
+		{
+		iComponentView[jj].iView.Close(*this);
+		}
+	User::Leave(err);
+	}
+
+void CContactConcatenatedView::CloseComponentViews()
+	{
+	const TInt numComponentViews=iComponentView.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		iComponentView[ii].iView.Close(*this);
+		}
+	iComponentView.Close();
+	}
+
+TBool CContactConcatenatedView::ComponentViewsReady()
+	{
+	const TInt numComponentViews=iComponentView.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		if (iComponentView[ii].iState!=EReady)
+			{
+			return EFalse;
+			}
+		}
+	return ETrue;
+	}
+
+void CContactConcatenatedView::SetComponentViewReady(const CContactViewBase& aView)
+	{
+	iComponentView[FindComponentView(aView)].iState=EReady;
+	}
+
+TBool CContactConcatenatedView::ComponentViewsEqual(const TComponentView& aFirst,const TComponentView& aSecond)
+	{
+	if (&aFirst.iView==&aSecond.iView)
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+TInt CContactConcatenatedView::FindComponentView(const CContactViewBase& aView)
+	{
+	TComponentView view(CONST_CAST(CContactViewBase&,aView),EReady); // Note, find ignores TComponentView::iState.
+	TInt index=iComponentView.Find(view,TIdentityRelation<TComponentView>(ComponentViewsEqual));
+	__ASSERT_DEBUG(index!=KErrNotFound,Panic(ECntPanicComponentViewNotFound));
+	return index;
+	}
+
+TContactItemId CContactConcatenatedView::AtL(TInt aIndex) const
+/** Gets the contact item ID at the specified index into the concatenated view.
+
+@param aIndex Index into the concatenated view.
+@leave KErrNotReady The view is not ready for use.
+@leave KErrNotFound The index is out of bounds. It must be less than the 
+total number of items in all component views.
+@return The contact item ID. 
+*/
+	{
+	if (iState != EReady)
+		{
+		User::Leave(KErrNotReady);
+		}
+	TInt count=0;
+	const TInt numComponentViews=iComponentView.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		const TInt thisCount=iComponentView[ii].iView.CountL();
+		if (aIndex<(count+thisCount))
+			{
+			return iComponentView[ii].iView.AtL(aIndex-count);
+			}
+		count+=thisCount;
+		}
+	//Out of Bounds 
+	User::Leave(KErrNotFound);
+	return KErrNotFound;
+	}
+
+
+const CViewContact& CContactConcatenatedView::ContactAtL(TInt aIndex) const
+/** Gets the contact item at the specified index into the view.
+
+@param aIndex Index into the view.
+@leave KErrNotReady The view is not ready for use. 
+@leave KErrNotFound The index is invalid. It must be less that the total 
+number of items in the concatenated view.
+@return The contact item. 
+*/
+	{
+	if (iState != EReady)
+		{
+		User::Leave(KErrNotReady);
+		}
+	TInt count=0;
+	const TInt numComponentViews=iComponentView.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		const TInt thisCount=iComponentView[ii].iView.CountL();
+		if (aIndex<(count+thisCount))
+			{
+			return iComponentView[ii].iView.ContactAtL(aIndex-count);
+			}
+		count+=thisCount;
+		}
+	//Out of Bounds 
+	User::Leave(KErrNotFound);
+	// the following code is never executed and is purely to stop the compiler warnings
+	const CViewContact* nullContact=NULL;
+	return *nullContact;
+	}
+
+TInt CContactConcatenatedView::CountL() const
+/** Gets the number of contact items in the concatenated view.
+
+This is the total number of items in all component views.
+@leave KErrNotReady The view is not ready for use.
+@return The number of items in the concatenated view. 
+*/
+	{
+	if (iState != EReady)
+		{
+		User::Leave(KErrNotReady);
+		}
+	TInt count=0;
+	const TInt numComponentViews=iComponentView.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		count+=iComponentView[ii].iView.CountL();
+		}
+	return count;
+	}
+
+TInt CContactConcatenatedView::FindL(TContactItemId aId) const
+/** Finds the index into the concatenated view of the specified contact item.
+
+@param aId The contact item ID to search for.
+@leave KErrNotReady The view is not ready for use.
+@return The index of the first matching item in the concatenated view or KErrNotFound 
+if no matching item can be found. 
+*/
+	{
+	if (iState != EReady)
+		{
+		User::Leave(KErrNotReady);
+		}
+	TInt count=0;
+	const TInt numComponentViews=iComponentView.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		TInt index=iComponentView[ii].iView.FindL(aId);
+		if (index!=KErrNotFound)
+			{
+			return count+index;
+			}
+		count+=iComponentView[ii].iView.CountL();
+		}
+	return KErrNotFound;
+	}
+
+HBufC* CContactConcatenatedView::AllFieldsLC(TInt aIndex,const TDesC& aSeparator) const
+/** Returns a descriptor containing the contents of all fields in an item in the 
+view.
+
+The fields are separated by aSeparator.
+
+@param aIndex The index into the view of the contact item.
+@param aSeparator The string to use to separate the fields.
+@leave KErrNotReady The view is not ready for use.
+@return Pointer to the contact item descriptor.
+@panic CNTMODEL 29 In debug builds, this indicates that the index is invalid. 
+It must be less that the total number of items in the concatenated view. 
+In release builds, a NULL pointer is returned instead. 
+*/
+	{
+	if (iState != EReady)
+		{
+		User::Leave(KErrNotReady);
+		}
+	TInt count=0;
+	const TInt numComponentViews=iComponentView.Count();
+	for (TInt ii=0;ii<numComponentViews;++ii)
+		{
+		count+=iComponentView[ii].iView.CountL();
+		if (aIndex<count)
+			{
+			return iComponentView[ii].iView.AllFieldsLC(aIndex-count,aSeparator);
+			}
+		}
+	__ASSERT_DEBUG(EFalse,Panic(ECntPanicInvalidIndexForConcatenatedView));
+	return NULL;	
+	}
+
+
+void CContactConcatenatedView::HandleContactViewEvent(const CContactViewBase& aView,const TContactViewEvent& aEvent)
+	{
+	TBool passOnNotification=ETrue;
+	TContactViewEvent event=aEvent;
+	
+	TInt err;
+
+	switch (event.iEventType)
+		{
+		case TContactViewEvent::ESortError:
+		case TContactViewEvent::EServerError:
+		case TContactViewEvent::EUnavailable:
+			iState=ENotReady;
+			break;
+		case TContactViewEvent::EReady:
+			SetComponentViewReady(aView);
+			if (ComponentViewsReady()) // Need to wait for all views to be ready before changing state.
+				{
+				iState=EReady;
+				}
+			else
+				{
+				passOnNotification=EFalse;
+				}
+			break;
+		case TContactViewEvent::ESortOrderChanged:
+			iState=EReady;
+			break;
+		case TContactViewEvent::EItemAdded:
+		case TContactViewEvent::EItemRemoved:
+			TRAP(err,event.iInt+=OffsetL(aView));
+			if (err != KErrNone)
+				{
+				NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,err));
+				passOnNotification = EFalse;
+				}
+			break;
+		case TContactViewEvent::EGroupChanged:
+			break;
+		default:
+			ASSERT(EFalse);
+		}
+
+	if (passOnNotification)
+		{
+		NotifyObservers(event);
+		}
+	}
+
+TInt CContactConcatenatedView::OffsetL(const CContactViewBase& aView)
+	{
+	const TInt eventOwningViewIndex=FindComponentView(aView);
+	TInt offset=0;
+	for (TInt ii=0;ii<eventOwningViewIndex;++ii)
+		{
+		offset+=iComponentView[ii].iView.CountL();
+		}
+	return offset;
+	}
+
+TContactViewPreferences CContactConcatenatedView::ContactViewPreferences()
+/** Gets the view preferences for the first component view.
+@return The view preferences. 
+*/
+	{
+	return iComponentView[0].iView.ContactViewPreferences();
+	}
+
+const RContactViewSortOrder& CContactConcatenatedView::SortOrderL() const
+/** Gets the sort order for the first component view.
+
+@return The sort order. */
+	{
+	return iComponentView[0].iView.SortOrderL();
+	}
+
+CContactConcatenatedView::TComponentView::TComponentView(CContactViewBase& aView,TState aState) : iView(aView),iState(aState) 
+	{
+	}