|
1 // Copyright (c) 2007-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 "calinstanceiteratoruid.h" |
|
17 #include "calsessionimpl.h" |
|
18 #include "calinstance.h" |
|
19 #include "calinstanceimpl.h" |
|
20 #include "calentryimpl.h" |
|
21 #include "calclient.h" |
|
22 #include "agmrptdef.h" |
|
23 #include "agmentry.h" |
|
24 #include "agmsimpleentry.h" |
|
25 #include "calcommonimpl.h" |
|
26 #include "agmdate.h" |
|
27 |
|
28 /** Uid instance iterator NewL |
|
29 |
|
30 @internalComponent |
|
31 */ |
|
32 CCalInstanceIteratorUid* CCalInstanceIteratorUid::NewL(const CCalInstanceViewImpl& iInstanceViewImpl, const TDesC8& aGuid, const TCalTime& aStartInstance, TUint8 aShortFileId) |
|
33 { |
|
34 CCalInstanceIteratorUid* self = new(ELeave) CCalInstanceIteratorUid(iInstanceViewImpl); |
|
35 CleanupStack::PushL(self); |
|
36 self->ConstructL(aGuid, aStartInstance, aShortFileId); |
|
37 CleanupStack::Pop(self); |
|
38 return self; |
|
39 } |
|
40 |
|
41 /** Uid instance iterator constructor |
|
42 |
|
43 @internalComponent |
|
44 */ |
|
45 CCalInstanceIteratorUid::CCalInstanceIteratorUid(const CCalInstanceViewImpl& iInstanceViewImpl) |
|
46 :CCalInstanceIterator(iInstanceViewImpl), iCurrentIndex(-1) |
|
47 { |
|
48 } |
|
49 |
|
50 /** Uid instance iterator ConstructL |
|
51 |
|
52 Fetches all the related entries to the UID and sets the currently indexed time |
|
53 |
|
54 @internalComponent |
|
55 */ |
|
56 void CCalInstanceIteratorUid::ConstructL(const TDesC8& aUid, const TCalTime& aInstanceTime, TCalCollectionId aCollectionId) |
|
57 { |
|
58 // record the time to use for undated todos |
|
59 TTime now; |
|
60 now.HomeTime(); |
|
61 iUndatedTodoTime.SetTimeLocalL(now); |
|
62 |
|
63 // Fetch all the entries that relate to the instance |
|
64 RPointerArray<CAgnSimpleEntry> simpleEntries; |
|
65 TCleanSimpleEntryArray cleanSimpleEntryArray(simpleEntries, iInstanceViewImpl.GetServ()); |
|
66 CleanupStack::PushL(TCleanupItem(CCalInstanceViewImpl::DestroySimpleEntryArray, &cleanSimpleEntryArray)); |
|
67 RArray<TInt> fileIds; |
|
68 iInstanceViewImpl.GetShortFileIdLC(fileIds);//It is in order |
|
69 iInstanceViewImpl.GetServ().FetchSimpleEntriesByGuidL(aUid, simpleEntries, fileIds); |
|
70 CleanupStack::PopAndDestroy(&fileIds); |
|
71 |
|
72 const TInt KEntryCount(simpleEntries.Count()); |
|
73 |
|
74 // There must be entries associated with this UID |
|
75 __ASSERT_ALWAYS(KEntryCount != 0, User::Leave(KErrNotFound)); |
|
76 |
|
77 TBool instanceExists(EFalse); |
|
78 |
|
79 for (TInt i(0) ; i < KEntryCount ; ++i) |
|
80 { |
|
81 CCalLiteEntry* liteEntry = CCalLiteEntry::NewL(*simpleEntries[0], iInstanceViewImpl.GetServ()); |
|
82 liteEntry->IncrementRefCount(); |
|
83 simpleEntries.Remove(0); |
|
84 TInt appendError = iCalLiteEntries.Append(liteEntry); |
|
85 if (appendError != KErrNone) |
|
86 { |
|
87 liteEntry->DecrementRefCount(); |
|
88 User::Leave(appendError); |
|
89 } |
|
90 |
|
91 if (iInstanceViewImpl.IsValidInstanceL(liteEntry->LiteEntry(), aInstanceTime)) |
|
92 {//Add the index of the entry which has the same time as aInstanceTime into iEntryWithSameTime |
|
93 if(liteEntry->LiteEntry().CollectionId() == aCollectionId) |
|
94 { |
|
95 instanceExists = ETrue; |
|
96 iCurrentIndexTime = aInstanceTime; |
|
97 iCurrentIndex = iEntryWithSameTime.Count(); |
|
98 } |
|
99 iEntryWithSameTime.AppendL(i); |
|
100 } |
|
101 } |
|
102 |
|
103 __ASSERT_ALWAYS(instanceExists, User::Leave(KErrNotFound)); |
|
104 CleanupStack::PopAndDestroy(); // simpleEntries |
|
105 } |
|
106 |
|
107 /** UID instance iterator destructor |
|
108 |
|
109 @internalComponent |
|
110 */ |
|
111 CCalInstanceIteratorUid::~CCalInstanceIteratorUid() |
|
112 { |
|
113 // should use CleanArray of LiteEntries |
|
114 const TInt KEntryCount(iCalLiteEntries.Count()); |
|
115 for (TInt i(0) ; i < KEntryCount ; ++i) |
|
116 { |
|
117 iCalLiteEntries[i]->DecrementRefCount(); |
|
118 } |
|
119 |
|
120 iCalLiteEntries.Close(); |
|
121 iEntryWithSameTime.Close(); |
|
122 } |
|
123 |
|
124 TCalTime CCalInstanceIteratorUid::NonRptEntryInstanceTimeL(const CAgnSimpleEntry& aEntry) |
|
125 { |
|
126 // The entry does not have a repeat rule so it is just a single instance |
|
127 TCalTime entryInstanceTime; |
|
128 if (aEntry.Type() == CCalEntry::ETodo) |
|
129 { |
|
130 TTime completionDate = aEntry.CompletedDateUtc(); |
|
131 if (completionDate == Time::NullTTime()) |
|
132 { |
|
133 if (!aEntry.EntryTime().IsSet()) |
|
134 { |
|
135 entryInstanceTime = iUndatedTodoTime; |
|
136 } |
|
137 else |
|
138 { |
|
139 entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime()); |
|
140 } |
|
141 } |
|
142 else |
|
143 { |
|
144 if (aEntry.TimeMode() == MAgnCalendarTimeMode::EFloating) |
|
145 { |
|
146 entryInstanceTime.SetTimeLocalFloatingL(AgnDateTime::ConvertToLocalTimeL(completionDate)); |
|
147 } |
|
148 else |
|
149 { |
|
150 entryInstanceTime.SetTimeUtcL(completionDate); |
|
151 } |
|
152 } |
|
153 } |
|
154 else |
|
155 { |
|
156 entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime()); |
|
157 } |
|
158 |
|
159 return entryInstanceTime; |
|
160 } |
|
161 |
|
162 /** Returns the next instance |
|
163 |
|
164 Loops through all the entries in the cached entry list and finds |
|
165 the earliest instance that appears after the current index instance time. |
|
166 |
|
167 @return The next instance |
|
168 |
|
169 @internalComponent |
|
170 */ |
|
171 CCalInstance* CCalInstanceIteratorUid::NextL() |
|
172 { |
|
173 CCalInstance* retInstance = NULL; |
|
174 TInt numSameTimeEntry = iEntryWithSameTime.Count(); |
|
175 if(numSameTimeEntry >0 && iCurrentIndex < numSameTimeEntry - 1) |
|
176 { |
|
177 //If there are entries in iEntryWithSameTime, their instance time is same as the iCurrentIndexTime, we should return this instance. |
|
178 return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[++iCurrentIndex]], iCurrentIndexTime); |
|
179 } |
|
180 |
|
181 TCalTime bestSoFar; |
|
182 bestSoFar.SetTimeUtcL(TCalTime::MaxTime()); |
|
183 TInt thisAgnSimpleEntryIndex(KErrNotFound); |
|
184 |
|
185 const TInt KEntryCount(iCalLiteEntries.Count()); |
|
186 TInt i(0); |
|
187 for (; i < KEntryCount ; ++i) |
|
188 { |
|
189 TCalTime entryNextTime; |
|
190 entryNextTime.SetTimeUtcL(TCalTime::MaxTime()); |
|
191 |
|
192 CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef(); |
|
193 if (thisEntryRptDef) |
|
194 { |
|
195 TTime entryNextTimeUtc; |
|
196 TBool instanceFound(EFalse); |
|
197 TTime fromTimeUtc(iCurrentIndexTime.TimeUtcL() + TTimeIntervalMicroSeconds(1)); |
|
198 |
|
199 do |
|
200 { |
|
201 // keep looping until we find an unexcepted instance or there are no more instances |
|
202 instanceFound = thisEntryRptDef->NudgeNextInstanceUtcL(fromTimeUtc, entryNextTimeUtc); |
|
203 fromTimeUtc = entryNextTimeUtc + TTimeIntervalMicroSeconds(1); |
|
204 } |
|
205 while (instanceFound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryNextTimeUtc) ) ); |
|
206 |
|
207 if (instanceFound) |
|
208 { |
|
209 entryNextTime.SetTimeUtcL(entryNextTimeUtc); |
|
210 } |
|
211 } |
|
212 else |
|
213 { |
|
214 TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry()); |
|
215 |
|
216 if (entryInstanceTime.TimeUtcL() > iCurrentIndexTime.TimeUtcL()) |
|
217 { |
|
218 // The entry's instance time is after the current index time |
|
219 // so it is a valid possible next instance |
|
220 entryNextTime = entryInstanceTime; |
|
221 } |
|
222 } |
|
223 |
|
224 if (entryNextTime.TimeUtcL() < bestSoFar.TimeUtcL()) |
|
225 { |
|
226 // This time is better than best time so far so update the best so far |
|
227 bestSoFar = entryNextTime; |
|
228 thisAgnSimpleEntryIndex = i; |
|
229 iEntryWithSameTime.Reset(); |
|
230 iCurrentIndex = -1; |
|
231 } |
|
232 else if (entryNextTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryNextTime.TimeUtcL()!= TCalTime::MaxTime()) |
|
233 { |
|
234 //Store the index of the entry which has the instance time as the "bestSoFar" time |
|
235 iEntryWithSameTime.AppendL(i); |
|
236 } |
|
237 } |
|
238 |
|
239 |
|
240 if (bestSoFar.TimeUtcL() != TCalTime::MaxTime()) |
|
241 { |
|
242 retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar); |
|
243 iCurrentIndexTime = bestSoFar; |
|
244 } |
|
245 |
|
246 return retInstance; |
|
247 } |
|
248 |
|
249 /** Returns the previous instance |
|
250 |
|
251 Loops through all the entries in the cached entry list and finds |
|
252 the latest instance that appears before the current index instance time. |
|
253 |
|
254 @return The previous instance |
|
255 |
|
256 @internalComponent |
|
257 */ |
|
258 CCalInstance* CCalInstanceIteratorUid::PreviousL() |
|
259 { |
|
260 CCalInstance* retInstance = NULL; |
|
261 TInt numOfsameTimeInstance = iEntryWithSameTime.Count(); |
|
262 if(numOfsameTimeInstance > 0 && iCurrentIndex >= 1) |
|
263 { |
|
264 // we should return the last instance in the array to make it consistent with NextL which returns the first entry's instance. |
|
265 return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[--iCurrentIndex]], iCurrentIndexTime); |
|
266 } |
|
267 |
|
268 TCalTime bestSoFar; |
|
269 bestSoFar.SetTimeUtcL(TCalTime::MinTime()); |
|
270 TInt thisAgnSimpleEntryIndex(KErrNotFound); |
|
271 |
|
272 const TInt KEntryCount(iCalLiteEntries.Count()); |
|
273 TInt i(0); |
|
274 for (; i < KEntryCount ; ++i) |
|
275 { |
|
276 TCalTime entryPreviousTime; |
|
277 entryPreviousTime.SetTimeUtcL(TCalTime::MinTime()); |
|
278 |
|
279 CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef(); |
|
280 |
|
281 if (thisEntryRptDef) |
|
282 { |
|
283 TTime entryPreviousTimeUtc(iCurrentIndexTime.TimeUtcL()); |
|
284 TBool instancefound(EFalse); |
|
285 TTime fromTimeUtc; |
|
286 |
|
287 do |
|
288 { |
|
289 fromTimeUtc = entryPreviousTimeUtc - TTimeIntervalMicroSeconds(1); |
|
290 // keep calling until an unexcepted instance is found or there are no more instances |
|
291 instancefound = thisEntryRptDef->NudgePreviousInstanceUtcL(fromTimeUtc, entryPreviousTimeUtc); |
|
292 } |
|
293 while (instancefound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryPreviousTimeUtc) ) ); |
|
294 |
|
295 if (instancefound) |
|
296 { |
|
297 entryPreviousTime.SetTimeUtcL(entryPreviousTimeUtc); |
|
298 } |
|
299 } |
|
300 else |
|
301 { |
|
302 // The entry does not have a repeat rule so it is just a single instance |
|
303 TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry()); |
|
304 |
|
305 if (entryInstanceTime.TimeUtcL() < iCurrentIndexTime.TimeUtcL()) |
|
306 { |
|
307 // The entry's instance time is before the current index time |
|
308 // so it is a valid possible next instance |
|
309 entryPreviousTime = entryInstanceTime; |
|
310 } |
|
311 } |
|
312 |
|
313 if (entryPreviousTime.TimeUtcL() > bestSoFar.TimeUtcL()) |
|
314 { |
|
315 // This time is better than best time so far so update the best so far |
|
316 bestSoFar = entryPreviousTime; |
|
317 thisAgnSimpleEntryIndex = i; |
|
318 iEntryWithSameTime.Reset(); |
|
319 iCurrentIndex = -1; |
|
320 } |
|
321 else if (entryPreviousTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryPreviousTime.TimeUtcL()!= TCalTime::MinTime()) |
|
322 { |
|
323 iEntryWithSameTime.AppendL(thisAgnSimpleEntryIndex); |
|
324 thisAgnSimpleEntryIndex = i; |
|
325 } |
|
326 } |
|
327 |
|
328 if (bestSoFar.TimeUtcL() != TCalTime::MinTime()) |
|
329 { |
|
330 retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar); |
|
331 iCurrentIndexTime = bestSoFar; |
|
332 numOfsameTimeInstance = iEntryWithSameTime.Count(); |
|
333 if(numOfsameTimeInstance>0) |
|
334 { |
|
335 iCurrentIndex = numOfsameTimeInstance; |
|
336 } |
|
337 } |
|
338 |
|
339 return retInstance; |
|
340 } |
|
341 |
|
342 /** To check if there are more instance to be returned by NextL(). |
|
343 |
|
344 Calls NextL() to see if if returns another instance, and then sets the current |
|
345 indexed instance time back to what it was before the call. |
|
346 |
|
347 @return ETrue if there are more instance to be returned by NextL(), |
|
348 EFalse if there are no more instance, and EFalse if there is a problem |
|
349 calculating if there are more instance to be returned by NextL(). |
|
350 |
|
351 @internalComponent |
|
352 */ |
|
353 TBool CCalInstanceIteratorUid::HasMore() const |
|
354 { |
|
355 TBool returnValue(EFalse); |
|
356 TRAP_IGNORE(returnValue = HasMoreL()); |
|
357 return returnValue; |
|
358 } |
|
359 |
|
360 TBool CCalInstanceIteratorUid::HasMoreL() const |
|
361 { |
|
362 TBool returnValue(EFalse); |
|
363 |
|
364 //Store the current state |
|
365 TCalTime storedCurrentIndex = iCurrentIndexTime; |
|
366 TInt storedArrayIndex = iCurrentIndex; |
|
367 RArray<TInt> storedArray; |
|
368 CleanupClosePushL(storedArray); |
|
369 const TInt count = iEntryWithSameTime.Count(); |
|
370 for(TInt ii=0; ii<count;++ii) |
|
371 { |
|
372 storedArray.AppendL(iEntryWithSameTime[ii]); |
|
373 } |
|
374 |
|
375 //Find instances |
|
376 CCalInstance* nextInstance = const_cast<CCalInstanceIteratorUid*>(this)->NextL(); |
|
377 returnValue = (nextInstance != NULL); |
|
378 delete nextInstance; |
|
379 |
|
380 // restore the state |
|
381 const_cast<CCalInstanceIteratorUid*>(this)->iCurrentIndexTime = storedCurrentIndex; |
|
382 iCurrentIndex = storedArrayIndex;//reset index since it could be moved in NextL |
|
383 iEntryWithSameTime.Reset(); |
|
384 const TInt countSortedArray = storedArray.Count(); |
|
385 for(TInt ii=0; ii<countSortedArray;++ii) |
|
386 { |
|
387 iEntryWithSameTime.AppendL(storedArray[ii]); |
|
388 } |
|
389 |
|
390 CleanupStack::PopAndDestroy(&storedArray); |
|
391 |
|
392 return returnValue; |
|
393 } |
|
394 |
|
395 /** Instance iterator count |
|
396 |
|
397 Loops through all the entries in the cached entry list and finds each of the instance counts. |
|
398 The instance count is the sum of all the entries instances. |
|
399 |
|
400 @return The sum of the instance counts for all the entries in the cached list. |
|
401 |
|
402 @internalComponent |
|
403 */ |
|
404 TInt CCalInstanceIteratorUid::Count() const |
|
405 { |
|
406 TInt returnInstanceCount(0); |
|
407 const TInt KEntryCount(iCalLiteEntries.Count()); |
|
408 for (TInt i(0) ; i < KEntryCount ; ++i) |
|
409 { |
|
410 CAgnRptDef* rptDef = iCalLiteEntries[i]->LiteEntry().RptDef(); |
|
411 if (rptDef) |
|
412 { |
|
413 // This gets all the instances generated by the repeat rule |
|
414 TRAPD(error, returnInstanceCount += rptDef->InstanceCountL()); |
|
415 if (error) |
|
416 { |
|
417 // an error has occoured whilst calculating the instance count |
|
418 // so quit and retrun the error code |
|
419 returnInstanceCount = error; |
|
420 break; |
|
421 } |
|
422 |
|
423 // Need to take off valid exception dates |
|
424 if (rptDef->Exceptions()) |
|
425 { |
|
426 returnInstanceCount -= rptDef->Exceptions()->Count(); |
|
427 } |
|
428 } |
|
429 else |
|
430 { |
|
431 // The entry does not have a repeat rule |
|
432 // so it is just a single instance |
|
433 ++returnInstanceCount; |
|
434 } |
|
435 } |
|
436 |
|
437 return returnInstanceCount; |
|
438 } |
|
439 |
|
440 |