plugins/contacts/symbian/contactsmodel/cntview/concview.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /*
       
     2 * Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <cntview.h>
       
    20 #include "cntstd.h"
       
    21 
       
    22 //#define CNTVIEW_API_PROFILING
       
    23 
       
    24 
       
    25 //
       
    26 // CContactConcatenatedView.
       
    27 //
       
    28 
       
    29 CContactConcatenatedView::~CContactConcatenatedView()
       
    30 	{
       
    31 	CloseComponentViews();
       
    32 	}
       
    33 
       
    34 CContactConcatenatedView::CContactConcatenatedView(const CContactDatabase& aDb) : CContactViewBase(aDb)
       
    35 	{
       
    36 	}
       
    37 
       
    38 EXPORT_C CContactConcatenatedView* CContactConcatenatedView::NewL(MContactViewObserver& aObserver,const CContactDatabase& aDb,RPointerArray<CContactViewBase>& aComponentViews)
       
    39 /** Allocates and constructs a new CContactConcatenatedView object,
       
    40 
       
    41 @param aObserver An observer that receives notifications when this view is 
       
    42 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady 
       
    43 event when the view is ready. An attempt to use the view before this notification 
       
    44 causes a panic.
       
    45 @param aDb The database that contains the contact items.
       
    46 @param aComponentViews An array of pointers to the component views to append 
       
    47 to this view. The concatenated view creates its own copy of this array and 
       
    48 sets itself to be the observer of each of the component views, unless an error 
       
    49 occurs, in which case the function leaves.
       
    50 @return The newly constructed concatenated view object. */
       
    51 	{
       
    52 #ifdef CNTVIEW_API_PROFILING
       
    53 	RDebug::Print(_L("[CNTMODEL] CContactConcatenatedView::NewL()\n"));
       
    54 #endif
       
    55 	CContactConcatenatedView* self=new(ELeave) CContactConcatenatedView(aDb);
       
    56 	CleanupStack::PushL(self);
       
    57 	self->ConstructL(aObserver,aComponentViews);
       
    58 	CleanupStack::Pop(); // self.
       
    59 	return self;
       
    60 	}
       
    61 
       
    62 /*
       
    63  * This is a reserved virtual exported function that is used for BC proofing 
       
    64  * against present and future additions of new exported virtual functions.
       
    65  @return Any return values of the helper functions called from this function or NULL.
       
    66  */
       
    67 TAny* CContactConcatenatedView::CContactViewBase_Reserved_1(TFunction aFunction,TAny* aParams)
       
    68 	{
       
    69 	return CContactViewBase::CContactViewBase_Reserved_1(aFunction,aParams);
       
    70 	}
       
    71 void CContactConcatenatedView::ConstructL(MContactViewObserver& aObserver,RPointerArray<CContactViewBase>& aComponentViews)
       
    72 	{
       
    73 	CContactViewBase::ConstructL();
       
    74 	OpenL(aObserver);
       
    75 	CopyComponentViewsL(aComponentViews);
       
    76 	OpenComponentViewsL();
       
    77 	}
       
    78 
       
    79 void CContactConcatenatedView::CopyComponentViewsL(RPointerArray<CContactViewBase>& aComponentViews)
       
    80 	{
       
    81 	const TInt numComponentViews=aComponentViews.Count();
       
    82 	for (TInt ii=0;ii<numComponentViews;++ii)
       
    83 		{
       
    84 		User::LeaveIfError(iComponentView.Append(TComponentView(*aComponentViews[ii],EInitializing)));
       
    85 		}
       
    86 	}
       
    87 
       
    88 void CContactConcatenatedView::OpenComponentViewsL()
       
    89 	{
       
    90 	TInt err=KErrNone;
       
    91 	const TInt numComponentViews=iComponentView.Count();
       
    92 	TInt ii;
       
    93 	for (ii=0;ii<numComponentViews;++ii)
       
    94 		{
       
    95 		err=iComponentView[ii].iView.Open(*this);
       
    96 		if (err)
       
    97 			{
       
    98 			goto cleanup;
       
    99 			}
       
   100 		}
       
   101 	return;
       
   102 
       
   103 cleanup:
       
   104 	for (TInt jj=0;jj<ii;++jj)
       
   105 		{
       
   106 		iComponentView[jj].iView.Close(*this);
       
   107 		}
       
   108 	User::Leave(err);
       
   109 	}
       
   110 
       
   111 void CContactConcatenatedView::CloseComponentViews()
       
   112 	{
       
   113 	const TInt numComponentViews=iComponentView.Count();
       
   114 	for (TInt ii=0;ii<numComponentViews;++ii)
       
   115 		{
       
   116 		iComponentView[ii].iView.Close(*this);
       
   117 		}
       
   118 	iComponentView.Close();
       
   119 	}
       
   120 
       
   121 TBool CContactConcatenatedView::ComponentViewsReady()
       
   122 	{
       
   123 	const TInt numComponentViews=iComponentView.Count();
       
   124 	for (TInt ii=0;ii<numComponentViews;++ii)
       
   125 		{
       
   126 		if (iComponentView[ii].iState!=EReady)
       
   127 			{
       
   128 			return EFalse;
       
   129 			}
       
   130 		}
       
   131 	return ETrue;
       
   132 	}
       
   133 
       
   134 void CContactConcatenatedView::SetComponentViewReady(const CContactViewBase& aView)
       
   135 	{
       
   136 	iComponentView[FindComponentView(aView)].iState=EReady;
       
   137 	}
       
   138 
       
   139 TBool CContactConcatenatedView::ComponentViewsEqual(const TComponentView& aFirst,const TComponentView& aSecond)
       
   140 	{
       
   141 	if (&aFirst.iView==&aSecond.iView)
       
   142 		{
       
   143 		return ETrue;
       
   144 		}
       
   145 	return EFalse;
       
   146 	}
       
   147 
       
   148 TInt CContactConcatenatedView::FindComponentView(const CContactViewBase& aView)
       
   149 	{
       
   150 	TComponentView view(CONST_CAST(CContactViewBase&,aView),EReady); // Note, find ignores TComponentView::iState.
       
   151 	TInt index=iComponentView.Find(view,TIdentityRelation<TComponentView>(ComponentViewsEqual));
       
   152 	__ASSERT_DEBUG(index!=KErrNotFound,Panic(ECntPanicComponentViewNotFound));
       
   153 	return index;
       
   154 	}
       
   155 
       
   156 TContactItemId CContactConcatenatedView::AtL(TInt aIndex) const
       
   157 /** Gets the contact item ID at the specified index into the concatenated view.
       
   158 
       
   159 @param aIndex Index into the concatenated view.
       
   160 @leave KErrNotReady The view is not ready for use.
       
   161 @leave KErrNotFound The index is out of bounds. It must be less than the 
       
   162 total number of items in all component views.
       
   163 @return The contact item ID. 
       
   164 */
       
   165 	{
       
   166 	if (iState != EReady)
       
   167 		{
       
   168 		User::Leave(KErrNotReady);
       
   169 		}
       
   170 	TInt count=0;
       
   171 	const TInt numComponentViews=iComponentView.Count();
       
   172 	for (TInt ii=0;ii<numComponentViews;++ii)
       
   173 		{
       
   174 		const TInt thisCount=iComponentView[ii].iView.CountL();
       
   175 		if (aIndex<(count+thisCount))
       
   176 			{
       
   177 			return iComponentView[ii].iView.AtL(aIndex-count);
       
   178 			}
       
   179 		count+=thisCount;
       
   180 		}
       
   181 	//Out of Bounds 
       
   182 	User::Leave(KErrNotFound);
       
   183 	return KErrNotFound;
       
   184 	}
       
   185 
       
   186 
       
   187 const CViewContact& CContactConcatenatedView::ContactAtL(TInt aIndex) const
       
   188 /** Gets the contact item at the specified index into the view.
       
   189 
       
   190 @param aIndex Index into the view.
       
   191 @leave KErrNotReady The view is not ready for use. 
       
   192 @leave KErrNotFound The index is invalid. It must be less that the total 
       
   193 number of items in the concatenated view.
       
   194 @return The contact item. 
       
   195 */
       
   196 	{
       
   197 	if (iState != EReady)
       
   198 		{
       
   199 		User::Leave(KErrNotReady);
       
   200 		}
       
   201 	TInt count=0;
       
   202 	const TInt numComponentViews=iComponentView.Count();
       
   203 	for (TInt ii=0;ii<numComponentViews;++ii)
       
   204 		{
       
   205 		const TInt thisCount=iComponentView[ii].iView.CountL();
       
   206 		if (aIndex<(count+thisCount))
       
   207 			{
       
   208 			return iComponentView[ii].iView.ContactAtL(aIndex-count);
       
   209 			}
       
   210 		count+=thisCount;
       
   211 		}
       
   212 	//Out of Bounds 
       
   213 	User::Leave(KErrNotFound);
       
   214 	// the following code is never executed and is purely to stop the compiler warnings
       
   215 	const CViewContact* nullContact=NULL;
       
   216 	return *nullContact;
       
   217 	}
       
   218 
       
   219 TInt CContactConcatenatedView::CountL() const
       
   220 /** Gets the number of contact items in the concatenated view.
       
   221 
       
   222 This is the total number of items in all component views.
       
   223 @leave KErrNotReady The view is not ready for use.
       
   224 @return The number of items in the concatenated view. 
       
   225 */
       
   226 	{
       
   227 	if (iState != EReady)
       
   228 		{
       
   229 		User::Leave(KErrNotReady);
       
   230 		}
       
   231 	TInt count=0;
       
   232 	const TInt numComponentViews=iComponentView.Count();
       
   233 	for (TInt ii=0;ii<numComponentViews;++ii)
       
   234 		{
       
   235 		count+=iComponentView[ii].iView.CountL();
       
   236 		}
       
   237 	return count;
       
   238 	}
       
   239 
       
   240 TInt CContactConcatenatedView::FindL(TContactItemId aId) const
       
   241 /** Finds the index into the concatenated view of the specified contact item.
       
   242 
       
   243 @param aId The contact item ID to search for.
       
   244 @leave KErrNotReady The view is not ready for use.
       
   245 @return The index of the first matching item in the concatenated view or KErrNotFound 
       
   246 if no matching item can be found. 
       
   247 */
       
   248 	{
       
   249 	if (iState != EReady)
       
   250 		{
       
   251 		User::Leave(KErrNotReady);
       
   252 		}
       
   253 	TInt count=0;
       
   254 	const TInt numComponentViews=iComponentView.Count();
       
   255 	for (TInt ii=0;ii<numComponentViews;++ii)
       
   256 		{
       
   257 		TInt index=iComponentView[ii].iView.FindL(aId);
       
   258 		if (index!=KErrNotFound)
       
   259 			{
       
   260 			return count+index;
       
   261 			}
       
   262 		count+=iComponentView[ii].iView.CountL();
       
   263 		}
       
   264 	return KErrNotFound;
       
   265 	}
       
   266 
       
   267 HBufC* CContactConcatenatedView::AllFieldsLC(TInt aIndex,const TDesC& aSeparator) const
       
   268 /** Returns a descriptor containing the contents of all fields in an item in the 
       
   269 view.
       
   270 
       
   271 The fields are separated by aSeparator.
       
   272 
       
   273 @param aIndex The index into the view of the contact item.
       
   274 @param aSeparator The string to use to separate the fields.
       
   275 @leave KErrNotReady The view is not ready for use.
       
   276 @return Pointer to the contact item descriptor.
       
   277 @panic CNTMODEL 29 In debug builds, this indicates that the index is invalid. 
       
   278 It must be less that the total number of items in the concatenated view. 
       
   279 In release builds, a NULL pointer is returned instead. 
       
   280 */
       
   281 	{
       
   282 	if (iState != EReady)
       
   283 		{
       
   284 		User::Leave(KErrNotReady);
       
   285 		}
       
   286 	TInt count=0;
       
   287 	const TInt numComponentViews=iComponentView.Count();
       
   288 	for (TInt ii=0;ii<numComponentViews;++ii)
       
   289 		{
       
   290 		count+=iComponentView[ii].iView.CountL();
       
   291 		if (aIndex<count)
       
   292 			{
       
   293 			return iComponentView[ii].iView.AllFieldsLC(aIndex-count,aSeparator);
       
   294 			}
       
   295 		}
       
   296 	__ASSERT_DEBUG(EFalse,Panic(ECntPanicInvalidIndexForConcatenatedView));
       
   297 	return NULL;	
       
   298 	}
       
   299 
       
   300 
       
   301 void CContactConcatenatedView::HandleContactViewEvent(const CContactViewBase& aView,const TContactViewEvent& aEvent)
       
   302 	{
       
   303 	TBool passOnNotification=ETrue;
       
   304 	TContactViewEvent event=aEvent;
       
   305 	
       
   306 	TInt err;
       
   307 
       
   308 	switch (event.iEventType)
       
   309 		{
       
   310 		case TContactViewEvent::ESortError:
       
   311 		case TContactViewEvent::EServerError:
       
   312 		case TContactViewEvent::EUnavailable:
       
   313 			iState=ENotReady;
       
   314 			break;
       
   315 		case TContactViewEvent::EReady:
       
   316 			SetComponentViewReady(aView);
       
   317 			if (ComponentViewsReady()) // Need to wait for all views to be ready before changing state.
       
   318 				{
       
   319 				iState=EReady;
       
   320 				}
       
   321 			else
       
   322 				{
       
   323 				passOnNotification=EFalse;
       
   324 				}
       
   325 			break;
       
   326 		case TContactViewEvent::ESortOrderChanged:
       
   327 			iState=EReady;
       
   328 			break;
       
   329 		case TContactViewEvent::EItemAdded:
       
   330 		case TContactViewEvent::EItemRemoved:
       
   331 			TRAP(err,event.iInt+=OffsetL(aView));
       
   332 			if (err != KErrNone)
       
   333 				{
       
   334 				NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,err));
       
   335 				passOnNotification = EFalse;
       
   336 				}
       
   337 			break;
       
   338 		case TContactViewEvent::EGroupChanged:
       
   339 			break;
       
   340 		default:
       
   341 			ASSERT(EFalse);
       
   342 		}
       
   343 
       
   344 	if (passOnNotification)
       
   345 		{
       
   346 		NotifyObservers(event);
       
   347 		}
       
   348 	}
       
   349 
       
   350 TInt CContactConcatenatedView::OffsetL(const CContactViewBase& aView)
       
   351 	{
       
   352 	const TInt eventOwningViewIndex=FindComponentView(aView);
       
   353 	TInt offset=0;
       
   354 	for (TInt ii=0;ii<eventOwningViewIndex;++ii)
       
   355 		{
       
   356 		offset+=iComponentView[ii].iView.CountL();
       
   357 		}
       
   358 	return offset;
       
   359 	}
       
   360 
       
   361 TContactViewPreferences CContactConcatenatedView::ContactViewPreferences()
       
   362 /** Gets the view preferences for the first component view.
       
   363 @return The view preferences. 
       
   364 */
       
   365 	{
       
   366 	return iComponentView[0].iView.ContactViewPreferences();
       
   367 	}
       
   368 
       
   369 const RContactViewSortOrder& CContactConcatenatedView::SortOrderL() const
       
   370 /** Gets the sort order for the first component view.
       
   371 
       
   372 @return The sort order. */
       
   373 	{
       
   374 	return iComponentView[0].iView.SortOrderL();
       
   375 	}
       
   376 
       
   377 CContactConcatenatedView::TComponentView::TComponentView(CContactViewBase& aView,TState aState) : iView(aView),iState(aState) 
       
   378 	{
       
   379 	}