diff -r 000000000000 -r f979ecb2b13e pimappservices/calendar/client/src/calinstanceiteratoruid.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappservices/calendar/client/src/calinstanceiteratoruid.cpp Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,440 @@ +// 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: +// + +#include "calinstanceiteratoruid.h" +#include "calsessionimpl.h" +#include "calinstance.h" +#include "calinstanceimpl.h" +#include "calentryimpl.h" +#include "calclient.h" +#include "agmrptdef.h" +#include "agmentry.h" +#include "agmsimpleentry.h" +#include "calcommonimpl.h" +#include "agmdate.h" + +/** Uid instance iterator NewL + +@internalComponent +*/ +CCalInstanceIteratorUid* CCalInstanceIteratorUid::NewL(const CCalInstanceViewImpl& iInstanceViewImpl, const TDesC8& aGuid, const TCalTime& aStartInstance, TUint8 aShortFileId) + { + CCalInstanceIteratorUid* self = new(ELeave) CCalInstanceIteratorUid(iInstanceViewImpl); + CleanupStack::PushL(self); + self->ConstructL(aGuid, aStartInstance, aShortFileId); + CleanupStack::Pop(self); + return self; + } + +/** Uid instance iterator constructor + +@internalComponent +*/ +CCalInstanceIteratorUid::CCalInstanceIteratorUid(const CCalInstanceViewImpl& iInstanceViewImpl) +:CCalInstanceIterator(iInstanceViewImpl), iCurrentIndex(-1) + { + } + +/** Uid instance iterator ConstructL + +Fetches all the related entries to the UID and sets the currently indexed time + +@internalComponent +*/ +void CCalInstanceIteratorUid::ConstructL(const TDesC8& aUid, const TCalTime& aInstanceTime, TCalCollectionId aCollectionId) + { + // record the time to use for undated todos + TTime now; + now.HomeTime(); + iUndatedTodoTime.SetTimeLocalL(now); + + // Fetch all the entries that relate to the instance + RPointerArray simpleEntries; + TCleanSimpleEntryArray cleanSimpleEntryArray(simpleEntries, iInstanceViewImpl.GetServ()); + CleanupStack::PushL(TCleanupItem(CCalInstanceViewImpl::DestroySimpleEntryArray, &cleanSimpleEntryArray)); + RArray fileIds; + iInstanceViewImpl.GetShortFileIdLC(fileIds);//It is in order + iInstanceViewImpl.GetServ().FetchSimpleEntriesByGuidL(aUid, simpleEntries, fileIds); + CleanupStack::PopAndDestroy(&fileIds); + + const TInt KEntryCount(simpleEntries.Count()); + + // There must be entries associated with this UID + __ASSERT_ALWAYS(KEntryCount != 0, User::Leave(KErrNotFound)); + + TBool instanceExists(EFalse); + + for (TInt i(0) ; i < KEntryCount ; ++i) + { + CCalLiteEntry* liteEntry = CCalLiteEntry::NewL(*simpleEntries[0], iInstanceViewImpl.GetServ()); + liteEntry->IncrementRefCount(); + simpleEntries.Remove(0); + TInt appendError = iCalLiteEntries.Append(liteEntry); + if (appendError != KErrNone) + { + liteEntry->DecrementRefCount(); + User::Leave(appendError); + } + + if (iInstanceViewImpl.IsValidInstanceL(liteEntry->LiteEntry(), aInstanceTime)) + {//Add the index of the entry which has the same time as aInstanceTime into iEntryWithSameTime + if(liteEntry->LiteEntry().CollectionId() == aCollectionId) + { + instanceExists = ETrue; + iCurrentIndexTime = aInstanceTime; + iCurrentIndex = iEntryWithSameTime.Count(); + } + iEntryWithSameTime.AppendL(i); + } + } + + __ASSERT_ALWAYS(instanceExists, User::Leave(KErrNotFound)); + CleanupStack::PopAndDestroy(); // simpleEntries + } + +/** UID instance iterator destructor + +@internalComponent +*/ +CCalInstanceIteratorUid::~CCalInstanceIteratorUid() + { + // should use CleanArray of LiteEntries + const TInt KEntryCount(iCalLiteEntries.Count()); + for (TInt i(0) ; i < KEntryCount ; ++i) + { + iCalLiteEntries[i]->DecrementRefCount(); + } + + iCalLiteEntries.Close(); + iEntryWithSameTime.Close(); + } + +TCalTime CCalInstanceIteratorUid::NonRptEntryInstanceTimeL(const CAgnSimpleEntry& aEntry) + { + // The entry does not have a repeat rule so it is just a single instance + TCalTime entryInstanceTime; + if (aEntry.Type() == CCalEntry::ETodo) + { + TTime completionDate = aEntry.CompletedDateUtc(); + if (completionDate == Time::NullTTime()) + { + if (!aEntry.EntryTime().IsSet()) + { + entryInstanceTime = iUndatedTodoTime; + } + else + { + entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime()); + } + } + else + { + if (aEntry.TimeMode() == MAgnCalendarTimeMode::EFloating) + { + entryInstanceTime.SetTimeLocalFloatingL(AgnDateTime::ConvertToLocalTimeL(completionDate)); + } + else + { + entryInstanceTime.SetTimeUtcL(completionDate); + } + } + } + else + { + entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime()); + } + + return entryInstanceTime; + } + +/** Returns the next instance + +Loops through all the entries in the cached entry list and finds +the earliest instance that appears after the current index instance time. + +@return The next instance + +@internalComponent +*/ +CCalInstance* CCalInstanceIteratorUid::NextL() + { + CCalInstance* retInstance = NULL; + TInt numSameTimeEntry = iEntryWithSameTime.Count(); + if(numSameTimeEntry >0 && iCurrentIndex < numSameTimeEntry - 1) + { + //If there are entries in iEntryWithSameTime, their instance time is same as the iCurrentIndexTime, we should return this instance. + return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[++iCurrentIndex]], iCurrentIndexTime); + } + + TCalTime bestSoFar; + bestSoFar.SetTimeUtcL(TCalTime::MaxTime()); + TInt thisAgnSimpleEntryIndex(KErrNotFound); + + const TInt KEntryCount(iCalLiteEntries.Count()); + TInt i(0); + for (; i < KEntryCount ; ++i) + { + TCalTime entryNextTime; + entryNextTime.SetTimeUtcL(TCalTime::MaxTime()); + + CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef(); + if (thisEntryRptDef) + { + TTime entryNextTimeUtc; + TBool instanceFound(EFalse); + TTime fromTimeUtc(iCurrentIndexTime.TimeUtcL() + TTimeIntervalMicroSeconds(1)); + + do + { + // keep looping until we find an unexcepted instance or there are no more instances + instanceFound = thisEntryRptDef->NudgeNextInstanceUtcL(fromTimeUtc, entryNextTimeUtc); + fromTimeUtc = entryNextTimeUtc + TTimeIntervalMicroSeconds(1); + } + while (instanceFound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryNextTimeUtc) ) ); + + if (instanceFound) + { + entryNextTime.SetTimeUtcL(entryNextTimeUtc); + } + } + else + { + TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry()); + + if (entryInstanceTime.TimeUtcL() > iCurrentIndexTime.TimeUtcL()) + { + // The entry's instance time is after the current index time + // so it is a valid possible next instance + entryNextTime = entryInstanceTime; + } + } + + if (entryNextTime.TimeUtcL() < bestSoFar.TimeUtcL()) + { + // This time is better than best time so far so update the best so far + bestSoFar = entryNextTime; + thisAgnSimpleEntryIndex = i; + iEntryWithSameTime.Reset(); + iCurrentIndex = -1; + } + else if (entryNextTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryNextTime.TimeUtcL()!= TCalTime::MaxTime()) + { + //Store the index of the entry which has the instance time as the "bestSoFar" time + iEntryWithSameTime.AppendL(i); + } + } + + + if (bestSoFar.TimeUtcL() != TCalTime::MaxTime()) + { + retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar); + iCurrentIndexTime = bestSoFar; + } + + return retInstance; + } + +/** Returns the previous instance + +Loops through all the entries in the cached entry list and finds +the latest instance that appears before the current index instance time. + +@return The previous instance + +@internalComponent +*/ +CCalInstance* CCalInstanceIteratorUid::PreviousL() + { + CCalInstance* retInstance = NULL; + TInt numOfsameTimeInstance = iEntryWithSameTime.Count(); + if(numOfsameTimeInstance > 0 && iCurrentIndex >= 1) + { + // we should return the last instance in the array to make it consistent with NextL which returns the first entry's instance. + return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[--iCurrentIndex]], iCurrentIndexTime); + } + + TCalTime bestSoFar; + bestSoFar.SetTimeUtcL(TCalTime::MinTime()); + TInt thisAgnSimpleEntryIndex(KErrNotFound); + + const TInt KEntryCount(iCalLiteEntries.Count()); + TInt i(0); + for (; i < KEntryCount ; ++i) + { + TCalTime entryPreviousTime; + entryPreviousTime.SetTimeUtcL(TCalTime::MinTime()); + + CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef(); + + if (thisEntryRptDef) + { + TTime entryPreviousTimeUtc(iCurrentIndexTime.TimeUtcL()); + TBool instancefound(EFalse); + TTime fromTimeUtc; + + do + { + fromTimeUtc = entryPreviousTimeUtc - TTimeIntervalMicroSeconds(1); + // keep calling until an unexcepted instance is found or there are no more instances + instancefound = thisEntryRptDef->NudgePreviousInstanceUtcL(fromTimeUtc, entryPreviousTimeUtc); + } + while (instancefound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryPreviousTimeUtc) ) ); + + if (instancefound) + { + entryPreviousTime.SetTimeUtcL(entryPreviousTimeUtc); + } + } + else + { + // The entry does not have a repeat rule so it is just a single instance + TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry()); + + if (entryInstanceTime.TimeUtcL() < iCurrentIndexTime.TimeUtcL()) + { + // The entry's instance time is before the current index time + // so it is a valid possible next instance + entryPreviousTime = entryInstanceTime; + } + } + + if (entryPreviousTime.TimeUtcL() > bestSoFar.TimeUtcL()) + { + // This time is better than best time so far so update the best so far + bestSoFar = entryPreviousTime; + thisAgnSimpleEntryIndex = i; + iEntryWithSameTime.Reset(); + iCurrentIndex = -1; + } + else if (entryPreviousTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryPreviousTime.TimeUtcL()!= TCalTime::MinTime()) + { + iEntryWithSameTime.AppendL(thisAgnSimpleEntryIndex); + thisAgnSimpleEntryIndex = i; + } + } + + if (bestSoFar.TimeUtcL() != TCalTime::MinTime()) + { + retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar); + iCurrentIndexTime = bestSoFar; + numOfsameTimeInstance = iEntryWithSameTime.Count(); + if(numOfsameTimeInstance>0) + { + iCurrentIndex = numOfsameTimeInstance; + } + } + + return retInstance; + } + +/** To check if there are more instance to be returned by NextL(). + +Calls NextL() to see if if returns another instance, and then sets the current +indexed instance time back to what it was before the call. + +@return ETrue if there are more instance to be returned by NextL(), +EFalse if there are no more instance, and EFalse if there is a problem +calculating if there are more instance to be returned by NextL(). + +@internalComponent +*/ +TBool CCalInstanceIteratorUid::HasMore() const + { + TBool returnValue(EFalse); + TRAP_IGNORE(returnValue = HasMoreL()); + return returnValue; + } + +TBool CCalInstanceIteratorUid::HasMoreL() const + { + TBool returnValue(EFalse); + + //Store the current state + TCalTime storedCurrentIndex = iCurrentIndexTime; + TInt storedArrayIndex = iCurrentIndex; + RArray storedArray; + CleanupClosePushL(storedArray); + const TInt count = iEntryWithSameTime.Count(); + for(TInt ii=0; ii(this)->NextL(); + returnValue = (nextInstance != NULL); + delete nextInstance; + + // restore the state + const_cast(this)->iCurrentIndexTime = storedCurrentIndex; + iCurrentIndex = storedArrayIndex;//reset index since it could be moved in NextL + iEntryWithSameTime.Reset(); + const TInt countSortedArray = storedArray.Count(); + for(TInt ii=0; iiLiteEntry().RptDef(); + if (rptDef) + { + // This gets all the instances generated by the repeat rule + TRAPD(error, returnInstanceCount += rptDef->InstanceCountL()); + if (error) + { + // an error has occoured whilst calculating the instance count + // so quit and retrun the error code + returnInstanceCount = error; + break; + } + + // Need to take off valid exception dates + if (rptDef->Exceptions()) + { + returnInstanceCount -= rptDef->Exceptions()->Count(); + } + } + else + { + // The entry does not have a repeat rule + // so it is just a single instance + ++returnInstanceCount; + } + } + + return returnInstanceCount; + } + +