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