phonebookengines/contactsmodel/cntview/Range.cpp
changeset 0 e686773b3f54
child 24 0ba2181d7c28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntview/Range.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,428 @@
+// 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"
+#include <collate.h>
+
+
+
+//#define CNTVIEW_API_PROFILING
+
+
+//
+// CContactViewRangeBase
+//
+
+/**
+@internalComponent
+*/
+CContactViewRangeBase::CContactViewRangeBase(const CContactViewBase& aView)
+	: iView(aView),iLow(KErrNotFound),iHigh(KErrNotFound)
+	{
+	}
+
+CContactViewRangeBase::~CContactViewRangeBase()
+	{
+	delete iCollateMethod;
+	}
+
+void CContactViewRangeBase::ConstructL()
+/** Called by derived classes to set the collation method iCollateMethod to be 
+the standard collation method for the current locale.
+@internalComponent
+*/
+	{
+	// Needed to ensure unicode sorting / inserting into sorted lists works the same as ER5,
+	// i.e. that it encludes all spaces and punctuation.
+	iCollateMethod = new(ELeave) TCollationMethod;
+	*iCollateMethod = *Mem::CollationMethodByIndex(0);
+	iCollateMethod->iFlags|=TCollationMethod::EIgnoreNone;
+	}
+
+EXPORT_C TBool CContactViewRangeBase::IndicesValid() const
+/** Tests whether the lower and upper indexes are valid, i.e. not KErrNotFound.
+
+@return ETrue if the indexes are valid, EFalse if not. */
+	{
+	if (iLow==KErrNotFound)
+		{
+		ASSERT(iHigh==KErrNotFound);
+		return EFalse;
+		}
+	return ETrue;
+	}
+
+TInt CContactViewRangeBase::FindIndexL(const TDesC& aMatch,TCriteria aCriteria) const
+// Binary search through iView to find the first contact that matches aMatch according to aCritera.
+/** Called by implementations of SetL() to search the sub view's underlying view 
+for the index of the first item whose field content matches aMatch, using 
+the specified search criteria.
+
+@internalComponent
+@param aMatch The text to search for. 
+@param aCriteria The search criteria. 
+@return The index of the first matching item in the view. KErrNotFound if the 
+view is empty or if none match. */
+	{
+	const TInt NumberOfCharsToCompare=1;
+	TInt result=KErrNotFound;
+	TInt min=0;
+	TInt max=iView.CountL()-1;
+	if (max<0)
+		{
+		// The parent view is empty.
+		return KErrNotFound;
+		}
+	TBool finished=EFalse;
+
+	HBufC* sortableText;
+	while (!finished)
+		{
+		TInt guess;
+		if (max==min)
+			{
+			finished=ETrue;
+			}
+
+		guess=(max-min)/2+min;
+		sortableText = iView.AllFieldsLC(guess,KNullDesC);
+		TInt compare=sortableText->Left(NumberOfCharsToCompare).CompareC(aMatch.Left(NumberOfCharsToCompare),3,iCollateMethod);
+		CleanupStack::PopAndDestroy();//sortableText
+		switch (aCriteria)
+			{
+			case ELessThan: 
+				{ 
+				if (compare>0 || compare==0)
+					{
+					// String is greater than aMatch.
+					max=guess-1;
+					if (max<min)
+						{
+						finished=ETrue;
+						}
+					}
+				else if (compare<0)
+					{
+					// String is less than aMatch - could be a hit.
+					min=guess+1;
+					if (min>max)
+						{
+						finished=ETrue;
+						}
+					if (result==KErrNotFound || guess>result)
+						{
+						// guess is a closer match, so overwrite result.
+						result=guess;
+						}
+					}
+				break;
+				}
+			case ELessThanOrEqualTo: 
+				{
+				if (compare>0)
+					{
+					// String is greater than aMatch.
+					max=guess-1;
+					if (max<min)
+						{
+						finished=ETrue;
+						}
+					}
+				else if (compare<=0)
+					{
+					// String is less than or equal to aMatch - possible hit.
+					min=guess+1;
+					if (min>max)
+						{
+						finished=ETrue;
+						}
+					if (result==KErrNotFound || guess>result)
+						{
+						// guess is a closer match, so overwrite result.
+						result=guess;
+						}
+					}
+				break;
+				}
+			case EGreaterThan: 
+				{
+				if (compare<0 || compare==0)
+					{
+					// String is less than aMatch.
+					min=guess+1;
+					if (min>max)
+						{
+						finished=ETrue;
+						}
+					}
+				else if (compare>0)
+					{
+					// String is greater than aMatch - possible hit.
+					max=guess-1;
+					if (max<min)
+						{
+						finished=ETrue;
+						}
+					if (result==KErrNotFound || guess<result)
+						{
+						// guess is a closer match, so overwrite result.
+						result=guess;
+						}
+					}
+				break;
+				}
+			case EGreaterThanOrEqualTo:
+				{
+				if (compare<0)
+					{
+					// String is less than aMatch.
+					min=guess+1;
+					if (min>max)
+						{
+						finished=ETrue;
+						}
+					}
+				else if (compare>=0)
+					{
+					// String is >= aMatch - possible hit.
+					max=guess-1;
+					if (max<min)
+						{
+						finished=ETrue;
+						}
+					if (result==KErrNotFound || guess<result)
+						{
+						// guess is a closer match, so overwrite result.
+						result=guess;
+						}
+					}
+				break;
+				}
+			};
+		}
+	return result;
+	}
+
+/**
+@internalComponent
+*/
+TBool CContactViewRangeBase::MatchesCriteriaL(TCriteria aCriteria,const TDesC& aMatch,TInt aIndex) const
+	{
+	TBool match=EFalse;
+	HBufC* sortableText=iView.AllFieldsLC(aIndex,KNullDesC);
+	TInt compare=sortableText->CompareC(aMatch,3,iCollateMethod);
+
+	switch(aCriteria)
+		{
+		case ELessThan:
+			{
+			if(compare<0)
+				{
+				//RDebug::Print(_L("Match of %S against < %S PASSED\x0D\x00\x0a\x00"),&sortableText,&aMatch);
+				match=ETrue;
+				}
+			else
+				{
+				//RDebug::Print(_L("Match of %S against < %S FAILED\x0D\x00\x0a\x00"),&sortableText,&aMatch);
+				}
+			break;
+			};
+		case ELessThanOrEqualTo:
+			{
+			if(compare<=0)
+				match=ETrue;
+			break;
+			};
+		case EGreaterThan:
+			{
+			if(compare>0)
+				match=ETrue;
+			break;
+			};
+		case EGreaterThanOrEqualTo:
+			{
+			if(compare>=0)
+				{
+				//RDebug::Print(_L("Match of %S against >= %S PASSED\x0D\x00\x0a\x00"),&sortableText,&aMatch);
+				match=ETrue;
+				}
+			else
+				{
+				//RDebug::Print(_L("Match of %S against >= %S FAILED\x0D\x00\x0a\x00"),&sortableText,&aMatch);
+				}
+			break;
+			};
+		};
+
+	return match;
+	}
+
+void CContactViewRangeBase::ValidateIndices()
+/** Called by derived classes to validate the upper and lower indexes (iLow and 
+iHigh).
+
+If either index is KErrNotFound, or iLow is greater than iHigh, then both 
+are set to KErrNotFound. 
+@internalComponent
+*/
+	{
+	// Check that range isn't inside out, and both ranges are valid.
+	if (iLow>iHigh || iHigh==KErrNotFound || iLow==KErrNotFound)
+		{
+		// Invalidate both indicies.
+		iLow=KErrNotFound;
+		iHigh=KErrNotFound;
+		}
+	}
+
+//
+// CContactViewRange
+//
+
+
+CContactViewRange::CContactViewRange(const CContactViewBase& aView,const TDesC& aLowMatch,TCriteria aLowCriteria,const TDesC& aHighMatch,TCriteria aHighCriteria)
+	:CContactViewRangeBase(aView),iLowMatch(aLowMatch),iLowCriteria(aLowCriteria),iHighMatch(aHighMatch),iHighCriteria(aHighCriteria)
+	{
+	}
+
+EXPORT_C CContactViewRange* CContactViewRange::NewL(const CContactViewBase& aView,const TDesC& aLowMatch,TCriteria aLowCriteria,const TDesC& aHighMatch,TCriteria aHighCriteria)
+/** Allocates and constructs a new sub view range.
+
+@param aView The sub view's underlying view. 
+@param aLowMatch The match string for the bottom of the range. Only the first 
+character in the string is used.
+@param aLowCriteria The query search condition for the bottom of the range; 
+either CContactViewRangeBase::EGreaterThan or CContactViewRangeBase::EGreaterThanOrEqualTo.
+@param aHighMatch The match string for the top of the range. Only the first 
+character in the string is used. 
+@param aHighCriteria The query search condition for the top of the range; either 
+CContactViewRangeBase::ELessThan or CContactViewRangeBase::ELessThanOrEqualTo.
+@return Pointer to a newly created sub view range object    */
+	{
+#ifdef CNTVIEW_API_PROFILING
+	RDebug::Print(_L("[CNTMODEL] CContactViewRange::NewL()\n"));
+#endif
+	CContactViewRange* self=new(ELeave) CContactViewRange(aView,aLowMatch,aLowCriteria,aHighMatch,aHighCriteria);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self.
+	return self;
+	}
+
+CContactViewRange::~CContactViewRange()
+/** Destructor. */
+	{
+	}
+
+void CContactViewRange::ConstructL()
+	{
+	CContactViewRangeBase::ConstructL();
+	}
+
+void CContactViewRange::SetL()
+	{
+	iLow=FindIndexL(iLowMatch,iLowCriteria);
+	iHigh=FindIndexL(iHighMatch,iHighCriteria);
+	ValidateIndices();
+	}
+
+
+//
+// CContactViewLowRange
+//
+
+CContactViewLowRange::CContactViewLowRange(const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria)
+	: CContactViewRangeBase(aView),iMatch(aMatch),iCriteria(aCriteria)
+	{
+	}
+
+CContactViewLowRange::~CContactViewLowRange()
+	{
+	}
+
+EXPORT_C CContactViewLowRange* CContactViewLowRange::NewL(const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria)
+/** Allocates and constructs a CContactViewLowRange object.
+
+@param aView The sub view's underlying view.
+@param aMatch The string to match items against. Only the first character in 
+the string is used.
+@param aCriteria The query search condition; either CContactViewRangeBase::ELessThanOrEqualTo 
+or CContactViewRangeBase::ELessThan.
+@return Pointer to a newly created CContactViewLowRange object  */
+	{
+#ifdef CNTVIEW_API_PROFILING
+	RDebug::Print(_L("[CNTMODEL] CContactViewLowRange::NewL()\n"));
+#endif
+	CContactViewLowRange* self=new(ELeave) CContactViewLowRange(aView,aMatch,aCriteria);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self.
+	return self;
+	}
+
+void CContactViewLowRange::SetL()
+	{
+	iHigh=FindIndexL(iMatch,iCriteria);
+	if(iHigh!=KErrNotFound && iHigh >=0)
+		{
+		iLow=0;
+		}
+	ValidateIndices();
+	}
+
+
+//
+// CContactViewHighRange 
+//
+
+CContactViewHighRange::CContactViewHighRange (const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria)
+	: CContactViewRangeBase(aView),iMatch(aMatch),iCriteria(aCriteria)
+	{
+	}
+
+CContactViewHighRange::~CContactViewHighRange()
+	{
+	}
+
+EXPORT_C CContactViewHighRange * CContactViewHighRange::NewL(const CContactViewBase& aView,const TDesC& aMatch,TCriteria aCriteria)
+/** Allocates and constructs a CContactViewHighRange object.
+
+@param aView The sub view's underlying view.
+@param aMatch The string to match items against. Only the first character in 
+the string is used.
+@param aCriteria The query search condition; either CContactViewRangeBase::EGreaterThan 
+or CContactViewRangeBase::EGreaterThanOrEqualTo. 
+@return Pointer to newly created CContactViewHighRange object  */
+	{
+#ifdef CNTVIEW_API_PROFILING
+	RDebug::Print(_L("[CNTMODEL] CContactViewHighRange::NewL()\n"));
+#endif
+	CContactViewHighRange * self=new(ELeave) CContactViewHighRange (aView,aMatch,aCriteria);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self.
+	return self;
+	}
+
+void CContactViewHighRange::SetL()
+	{
+	iLow=FindIndexL(iMatch,iCriteria);
+	if (iLow!=KErrNotFound)
+		{
+		iHigh=iView.CountL()-1;
+		}
+	ValidateIndices();
+	}