|
1 /* |
|
2 * Copyright (c) 2006 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: CalenEditorDataHandler implements all logic of checking and |
|
15 * validating editor data |
|
16 * |
|
17 */ |
|
18 |
|
19 // System includes |
|
20 #include <calendateutils.h> |
|
21 #include <calenagendautils.h> |
|
22 #include <calinstance.h> |
|
23 #include <calalarm.h> |
|
24 #include <calentry.h> |
|
25 #include <calrrule.h> |
|
26 #include <centralrepository.h> |
|
27 #include <calattachment.h> |
|
28 #include <eikenv.h> |
|
29 #include <CalenInterimUtils2.h> |
|
30 #include <calencontext.h> |
|
31 #include <caleninstanceid.h> // TCalenInstanceId |
|
32 #include <calenservices.h> |
|
33 |
|
34 // User includes |
|
35 #include "CalenEditorDataHandler.h" |
|
36 #include "CalendarPrivateCRKeys.h" |
|
37 #include "CalenDefaultEditors.hrh" |
|
38 #include "calenentryutil.h" |
|
39 #include "CleanupResetAndDestroy.h" |
|
40 #include "calenattachmentutils.h" |
|
41 #include "calenattachmentinfo.h" |
|
42 #include "calenattachmentmodel.h" |
|
43 #include "calenunifiededitor.h" |
|
44 #include "calendarui_debug.h" |
|
45 |
|
46 // Constants |
|
47 #define KNoOfDaysInWeek 7 |
|
48 |
|
49 // ======== LOCAL FUNCTIONS ======== |
|
50 |
|
51 // ----------------------------------------------------------------------------- |
|
52 // IsTimed |
|
53 // Returns ETrue if the entry is timed (i.e. an appointment or a |
|
54 // reminder), EFalse otherwise. |
|
55 // (other items were commented in a header). |
|
56 // ----------------------------------------------------------------------------- |
|
57 // |
|
58 static TBool IsTimed( CCalEntry::TType aEntryType ) |
|
59 { |
|
60 TRACE_ENTRY_POINT; |
|
61 |
|
62 TRACE_EXIT_POINT; |
|
63 return aEntryType == CCalEntry::EAppt || aEntryType == CCalEntry::EReminder; |
|
64 } |
|
65 |
|
66 // ----------------------------------------------------------------------------- |
|
67 // ForeverDate |
|
68 // Returns the date which Calendar presumes to be infinitely far in the future. |
|
69 // Used, for example, when setting a repeating meeting to repeat forever. |
|
70 // (other items were commented in a header). |
|
71 // ----------------------------------------------------------------------------- |
|
72 // |
|
73 static TTime ForeverDate() |
|
74 { |
|
75 TRACE_ENTRY_POINT; |
|
76 |
|
77 TTime forever = TTime( TDateTime( ECalenForeverYear, static_cast<TMonth>( ECalenForeverMonth ), |
|
78 ECalenForeverDay, 0, 0, 0, 0) ); |
|
79 |
|
80 TRACE_EXIT_POINT; |
|
81 return forever; |
|
82 } |
|
83 |
|
84 // ----------------------------------------------------------------------------- |
|
85 // IsForeverDate |
|
86 // Returns ETrue if the given date is considered by Calendar to be infinitely |
|
87 // far in the future. |
|
88 // (other items were commented in a header). |
|
89 // ----------------------------------------------------------------------------- |
|
90 // |
|
91 static TBool IsForeverDate( const TTime& aDate ) |
|
92 { |
|
93 TRACE_ENTRY_POINT; |
|
94 |
|
95 TRACE_EXIT_POINT; |
|
96 return CalenDateUtils::OnSameDay( aDate, ForeverDate() ); |
|
97 } |
|
98 |
|
99 // ======== MEMBER FUNCTIONS ======== |
|
100 |
|
101 // --------------------------------------------------------------------------- |
|
102 // CCalenEditorDataHandler::CCalenEditorDataHandler |
|
103 // Constructor. |
|
104 // (other items were commented in a header). |
|
105 // --------------------------------------------------------------------------- |
|
106 // |
|
107 CCalenEditorDataHandler::CCalenEditorDataHandler( |
|
108 CCalEntry& aEntry, |
|
109 const TCalTime& aInstanceDateTime, |
|
110 TBool aIsCreatingNew, |
|
111 TInt aMaxTextEditorLength, |
|
112 MCalenServices& aServices, |
|
113 RArray<TInt>& aCollectionIds) |
|
114 : iEntry( aEntry ), |
|
115 iInstanceDateTime( aInstanceDateTime ), |
|
116 iIsCreatingNew( aIsCreatingNew ), |
|
117 iMaxTextEditorLength( aMaxTextEditorLength ), |
|
118 iServices( aServices ) , iCalendarFieldEdited(EFalse) , iCollectionIds(aCollectionIds) |
|
119 { |
|
120 TRACE_ENTRY_POINT; |
|
121 TRACE_EXIT_POINT; |
|
122 } |
|
123 |
|
124 // --------------------------------------------------------------------------- |
|
125 // CCalenEditorDataHandler::ConstructL |
|
126 // Two phase construction. |
|
127 // (other items were commented in a header). |
|
128 // --------------------------------------------------------------------------- |
|
129 // |
|
130 void CCalenEditorDataHandler::ConstructL() |
|
131 { |
|
132 TRACE_ENTRY_POINT; |
|
133 |
|
134 iEntryType = iEntry.EntryTypeL(); |
|
135 iRecurrenceId = iEntry.RecurrenceIdL(); |
|
136 |
|
137 iOriginal = CCalenEntryUtil::NewL( iEntry, iInstanceDateTime ); |
|
138 iEdited = CCalenEntryUtil::NewL( iEntry, iInstanceDateTime ); |
|
139 if ( IsCreatingNew() ) |
|
140 { |
|
141 SetDefaultNewValuesL( *iOriginal ); // modify iOriginal also |
|
142 SetDefaultNewValuesL( *iEdited ); |
|
143 } |
|
144 else |
|
145 { |
|
146 iInstanceId = iServices.Context().InstanceId(); |
|
147 } |
|
148 |
|
149 |
|
150 TRACE_EXIT_POINT; |
|
151 } |
|
152 |
|
153 // --------------------------------------------------------------------------- |
|
154 // CCalenEditorDataHandler::NewL |
|
155 // Two-phased constructor. |
|
156 // (other items were commented in a header). |
|
157 // --------------------------------------------------------------------------- |
|
158 // |
|
159 CCalenEditorDataHandler* CCalenEditorDataHandler::NewL( |
|
160 CCalEntry& aEntry, |
|
161 const TCalTime& aInstanceDateTime, |
|
162 TBool aIsCreatingNew, |
|
163 TInt aMaxTextEditorLength, |
|
164 MCalenServices& aServices, |
|
165 RArray<TInt>& aCollectionIds) |
|
166 { |
|
167 TRACE_ENTRY_POINT; |
|
168 |
|
169 CCalenEditorDataHandler* self = new( ELeave ) CCalenEditorDataHandler( |
|
170 aEntry, aInstanceDateTime, aIsCreatingNew, aMaxTextEditorLength, aServices,aCollectionIds ); |
|
171 CleanupStack::PushL( self ); |
|
172 self->ConstructL(); |
|
173 CleanupStack::Pop( self ); |
|
174 |
|
175 TRACE_EXIT_POINT; |
|
176 return self; |
|
177 } |
|
178 |
|
179 // --------------------------------------------------------------------------- |
|
180 // CCalenEditorDataHandler::~CCalenEditorDataHandler |
|
181 // Destructor. |
|
182 // (other items were commented in a header). |
|
183 // --------------------------------------------------------------------------- |
|
184 // |
|
185 CCalenEditorDataHandler::~CCalenEditorDataHandler() |
|
186 { |
|
187 TRACE_ENTRY_POINT; |
|
188 |
|
189 delete iOriginal; |
|
190 delete iEdited; |
|
191 |
|
192 TRACE_EXIT_POINT; |
|
193 } |
|
194 |
|
195 // --------------------------------------------------------------------------- |
|
196 // CCalenEditorDataHandler::Edited |
|
197 // Returns the CCalenEditorDataHandler used to represent the entry the |
|
198 // user is currently editing. |
|
199 // (other items were commented in a header). |
|
200 // --------------------------------------------------------------------------- |
|
201 // |
|
202 CCalenEntryUtil& CCalenEditorDataHandler::Edited() |
|
203 { |
|
204 TRACE_ENTRY_POINT; |
|
205 |
|
206 TRACE_EXIT_POINT; |
|
207 return *iEdited; |
|
208 } |
|
209 |
|
210 // --------------------------------------------------------------------------- |
|
211 // CCalenEditorDataHandler::Original |
|
212 // Returns the CCalenEditorDataHandler used to represent the entry the |
|
213 // user originally opened. |
|
214 // (other items were commented in a header). |
|
215 // --------------------------------------------------------------------------- |
|
216 // |
|
217 const CCalenEntryUtil& CCalenEditorDataHandler::Original() const |
|
218 { |
|
219 TRACE_ENTRY_POINT; |
|
220 |
|
221 TRACE_EXIT_POINT; |
|
222 return *iOriginal; |
|
223 } |
|
224 |
|
225 // --------------------------------------------------------------------------- |
|
226 // CCalenEditorDataHandler::Entry |
|
227 // Returns the entry this object is wrapping round. |
|
228 // (other items were commented in a header). |
|
229 // --------------------------------------------------------------------------- |
|
230 // |
|
231 CCalEntry& CCalenEditorDataHandler::Entry() |
|
232 { |
|
233 TRACE_ENTRY_POINT; |
|
234 |
|
235 TRACE_EXIT_POINT; |
|
236 return iEntry; |
|
237 } |
|
238 |
|
239 // --------------------------------------------------------------------------- |
|
240 // CCalenEditorDataHandler::InstanceDateTime |
|
241 // Returns the instance date/time. |
|
242 // (other items were commented in a header). |
|
243 // --------------------------------------------------------------------------- |
|
244 // |
|
245 const TCalTime& CCalenEditorDataHandler::InstanceDateTime() const |
|
246 { |
|
247 TRACE_ENTRY_POINT; |
|
248 |
|
249 TRACE_EXIT_POINT; |
|
250 return iInstanceDateTime; |
|
251 } |
|
252 |
|
253 |
|
254 // --------------------------------------------------------------------------- |
|
255 // CCalenEditorDataHandler::ShouldSaveOrDeleteOrDoNothingL |
|
256 // Works out whether the entry should be deleted, saved, |
|
257 // or whether no action should be taken. |
|
258 // (other items were commented in a header). |
|
259 // --------------------------------------------------------------------------- |
|
260 // |
|
261 CCalenEditorDataHandler::TAction CCalenEditorDataHandler::ShouldSaveOrDeleteOrDoNothingL() |
|
262 { |
|
263 TRACE_ENTRY_POINT; |
|
264 |
|
265 if ( !IsEditedL() ) |
|
266 { |
|
267 // Not edited at all OR |
|
268 // Only added space characters to text fields but not |
|
269 // edited the non-text fields |
|
270 // no need to save the note |
|
271 TRACE_EXIT_POINT; |
|
272 return CCalenEditorDataHandler::EActionNothing; |
|
273 } |
|
274 |
|
275 // *************** THE NOTE IS EDITED ******************** |
|
276 if(IsCreatingNew()) |
|
277 { |
|
278 // ************* EDITED NEW NOTE ********* |
|
279 |
|
280 // Subject && Location && Description are text fields |
|
281 // If text fields as a whole is not empty, we can save the note |
|
282 // If text fields as a whole IS empty, we can STILL save the note |
|
283 // since we edited "non-text" fields |
|
284 if ( !NonTextFieldsEditedL() && AreTextFieldsEmptyL() ) |
|
285 { |
|
286 TRACE_EXIT_POINT; |
|
287 return CCalenEditorDataHandler::EActionNothing; |
|
288 } |
|
289 else |
|
290 { |
|
291 TRACE_EXIT_POINT; |
|
292 return CCalenEditorDataHandler::EActionSave; |
|
293 } |
|
294 } |
|
295 |
|
296 // **************** EDITED OLD NOTE ********** |
|
297 |
|
298 if(AreTextFieldsClearedL() && !NonTextFieldsEditedL()) // subject && location && description |
|
299 { |
|
300 // ***** OLD NOTE + TEXT FIELDS EMPTIED + NON-TEXT FIELDS NOT EDITED |
|
301 // Even if user may have edited non-text fields, |
|
302 // delete the note |
|
303 TRACE_EXIT_POINT; |
|
304 return CCalenEditorDataHandler::EActionDelete; |
|
305 } |
|
306 |
|
307 // ****** OLD NOTE WITH TEXT FIELDS ********** |
|
308 // Save the note, since the text fields contain something |
|
309 TRACE_EXIT_POINT; |
|
310 return CCalenEditorDataHandler::EActionSave; |
|
311 } |
|
312 |
|
313 // --------------------------------------------------------------------------- |
|
314 // CCalenEditorDataHandler::NonTextFieldsEdited |
|
315 // Returns ETrue if any of the non-text fields (e.g. time fields) of the entry |
|
316 // have been edited, EFalse otherwise. |
|
317 // (other items were commented in a header). |
|
318 // --------------------------------------------------------------------------- |
|
319 // |
|
320 TBool CCalenEditorDataHandler::NonTextFieldsEditedL() |
|
321 { |
|
322 TRACE_ENTRY_POINT; |
|
323 |
|
324 TRACE_EXIT_POINT; |
|
325 |
|
326 return ( IsStartDateTimeEdited() || |
|
327 IsEndDateTimeEdited() || |
|
328 IsAlarmEditedL() || |
|
329 IsRepeatRuleEdited() || |
|
330 IsPriorityEdited() || |
|
331 IsCalendarEditedL() || |
|
332 IsAttachmentExists() || |
|
333 IsEventTypeEdited() || |
|
334 AllDayFieldEdited() ); |
|
335 } |
|
336 |
|
337 // --------------------------------------------------------------------------- |
|
338 // CCalenEditorDataHandler::TextFieldsEdited |
|
339 // Returns ETrue if any of the text fields (e.g. summary) of the entry |
|
340 // have been edited, EFalse otherwise. |
|
341 // (other items were commented in a header). |
|
342 // --------------------------------------------------------------------------- |
|
343 // |
|
344 TBool CCalenEditorDataHandler::TextFieldsEdited() |
|
345 { |
|
346 TRACE_ENTRY_POINT; |
|
347 |
|
348 TRACE_EXIT_POINT; |
|
349 |
|
350 return ( IsSummaryEdited() || IsLocationEdited() || IsDescriptionEdited() |
|
351 || IsAttachmentExists() ); |
|
352 } |
|
353 |
|
354 // --------------------------------------------------------------------------- |
|
355 // CCalenEditorDataHandler::IsEditedL |
|
356 // Returns ETrue if the entry has been modified, EFalse otherwise. |
|
357 // (other items were commented in a header). |
|
358 // --------------------------------------------------------------------------- |
|
359 // |
|
360 TBool CCalenEditorDataHandler::IsEditedL() |
|
361 { |
|
362 TRACE_ENTRY_POINT; |
|
363 |
|
364 TRACE_EXIT_POINT; |
|
365 |
|
366 return ( TextFieldsEdited() || NonTextFieldsEditedL() ); |
|
367 } |
|
368 |
|
369 // --------------------------------------------------------------------------- |
|
370 // CCalenEditorDataHandler::WriteChangesToEntryL |
|
371 // Read the data from the form and set it to the entry. |
|
372 // (other items were commented in a header). |
|
373 // --------------------------------------------------------------------------- |
|
374 // |
|
375 void CCalenEditorDataHandler::WriteChangesToEntryL( CalCommon::TRecurrenceRange aRepeatTarget ) |
|
376 { |
|
377 TRACE_ENTRY_POINT; |
|
378 |
|
379 // This is only place where we can read data from CCalEntry. |
|
380 // E.g. when we calculate alarm offset, we need to read start time from |
|
381 // entry, not anymore from CCalenEntryUtil. |
|
382 TBool isNew = IsCreatingNew(); |
|
383 |
|
384 WriteStartAndEndTimesToEntryL( aRepeatTarget ); |
|
385 |
|
386 if ( isNew || IsSummaryEdited() ) |
|
387 { |
|
388 TPtrC summary = Edited().Summary(); |
|
389 // If text is considered empty, always store as KNullDesC |
|
390 if ( CalenAgendaUtils::IsEmptyText( summary ) ) |
|
391 { |
|
392 summary.Set( KNullDesC ); |
|
393 } |
|
394 iEntry.SetSummaryL( summary ); |
|
395 } |
|
396 |
|
397 if ( isNew || IsLocationEdited() ) |
|
398 { |
|
399 TPtrC location = Edited().Location(); |
|
400 // If text is considered empty, always store as KNullDesC |
|
401 if ( CalenAgendaUtils::IsEmptyText( location ) ) |
|
402 { |
|
403 location.Set(KNullDesC); |
|
404 } |
|
405 iEntry.SetLocationL( location ); |
|
406 } |
|
407 |
|
408 if ( isNew || IsDescriptionEdited() ) |
|
409 { |
|
410 iEntry.SetDescriptionL( Edited().Description() ); |
|
411 } |
|
412 |
|
413 // Repeat rule has to be modified in both cases |
|
414 if ( isNew || IsStartDateTimeEdited() || IsRepeatRuleEdited() ) |
|
415 { |
|
416 |
|
417 if ( aRepeatTarget == CalCommon::EThisOnly) |
|
418 { |
|
419 iEntry.ClearRepeatingPropertiesL(); |
|
420 } |
|
421 else if ( Edited().IsRepeating() ) |
|
422 { |
|
423 // If we're an RDate (with repeat type ERepeatOther), don't try to set an RRule, |
|
424 // but don't clear the repeat properties either. |
|
425 if( Edited().RepeatType() != ERepeatOther ) |
|
426 { |
|
427 TCalRRule rrule; |
|
428 |
|
429 CalculateRepeatRuleL( Edited().StartDateTime(), |
|
430 Edited().RepeatType(), |
|
431 Edited().RepeatUntilDateTime(), |
|
432 rrule ); |
|
433 |
|
434 iEntry.SetRRuleL( rrule ); |
|
435 |
|
436 // As there should not be any rdates, remove any that are |
|
437 // still present |
|
438 RArray<TCalTime> emptyList; |
|
439 CleanupClosePushL( emptyList ); |
|
440 iEntry.SetRDatesL( emptyList ); |
|
441 CleanupStack::PopAndDestroy(); // emptyList |
|
442 } |
|
443 else |
|
444 { |
|
445 // The repeat type is ERepeatOther, therefore as |
|
446 // it is impossible to create an entry of type |
|
447 // ERepeat other using the editor either the repeat until |
|
448 // date or the start date must have been changed |
|
449 |
|
450 // The start date/time has changed, in order for the |
|
451 // series to maintain its pattern, any rDates and if |
|
452 // present rRule are moved by the same offset |
|
453 // The repeat type is ERepeatOther, so check if we have any rdates |
|
454 RArray<TCalTime> rDateList; |
|
455 CleanupClosePushL( rDateList ); |
|
456 iEntry.GetRDatesL( rDateList ); |
|
457 TInt count = rDateList.Count(); |
|
458 |
|
459 if ( count == 0 ) |
|
460 { |
|
461 // There are no rdates so the new until and start date can be applied |
|
462 // directly. |
|
463 TCalRRule rrule; |
|
464 |
|
465 CalculateRepeatRuleL( Edited().StartDateTime(), |
|
466 Edited().RepeatType(), |
|
467 Edited().RepeatUntilDateTime(), |
|
468 rrule ); |
|
469 |
|
470 iEntry.SetRRuleL( rrule ); |
|
471 } |
|
472 else |
|
473 { |
|
474 // There are rDates which need to be checked. |
|
475 if ( IsStartDateTimeEdited() ) |
|
476 { |
|
477 // Need to shift any rdates |
|
478 TTime editedStart = iEdited->StartDateTime(); |
|
479 TTime origStart = iOriginal->StartDateTime(); |
|
480 TTimeIntervalMicroSeconds offSet = editedStart.MicroSecondsFrom( origStart ); |
|
481 for ( TInt index = 0; index < count; index++ ) |
|
482 { |
|
483 TCalTime& rDateTime = rDateList[ index ]; |
|
484 TTime shiftedTime = rDateTime.TimeUtcL(); |
|
485 TDateTime before = shiftedTime.DateTime(); |
|
486 shiftedTime += offSet; |
|
487 TDateTime after = shiftedTime.DateTime(); |
|
488 rDateTime.SetTimeUtcL( shiftedTime ); |
|
489 } |
|
490 } |
|
491 |
|
492 // Check and fix the rDates and rRules match the |
|
493 // repeat until date and time. |
|
494 TTime untilTime = Edited().RepeatUntilDateTime(); |
|
495 |
|
496 // Remove any rdates that are after the the repeat until date |
|
497 TInt count = rDateList.Count(); |
|
498 if ( count > 0 ) |
|
499 { |
|
500 TInt index = count - 1; |
|
501 do |
|
502 { |
|
503 TTime lastRDate = CalenDateUtils::BeginningOfDay( rDateList[ index ].TimeLocalL() ); |
|
504 TDateTime before = lastRDate.DateTime(); |
|
505 if ( lastRDate > untilTime ) |
|
506 { |
|
507 rDateList.Remove( index-- ); |
|
508 } |
|
509 else |
|
510 { |
|
511 index = KErrNotFound; |
|
512 } |
|
513 } while ( index != KErrNotFound ); |
|
514 } |
|
515 |
|
516 // Need to check if the end date of the |
|
517 // rrule needs adjusting if it exists. |
|
518 TCalRRule rRule; |
|
519 if ( iEntry.GetRRuleL( rRule ) ) |
|
520 { |
|
521 count = rDateList.Count(); |
|
522 if ( count > 0 ) |
|
523 { |
|
524 // There still exists some rdates, so only need to trim |
|
525 // the rrule if it exists |
|
526 TTime lastRDate = CalenDateUtils::BeginningOfDay( rDateList[ count - 1 ].TimeLocalL() ); |
|
527 const TTime& origUntilDate = Original().RepeatUntilDateTime(); |
|
528 TTime startDT = rRule.DtStart().TimeLocalL(); |
|
529 |
|
530 if ( lastRDate <= origUntilDate && startDT > lastRDate ) |
|
531 { |
|
532 if ( startDT < untilTime) |
|
533 { |
|
534 if( origUntilDate != untilTime) |
|
535 { |
|
536 ApplyUntilDateToRRuleL( rRule, untilTime); |
|
537 iEntry.SetRRuleL( rRule ); |
|
538 } |
|
539 } |
|
540 else |
|
541 { |
|
542 // The repeat start is after the until date |
|
543 // so remove any repeat information. |
|
544 iEntry.ClearRepeatingPropertiesL(); |
|
545 |
|
546 // If the entry date has been moved past the until |
|
547 // date, need to swap the an rDate for the entry. |
|
548 TTime startTime = iEntry.StartTimeL().TimeLocalL(); |
|
549 |
|
550 if ( startTime > untilTime ) |
|
551 { |
|
552 // Find the duration of the entry |
|
553 TTime endTime = iEntry.EndTimeL().TimeLocalL(); |
|
554 TTimeIntervalMinutes duration; |
|
555 //startTime.MinutesFrom( endTime, duration );// for bug: CMCA-745CZ4 |
|
556 endTime.MinutesFrom( startTime, duration ); |
|
557 |
|
558 // Choose the first rDate as the new start time |
|
559 TCalTime newStartTime = rDateList[ 0 ]; |
|
560 endTime = newStartTime.TimeLocalL() + duration; |
|
561 |
|
562 // FIXME. |
|
563 // If there is only one rDate left, the agenda model |
|
564 // will crash if it is deleted. |
|
565 if ( count != 0 ) |
|
566 { |
|
567 rDateList.Remove( 0 ); |
|
568 } |
|
569 |
|
570 TCalTime newEndTime; |
|
571 if ( UseFloatingTimeL() ) |
|
572 { |
|
573 newEndTime.SetTimeLocalFloatingL( endTime ); |
|
574 } |
|
575 else |
|
576 { |
|
577 newEndTime.SetTimeLocalL( endTime ); |
|
578 } |
|
579 |
|
580 iEntry.SetStartAndEndTimeL( newStartTime, newEndTime ); |
|
581 } |
|
582 } |
|
583 } |
|
584 } |
|
585 } |
|
586 |
|
587 iEntry.SetRDatesL( rDateList ); |
|
588 } |
|
589 |
|
590 CleanupStack::PopAndDestroy(); // rDateList |
|
591 } |
|
592 } |
|
593 else |
|
594 { |
|
595 iEntry.ClearRepeatingPropertiesL(); |
|
596 |
|
597 // FIXME As the entry is supposedly not repeating |
|
598 // any rDates should be removed. Unforunately this |
|
599 // is not possible at the moment because removing the |
|
600 // rdates will cause the agenda model to panic |
|
601 // |
|
602 // RArray<TCalTime> emptyList; |
|
603 // CleanupClosePushL( emptyList ); |
|
604 // iEntry.SetRDatesL( emptyList ); |
|
605 // CleanupStack::PopAndDestroy(); // emptyList |
|
606 } |
|
607 } |
|
608 |
|
609 if ( isNew || IsAlarmEditedL() && ( iEntry.StatusL() != CCalEntry::ETodoCompleted ) ) |
|
610 { |
|
611 if ( Edited().IsAlarmActivated() ) |
|
612 { |
|
613 CCalAlarm* alarm = iEntry.AlarmL(); |
|
614 if ( ! alarm ) |
|
615 { |
|
616 alarm = CCalAlarm::NewL(); |
|
617 } |
|
618 CleanupStack::PushL( alarm ); |
|
619 |
|
620 TTime startTime; |
|
621 // ToDos don't have start time! |
|
622 // If we have undated todo with alarm that was taken care earlier |
|
623 if (iEntry.EntryTypeL()==CCalEntry::ETodo) |
|
624 { |
|
625 startTime = iEntry.EndTimeL().TimeLocalL(); |
|
626 } |
|
627 |
|
628 // if this is not todo we use starttime normal way |
|
629 else |
|
630 { |
|
631 startTime = iEntry.StartTimeL().TimeLocalL(); |
|
632 } |
|
633 TCalRRule ignore; |
|
634 TBool isRepeating = iEntry.GetRRuleL( ignore ); |
|
635 |
|
636 // If edit alarm of repeating entry, we have to nudge start |
|
637 // time to instance date |
|
638 if ( isRepeating && aRepeatTarget == CalCommon::EThisAndAll ) |
|
639 { |
|
640 // nudge to instance date; |
|
641 TTime instanceDate = iInstanceDateTime.TimeLocalL(); |
|
642 if ( IsStartDateTimeEdited() ) |
|
643 { |
|
644 instanceDate = Edited().EventDateTime(); |
|
645 } |
|
646 |
|
647 TDateTime insDt = instanceDate.DateTime(); |
|
648 TDateTime startDt = startTime.DateTime(); |
|
649 // Don't use individual setters (SetMonth, SetDay ...), because |
|
650 // they break if month doesn't contain old date |
|
651 // or date to be set. |
|
652 startDt.Set( insDt.Year(), insDt.Month(), insDt.Day(), |
|
653 startDt.Hour(), startDt.Minute(), |
|
654 startDt.Second(), startDt.MicroSecond() ); |
|
655 startTime = TTime( startDt ); |
|
656 } |
|
657 |
|
658 TTime alarmTime = Edited().AlarmDateTime(); |
|
659 |
|
660 TTimeIntervalMinutes offset; |
|
661 startTime.MinutesFrom( alarmTime, offset ); |
|
662 alarm->SetTimeOffset( offset ); |
|
663 |
|
664 iEntry.SetAlarmL( alarm ); |
|
665 CleanupStack::PopAndDestroy( alarm ); |
|
666 } |
|
667 else |
|
668 { |
|
669 iEntry.SetAlarmL( NULL ); |
|
670 } |
|
671 } |
|
672 |
|
673 if ( isNew || IsPriorityEdited() ) |
|
674 { |
|
675 // map priority here |
|
676 TUint priority = 0; |
|
677 switch ( Edited().Priority() ) |
|
678 { |
|
679 case CCalenEntryUtil::ETodoPriorityHigh: |
|
680 priority = 1; |
|
681 break; |
|
682 case CCalenEntryUtil::ETodoPriorityNormal: |
|
683 priority = 2; |
|
684 break; |
|
685 case CCalenEntryUtil::ETodoPriorityLow: |
|
686 priority = 3; |
|
687 break; |
|
688 default: |
|
689 ASSERT( EFalse ); |
|
690 break; |
|
691 } |
|
692 iEntry.SetPriorityL( priority ); |
|
693 } |
|
694 |
|
695 if ( isNew ) |
|
696 { |
|
697 CCalEntry::TReplicationStatus status = CCalEntry::EOpen; |
|
698 switch ( Edited().SynchType() ) |
|
699 { |
|
700 case CCalenEntryUtil::ESynchPrivate: |
|
701 status = CCalEntry::EPrivate; |
|
702 break; |
|
703 case CCalenEntryUtil::ESynchPublic: |
|
704 status = CCalEntry::EOpen; |
|
705 break; |
|
706 case CCalenEntryUtil::ESynchNoSync: |
|
707 status = CCalEntry::ERestricted; |
|
708 break; |
|
709 default: |
|
710 ASSERT( EFalse ); |
|
711 break; |
|
712 } |
|
713 iEntry.SetReplicationStatusL( status ); |
|
714 } |
|
715 |
|
716 /** |
|
717 * S60 settings for new entries |
|
718 */ |
|
719 if ( IsCreatingNew() ) |
|
720 { |
|
721 if ( Edited().EntryType() == CCalEntry::EAnniv ) |
|
722 { |
|
723 TCalRRule rrule( TCalRRule::EYearly ); |
|
724 rrule.SetDtStart( iEntry.StartTimeL() ); |
|
725 rrule.SetInterval( 1 ); |
|
726 rrule.SetCount( 0 ); |
|
727 iEntry.SetRRuleL( rrule ); |
|
728 } |
|
729 } |
|
730 |
|
731 // check for attachments |
|
732 if( isNew || IsAttachmentExists() ) |
|
733 { |
|
734 // TODO: Uncomment this when enabling attachment support |
|
735 AddAttachementsToEntryL(); |
|
736 } |
|
737 TRACE_EXIT_POINT; |
|
738 } |
|
739 |
|
740 // ----------------------------------------------------------------------------- |
|
741 // CCalenEditorDataHandler::ApplyUntilDateToRRuleL |
|
742 // Applies an new until date to a rrule |
|
743 // (other items were commented in a header). |
|
744 // ----------------------------------------------------------------------------- |
|
745 // |
|
746 void CCalenEditorDataHandler::ApplyUntilDateToRRuleL( TCalRRule& aRRule, const TTime& aRepeatUntil ) const |
|
747 { |
|
748 TRACE_ENTRY_POINT; |
|
749 // note repeat is set to forever. |
|
750 if ( ! CalenDateUtils::IsValidDay( aRepeatUntil ) || IsForeverDate( aRepeatUntil ) ) |
|
751 { |
|
752 // Set repeat to forever: |
|
753 aRRule.SetCount( 0 ); |
|
754 } |
|
755 else |
|
756 { |
|
757 // Change repeatuntil so that hours, minutes, ... are same as in start date |
|
758 TDateTime dtUntil = aRepeatUntil.DateTime(); |
|
759 TDateTime dtStart= iEntry.StartTimeL().TimeLocalL().DateTime(); |
|
760 |
|
761 dtUntil.Set( dtUntil.Year(), dtUntil.Month(), dtUntil.Day(), |
|
762 dtStart.Hour(), dtStart.Minute(), dtStart.Second(), dtStart.MicroSecond() ); |
|
763 |
|
764 TCalTime calRepeatUntil; |
|
765 if ( UseFloatingTimeL() ) |
|
766 { |
|
767 calRepeatUntil.SetTimeLocalFloatingL( TTime( dtUntil ) ); |
|
768 } |
|
769 else |
|
770 { |
|
771 calRepeatUntil.SetTimeLocalL( TTime( dtUntil ) ); |
|
772 } |
|
773 aRRule.SetUntil( calRepeatUntil ); |
|
774 } |
|
775 TRACE_EXIT_POINT; |
|
776 } |
|
777 // ----------------------------------------------------------------------------- |
|
778 // CCalenEditorDataHandler::DurationGreaterThanRepeatIntervalError |
|
779 // Returns ETrue if the duration of instances of the meeting is greater than |
|
780 // the repeat period of the series, EFalse otherwise. |
|
781 // (other items were commented in a header). |
|
782 // ----------------------------------------------------------------------------- |
|
783 // |
|
784 TBool CCalenEditorDataHandler::DurationGreaterThanRepeatIntervalError() |
|
785 { |
|
786 TRACE_ENTRY_POINT; |
|
787 TBool isError = EFalse; |
|
788 switch( Edited().RepeatType() ) |
|
789 { |
|
790 case ERepeatDaily: |
|
791 case ERepeatWorkdays: |
|
792 { |
|
793 TTime startDate = Edited().StartDateTime(); |
|
794 TTime endDate = Edited().EndDateTime(); |
|
795 // In case AllDay event end at "12:00am" 24/06/2009. |
|
796 // editor should display EndDate as 23/06/2009. |
|
797 if(Edited().IsAllDayEvent()) |
|
798 { |
|
799 if( endDate > startDate ) |
|
800 { |
|
801 endDate -= TTimeIntervalDays( 1 ); |
|
802 if( endDate < startDate ) |
|
803 { |
|
804 endDate = startDate; |
|
805 } |
|
806 } |
|
807 } |
|
808 TTimeIntervalDays durDays = endDate.DaysFrom( startDate); |
|
809 isError = durDays >= TTimeIntervalDays(1); |
|
810 break; |
|
811 } |
|
812 case ERepeatWeekly: |
|
813 { |
|
814 TTimeIntervalDays durDays = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() ); |
|
815 isError = durDays >= TTimeIntervalDays(7); |
|
816 break; |
|
817 } |
|
818 case ERepeatBiWeekly: |
|
819 { |
|
820 TTimeIntervalDays durDays = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() ); |
|
821 isError = durDays >= TTimeIntervalDays(14); |
|
822 break; |
|
823 } |
|
824 case ERepeatMonthly: |
|
825 { |
|
826 TTimeIntervalMonths durMonths = Edited().EndDateTime().MonthsFrom( Edited().StartDateTime() ); |
|
827 isError = durMonths >= TTimeIntervalMonths(1); |
|
828 break; |
|
829 } |
|
830 case ERepeatYearly: |
|
831 { |
|
832 TTimeIntervalYears durYears = Edited().EndDateTime().YearsFrom( Edited().StartDateTime() ); |
|
833 isError = durYears >= TTimeIntervalYears(1); |
|
834 break; |
|
835 } |
|
836 case ERepeatOther: |
|
837 { |
|
838 isError = EFalse; |
|
839 break; |
|
840 } |
|
841 default: |
|
842 // Not repeating, no error |
|
843 isError = EFalse; |
|
844 break; |
|
845 } |
|
846 TRACE_EXIT_POINT; |
|
847 return isError; |
|
848 } |
|
849 |
|
850 // ----------------------------------------------------------------------------- |
|
851 // CCalenEditorDataHandler::CheckErrorsForThisAndAllL |
|
852 // Check for errors in the form. This function should only be called when the |
|
853 // user has decided they want to edit "This and all" from a prompt, or when the |
|
854 // entry is not repeating. |
|
855 // (other items were commented in a header). |
|
856 // ----------------------------------------------------------------------------- |
|
857 // |
|
858 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckErrorsForThisAndAllL() |
|
859 { |
|
860 TRACE_ENTRY_POINT; |
|
861 |
|
862 // From UI spec: |
|
863 // 5 checks is specified, only one not needed in this phase is 2.1 |
|
864 |
|
865 const TTime start = Edited().StartDateTime(); |
|
866 const TTime end = Edited().EndDateTime(); |
|
867 |
|
868 // 1) Check that entry doesn't end earlier than it starts |
|
869 if ( end < start ) |
|
870 { |
|
871 TRACE_EXIT_POINT; |
|
872 return CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime; |
|
873 } |
|
874 |
|
875 // 2) Repeating entry checks: |
|
876 if ( Edited().IsRepeating() ) |
|
877 { |
|
878 // 2.1) Check that repeat until date is a) later than start date (for new notes) |
|
879 // b) not before start date (for existing notes) |
|
880 TTime repeatUntilDay = CalenDateUtils::BeginningOfDay( |
|
881 Edited().RepeatUntilDateTime() ); |
|
882 |
|
883 TTime repeatStartDay; |
|
884 |
|
885 // if new note or old note isnt repeating |
|
886 // edited.repeatUntil date must be greater than edited.start date |
|
887 // else |
|
888 // if IsRepeatRuleEdited or IsStartDateTimeEdited |
|
889 // //(either one above will make a new rule in which edited.startdate is the start date) |
|
890 // edited.repeatUntil must be greater than edited.start date |
|
891 // else |
|
892 // edited.repeatUntil must be greater than start date on disk |
|
893 |
|
894 TCalRRule rrule; |
|
895 if( IsCreatingNew() || |
|
896 !Entry().GetRRuleL(rrule) || |
|
897 IsRepeatRuleEdited() || |
|
898 IsStartDateTimeEdited() ) |
|
899 { |
|
900 // We don't have an rrule so we can't get the rrule start date, |
|
901 // or user has edited a field that will cause new start date to be used in the new rule. |
|
902 // Use the edited entry's start date. |
|
903 repeatStartDay = CalenDateUtils::BeginningOfDay( start ); |
|
904 } |
|
905 else |
|
906 { |
|
907 // original rrule is valid and new rule will not be created |
|
908 repeatStartDay = CalenDateUtils::BeginningOfDay( rrule.DtStart().TimeLocalL() ); |
|
909 } |
|
910 |
|
911 if ( repeatUntilDay <= repeatStartDay ) |
|
912 { |
|
913 TRACE_EXIT_POINT; |
|
914 return CCalenEditorDataHandler::EFormErrRepeatUntilEarlierThanNote; |
|
915 } |
|
916 |
|
917 if( DurationGreaterThanRepeatIntervalError() ) |
|
918 { |
|
919 TRACE_EXIT_POINT; |
|
920 return CCalenEditorDataHandler::EFormErrDurationGreaterThanRepeatInterval; |
|
921 } |
|
922 // 3) Alarm field checks: |
|
923 TRACE_EXIT_POINT; |
|
924 return CheckAlarmFieldsForErrorsL(ETrue); // user editing the series |
|
925 } |
|
926 |
|
927 // 3) Alarm field checks: |
|
928 TRACE_EXIT_POINT; |
|
929 return CheckAlarmFieldsForErrorsL(); // user editing the series |
|
930 } |
|
931 |
|
932 // ----------------------------------------------------------------------------- |
|
933 // CCalenEditorDataHandler::CheckErrorsForThisOnlyL |
|
934 // Check for errors in the form. This function should only be called when the |
|
935 // user has decided they want to edit "This only" from a prompt, or when the |
|
936 // entry is an exception. |
|
937 // (other items were commented in a header). |
|
938 // ----------------------------------------------------------------------------- |
|
939 // |
|
940 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckErrorsForThisOnlyL( CCalEntry& /*aParentEntry*/, |
|
941 CCalInstanceView& /*aInstanceView*/ ) |
|
942 { |
|
943 TRACE_ENTRY_POINT; |
|
944 |
|
945 const TTime start = Edited().StartDateTime(); |
|
946 const TTime end = Edited().EndDateTime(); |
|
947 |
|
948 // Check that entry doesn't end earlier than it starts |
|
949 if ( end < start ) |
|
950 { |
|
951 TRACE_EXIT_POINT; |
|
952 return CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime; |
|
953 } |
|
954 |
|
955 TError error = CheckForOutOfSequenceL(); |
|
956 |
|
957 if( error != EFormErrNone ) |
|
958 { |
|
959 return error; |
|
960 } |
|
961 |
|
962 // Alarm field checks: |
|
963 TRACE_EXIT_POINT; |
|
964 return CheckAlarmFieldsForErrorsL(); // user creating/editing an exception |
|
965 } |
|
966 |
|
967 // ----------------------------------------------------------------------------- |
|
968 // CCalenEditorDataHandler::CheckForOutOfSequenceL |
|
969 // Checks to see if the instance is being moved out of sequence, relative to |
|
970 // the rest of the series. |
|
971 // (other items were commented in a header). |
|
972 // ----------------------------------------------------------------------------- |
|
973 // |
|
974 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckForOutOfSequenceL() |
|
975 { |
|
976 TRACE_ENTRY_POINT; |
|
977 // Only perform the checks when we change the start or end time of the meeting. |
|
978 if( !IsStartDateTimeEdited() && !IsEndDateTimeEdited() ) |
|
979 { |
|
980 TRACE_EXIT_POINT; |
|
981 return EFormErrNone; |
|
982 } |
|
983 |
|
984 TCalTime prevStart, prevEnd; |
|
985 |
|
986 GetPreviousInstanceTimeL( prevStart, prevEnd ); |
|
987 |
|
988 if( prevStart.TimeLocalL() != Time::NullTTime() ) |
|
989 { |
|
990 // Does the exception end on/after prevEnd? |
|
991 if( Edited().StartDateTime() < prevEnd.TimeLocalL() ) |
|
992 { |
|
993 // Does the exception start after prevStart? |
|
994 if( Edited().StartDateTime() > prevStart.TimeLocalL() ) |
|
995 { |
|
996 TRACE_EXIT_POINT; |
|
997 return EFormErrOverlapsExistingInstance; |
|
998 } |
|
999 else |
|
1000 { |
|
1001 // Does the exception finish after prevStart? |
|
1002 if( Edited().EndDateTime() > prevStart.TimeLocalL() ) |
|
1003 { |
|
1004 TRACE_EXIT_POINT; |
|
1005 return EFormErrOverlapsExistingInstance; |
|
1006 } |
|
1007 else |
|
1008 { |
|
1009 TRACE_EXIT_POINT; |
|
1010 return EFormErrOutOfSequence; |
|
1011 } |
|
1012 } |
|
1013 } |
|
1014 |
|
1015 // Does the exception start on the same day as prevStart? |
|
1016 if( CalenDateUtils::OnSameDay( Edited().StartDateTime(), prevStart.TimeLocalL() ) ) |
|
1017 { |
|
1018 TRACE_EXIT_POINT; |
|
1019 return EFormErrInstanceAlreadyExistsOnThisDay; |
|
1020 } |
|
1021 } |
|
1022 |
|
1023 TCalTime nextStart, nextEnd; |
|
1024 |
|
1025 GetNextInstanceTimeL( nextStart, nextEnd ); |
|
1026 |
|
1027 if( nextStart.TimeLocalL() != Time::NullTTime() ) |
|
1028 { |
|
1029 // Does the exception finish on/before nextStart? |
|
1030 if( Edited().EndDateTime() > nextStart.TimeLocalL() ) |
|
1031 { |
|
1032 // Does the exception finish before nextFinish? |
|
1033 if( Edited().EndDateTime() < nextEnd.TimeLocalL() ) |
|
1034 { |
|
1035 TRACE_EXIT_POINT; |
|
1036 return EFormErrOverlapsExistingInstance; |
|
1037 } |
|
1038 else |
|
1039 { |
|
1040 // Does the exception start before nextFinish? |
|
1041 if( Edited().StartDateTime() < nextEnd.TimeLocalL() ) |
|
1042 { |
|
1043 TRACE_EXIT_POINT; |
|
1044 return EFormErrOverlapsExistingInstance; |
|
1045 } |
|
1046 else |
|
1047 { |
|
1048 TRACE_EXIT_POINT; |
|
1049 return EFormErrOutOfSequence; |
|
1050 } |
|
1051 } |
|
1052 } |
|
1053 |
|
1054 // Does the exception start on the same day as nextStart? |
|
1055 if( CalenDateUtils::OnSameDay( Edited().StartDateTime(), nextStart.TimeLocalL() ) ) |
|
1056 { |
|
1057 TRACE_EXIT_POINT; |
|
1058 return EFormErrInstanceAlreadyExistsOnThisDay; |
|
1059 } |
|
1060 } |
|
1061 |
|
1062 // Does the series have any rdates |
|
1063 RArray<TCalTime> rDateArray; |
|
1064 CleanupClosePushL( rDateArray ); |
|
1065 Entry().GetRDatesL( rDateArray ); |
|
1066 TInt rDateCount = rDateArray.Count(); |
|
1067 |
|
1068 if ( rDateCount > 0 ) |
|
1069 { |
|
1070 // If the series has rdates, check that the exception |
|
1071 // does not overlap or start on the same day |
|
1072 const TTime& startDateTime = Edited().StartDateTime(); |
|
1073 const TTime& endDateTime = Edited().EndDateTime(); |
|
1074 TTimeIntervalMinutes duration; |
|
1075 startDateTime.MinutesFrom( endDateTime, duration ); |
|
1076 |
|
1077 for ( TInt index = 0; index < rDateCount; index++ ) |
|
1078 { |
|
1079 const TTime& rDate = rDateArray[ index ].TimeLocalL(); |
|
1080 |
|
1081 if ( !CalenDateUtils::OnSameDay( Original().StartDateTime(), rDate ) ) |
|
1082 { |
|
1083 // Does the exception start or end on the same day as a rdate. |
|
1084 if ( CalenDateUtils::OnSameDay( startDateTime, rDate ) ) |
|
1085 { |
|
1086 CleanupStack::PopAndDestroy(); // rDateArray |
|
1087 TRACE_EXIT_POINT; |
|
1088 return EFormErrInstanceAlreadyExistsOnThisDay; |
|
1089 } |
|
1090 |
|
1091 // Does the exception overlap an rdate? |
|
1092 TTime rDateEnd = rDate + duration; |
|
1093 if ( endDateTime > rDateEnd && startDateTime < rDate ) |
|
1094 { |
|
1095 CleanupStack::PopAndDestroy(); // rDateArray |
|
1096 TRACE_EXIT_POINT; |
|
1097 return EFormErrOverlapsExistingInstance; |
|
1098 } |
|
1099 } |
|
1100 } |
|
1101 } |
|
1102 |
|
1103 CleanupStack::PopAndDestroy(); // rDateArray |
|
1104 TRACE_EXIT_POINT; |
|
1105 return EFormErrNone; |
|
1106 } |
|
1107 |
|
1108 // ----------------------------------------------------------------------------- |
|
1109 // CCalenEditorDataHandler::GetPreviousInstanceTimeL |
|
1110 // Gets the start and end times of the previous instance. Sets both to a null |
|
1111 // time if there is no instance before the current one |
|
1112 // (other items were commented in a header). |
|
1113 // ----------------------------------------------------------------------------- |
|
1114 // |
|
1115 void CCalenEditorDataHandler::GetPreviousInstanceTimeL( TCalTime& aPreviousStartTime, |
|
1116 TCalTime& aPreviousEndTime ) |
|
1117 { |
|
1118 TRACE_ENTRY_POINT; |
|
1119 |
|
1120 aPreviousStartTime.SetTimeLocalL( Time::NullTTime() ); |
|
1121 aPreviousEndTime.SetTimeLocalL( Time::NullTTime() ); |
|
1122 |
|
1123 RPointerArray<CCalEntry> entries; |
|
1124 CleanupResetAndDestroyPushL(entries); |
|
1125 |
|
1126 EntryViewL().FetchL( Entry().UidL(), entries ); |
|
1127 |
|
1128 TCalTime currentInstanceDate = Entry().RecurrenceIdL(); |
|
1129 if( currentInstanceDate.TimeUtcL() == Time::NullTTime() ) |
|
1130 { |
|
1131 // We must be creating a new exception. Calculate the recurrence id. |
|
1132 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( entries[0]->StartTimeL().TimeLocalL() ); |
|
1133 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() ); |
|
1134 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay ); |
|
1135 } |
|
1136 |
|
1137 TCalRRule rrule; |
|
1138 if( entries[0]->GetRRuleL(rrule) ) |
|
1139 { |
|
1140 TCalenRepeatIndex repeatIndex = CalenNoteDataUtil::RepeatIndexL( *entries[0] ); |
|
1141 TBool keepLooking = ETrue; |
|
1142 RArray<TCalTime> exdates; |
|
1143 CleanupClosePushL( exdates ); |
|
1144 entries[0]->GetExceptionDatesL(exdates); |
|
1145 |
|
1146 // Needed for case ERepeatOther |
|
1147 TCalRRule::TType type( rrule.Type() ); |
|
1148 TInt repeatInterval( rrule.Interval() ); |
|
1149 TCalTime start, end; |
|
1150 TTime previousInstanceTime = Time::NullTTime(); |
|
1151 |
|
1152 while( keepLooking ) |
|
1153 { |
|
1154 // Subtract the repeat interval of the parent. |
|
1155 switch( repeatIndex ) |
|
1156 { |
|
1157 case ERepeatDaily: |
|
1158 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(1) ); |
|
1159 break; |
|
1160 case ERepeatWeekly: |
|
1161 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7) ); |
|
1162 break; |
|
1163 case ERepeatBiWeekly: |
|
1164 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(14) ); |
|
1165 break; |
|
1166 case ERepeatMonthly: |
|
1167 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalMonths(1) ); |
|
1168 break; |
|
1169 case ERepeatYearly: |
|
1170 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalYears(1) ); |
|
1171 break; |
|
1172 case ERepeatWorkdays: |
|
1173 currentInstanceDate.SetTimeLocalL(currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7) ); |
|
1174 case ERepeatOther: |
|
1175 /* This case includes repeating events like: 3 days every week, 3rd weekday of everymonth |
|
1176 that does not fall in any cases above but still have repeating rule*/ |
|
1177 |
|
1178 // Check if the current entry being edited is child entry |
|
1179 // If yes, then put back the child entry time to currentInstanceDate |
|
1180 if(Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime() ) |
|
1181 { |
|
1182 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( Entry().StartTimeL().TimeLocalL() ); |
|
1183 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() ); |
|
1184 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay ); |
|
1185 } |
|
1186 |
|
1187 switch( type ) |
|
1188 { |
|
1189 case TCalRRule::EDaily: |
|
1190 start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(1 * repeatInterval)); |
|
1191 break; |
|
1192 case TCalRRule::EWeekly: |
|
1193 start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7 * repeatInterval)); |
|
1194 break; |
|
1195 case TCalRRule::EMonthly: |
|
1196 // Add 7 days of buffer to cover the cases were gap b/w two instances of the event |
|
1197 // can go beuong 30 days. Ex: Every third wednesday of every month |
|
1198 start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalMonths(repeatInterval)-TTimeIntervalDays(7 * repeatInterval)); |
|
1199 break; |
|
1200 case TCalRRule::EYearly: |
|
1201 // Add 7 days of buffer to cover the cases were gap b/w two instances of the event |
|
1202 // can go beuong 365 days. Ex: Every third wednesday of September of every year |
|
1203 start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalYears(repeatInterval)-TTimeIntervalDays(7 * repeatInterval)); |
|
1204 break; |
|
1205 } |
|
1206 |
|
1207 end.SetTimeLocalL(CalenDateUtils::BeginningOfDay(currentInstanceDate.TimeLocalL())); |
|
1208 previousInstanceTime = GetPreviousInstanceForRepeatOtherL(*entries[0], CalCommon::TCalTimeRange( start, end)); |
|
1209 currentInstanceDate.SetTimeLocalL( previousInstanceTime); |
|
1210 break; |
|
1211 default: |
|
1212 case ERepeatNotRepeated: |
|
1213 keepLooking = EFalse; |
|
1214 break; |
|
1215 } |
|
1216 |
|
1217 // Is currentInstanceDate before parent dt start? |
|
1218 if( currentInstanceDate.TimeLocalL() < entries[0]->StartTimeL().TimeLocalL() ) |
|
1219 { |
|
1220 // There are no instances before the exception |
|
1221 keepLooking = EFalse; |
|
1222 } |
|
1223 else |
|
1224 { |
|
1225 // Is there an exdate on currentInstanceDate? |
|
1226 TBool isExdateOnDay = EFalse; |
|
1227 for(TInt i=0; i<exdates.Count(); ++i) |
|
1228 { |
|
1229 if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() ) |
|
1230 { |
|
1231 isExdateOnDay = ETrue; |
|
1232 // There is an exdate - is there a child associated with the exdate? |
|
1233 for(TInt j=1; j<entries.Count(); ++j) |
|
1234 { |
|
1235 if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() ) |
|
1236 { |
|
1237 // This child is the previous instance. |
|
1238 aPreviousStartTime = entries[j]->StartTimeL(); |
|
1239 aPreviousEndTime = entries[j]->EndTimeL(); |
|
1240 keepLooking = EFalse; |
|
1241 } |
|
1242 } |
|
1243 break; |
|
1244 } |
|
1245 } |
|
1246 |
|
1247 if( !isExdateOnDay ) |
|
1248 { |
|
1249 // The instance exists and hasn't been deleted or made into an exception. |
|
1250 // Use information from the parent to set the start/end times. |
|
1251 aPreviousStartTime = currentInstanceDate; |
|
1252 |
|
1253 TTimeIntervalMinutes duration; |
|
1254 TTime start = entries[0]->StartTimeL().TimeLocalL(); |
|
1255 TTime end = entries[0]->EndTimeL().TimeLocalL(); |
|
1256 end.MinutesFrom( start, duration ); |
|
1257 aPreviousEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration ); |
|
1258 keepLooking = EFalse; |
|
1259 } |
|
1260 } |
|
1261 } |
|
1262 CleanupStack::PopAndDestroy( &exdates ); |
|
1263 } |
|
1264 |
|
1265 CleanupStack::PopAndDestroy(&entries); |
|
1266 |
|
1267 TRACE_EXIT_POINT; |
|
1268 } |
|
1269 |
|
1270 // ----------------------------------------------------------------------------- |
|
1271 // CCalenEditorDataHandler::GetNextInstanceTimeL |
|
1272 // Gets the start and end times of the next instance. Sets both to a null |
|
1273 // time if there is no instance after the current one. |
|
1274 // (other items were commented in a header). |
|
1275 // ----------------------------------------------------------------------------- |
|
1276 // |
|
1277 void CCalenEditorDataHandler::GetNextInstanceTimeL( TCalTime& aNextStartTime, |
|
1278 TCalTime& aNextEndTime ) |
|
1279 { |
|
1280 TRACE_ENTRY_POINT; |
|
1281 |
|
1282 aNextStartTime.SetTimeLocalL( Time::NullTTime() ); |
|
1283 aNextEndTime.SetTimeLocalL( Time::NullTTime() ); |
|
1284 |
|
1285 RPointerArray<CCalEntry> entries; |
|
1286 CleanupResetAndDestroyPushL(entries); |
|
1287 |
|
1288 EntryViewL().FetchL( Entry().UidL(), entries ); |
|
1289 |
|
1290 TCalTime currentInstanceDate = Entry().RecurrenceIdL(); |
|
1291 if( currentInstanceDate.TimeUtcL() == Time::NullTTime() ) |
|
1292 { |
|
1293 // We must be creating a new exception. Calculate the recurrence id. |
|
1294 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( entries[0]->StartTimeL().TimeLocalL() ); |
|
1295 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() ); |
|
1296 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay ); |
|
1297 } |
|
1298 |
|
1299 TCalRRule rrule; |
|
1300 if( entries[0]->GetRRuleL(rrule) ) |
|
1301 { |
|
1302 TCalenRepeatIndex repeatIndex = CalenNoteDataUtil::RepeatIndexL( *entries[0] ); |
|
1303 TBool keepLooking = ETrue; |
|
1304 RArray<TCalTime> exdates; |
|
1305 CleanupClosePushL( exdates ); |
|
1306 entries[0]->GetExceptionDatesL(exdates); |
|
1307 |
|
1308 // Needed for case ERepeatOther |
|
1309 TCalRRule::TType type( rrule.Type() ); |
|
1310 TInt repeatInterval( rrule.Interval() ); |
|
1311 TCalTime start, end; |
|
1312 TTime nextInstanceTime = Time::NullTTime(); |
|
1313 |
|
1314 while( keepLooking ) |
|
1315 { |
|
1316 // Subtract the repeat interval of the parent. |
|
1317 switch( repeatIndex ) |
|
1318 { |
|
1319 case ERepeatDaily: |
|
1320 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1) ); |
|
1321 break; |
|
1322 case ERepeatWeekly: |
|
1323 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7) ); |
|
1324 break; |
|
1325 case ERepeatBiWeekly: |
|
1326 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(14) ); |
|
1327 break; |
|
1328 case ERepeatMonthly: |
|
1329 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalMonths(1) ); |
|
1330 break; |
|
1331 case ERepeatYearly: |
|
1332 currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalYears(1) ); |
|
1333 break; |
|
1334 case ERepeatWorkdays: |
|
1335 currentInstanceDate.SetTimeLocalL(currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7) ); |
|
1336 break; |
|
1337 case ERepeatOther: |
|
1338 { |
|
1339 /* This case includes repeating events like: 3 days every week, 3rd weekday of everymonth |
|
1340 that does not fall in any cases above but still have repeating rule*/ |
|
1341 |
|
1342 // Check if the current entry being edited is child entry |
|
1343 // If yes, then put back the child entry time to currentInstanceDate |
|
1344 if(Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime()) |
|
1345 { |
|
1346 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( Entry().StartTimeL().TimeLocalL() ); |
|
1347 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() ); |
|
1348 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay ); |
|
1349 } |
|
1350 switch( type ) |
|
1351 { |
|
1352 case TCalRRule::EDaily: |
|
1353 end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1 * repeatInterval)); |
|
1354 break; |
|
1355 case TCalRRule::EWeekly: |
|
1356 end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7 * repeatInterval)); |
|
1357 break; |
|
1358 case TCalRRule::EMonthly: |
|
1359 // Add 7 days of buffer to cover the cases were gap b/w two instances of the event |
|
1360 // can go beuong 30 days. Ex: Every third wednesday of every month |
|
1361 end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalMonths(repeatInterval)+TTimeIntervalDays(7 * repeatInterval)); |
|
1362 break; |
|
1363 case TCalRRule::EYearly: |
|
1364 // Add 7 days of buffer to cover the cases were gap b/w two instances of the event |
|
1365 // can go beuong 365 days. Ex: Every third wednesday of September of every year |
|
1366 end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalYears(repeatInterval)+TTimeIntervalDays(7 * repeatInterval)); |
|
1367 break; |
|
1368 } |
|
1369 |
|
1370 start.SetTimeLocalL(CalenDateUtils::BeginningOfDay(currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1))); |
|
1371 |
|
1372 nextInstanceTime = GetNextInstanceForRepeatOtherL(*entries[0], CalCommon::TCalTimeRange( start, end)); |
|
1373 currentInstanceDate.SetTimeLocalL( nextInstanceTime); |
|
1374 break; |
|
1375 } |
|
1376 case ERepeatNotRepeated: |
|
1377 keepLooking = EFalse; |
|
1378 break; |
|
1379 default: |
|
1380 break; |
|
1381 } |
|
1382 |
|
1383 // Is currentInstanceDate after parent dt end? |
|
1384 if( currentInstanceDate.TimeLocalL() > rrule.Until().TimeLocalL() ) |
|
1385 { |
|
1386 // There are no instances before the exception |
|
1387 keepLooking = EFalse; |
|
1388 } |
|
1389 else |
|
1390 { |
|
1391 // Is there an exdate on currentInstanceDate? |
|
1392 TBool isExdateOnDay = EFalse; |
|
1393 for(TInt i=0; i<exdates.Count(); ++i) |
|
1394 { |
|
1395 if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() ) |
|
1396 { |
|
1397 isExdateOnDay = ETrue; |
|
1398 // There is an exdate - is there a child associated with the exdate? |
|
1399 for(TInt j=1; j<entries.Count(); ++j) |
|
1400 { |
|
1401 if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() ) |
|
1402 { |
|
1403 // This child is the previous instance. |
|
1404 aNextStartTime = entries[j]->StartTimeL(); |
|
1405 aNextEndTime = entries[j]->EndTimeL(); |
|
1406 keepLooking = EFalse; |
|
1407 } |
|
1408 } |
|
1409 break; |
|
1410 } |
|
1411 } |
|
1412 |
|
1413 if( !isExdateOnDay ) |
|
1414 { |
|
1415 // The instance exists and hasn't been deleted or made into an exception. |
|
1416 // Use information from the parent to set the start/end times. |
|
1417 aNextStartTime = currentInstanceDate; |
|
1418 |
|
1419 TTimeIntervalMinutes duration; |
|
1420 TTime start = entries[0]->StartTimeL().TimeLocalL(); |
|
1421 TTime end = entries[0]->EndTimeL().TimeLocalL(); |
|
1422 end.MinutesFrom( start, duration ); |
|
1423 aNextEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration ); |
|
1424 keepLooking = EFalse; |
|
1425 } |
|
1426 } |
|
1427 } |
|
1428 CleanupStack::PopAndDestroy( &exdates ); |
|
1429 } |
|
1430 |
|
1431 CleanupStack::PopAndDestroy(&entries); |
|
1432 |
|
1433 TRACE_EXIT_POINT; |
|
1434 } |
|
1435 |
|
1436 // ----------------------------------------------------------------------------- |
|
1437 // CCalenEditorDataHandler::CheckAlarmFieldsForErrorsL |
|
1438 // Check the alarm fields for errors. Returns the error if found, or |
|
1439 // EFormErrNone if no error found. |
|
1440 // (other items were commented in a header). |
|
1441 // ----------------------------------------------------------------------------- |
|
1442 // |
|
1443 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckAlarmFieldsForErrorsL(TBool aSeries) |
|
1444 { |
|
1445 TRACE_ENTRY_POINT; |
|
1446 |
|
1447 TError error = EFormErrNone; |
|
1448 // If alarm not active, no check |
|
1449 if ( Edited().IsAlarmActivated() ) |
|
1450 { |
|
1451 TTime alarm = Edited().AlarmDateTime(); |
|
1452 TTime startTime = Edited().StartDateTime(); |
|
1453 TTime now(Time::NullTTime()); |
|
1454 now.HomeTime(); |
|
1455 |
|
1456 if(IsAlarmInAcceptablePeriod(error, alarm, startTime)) |
|
1457 { |
|
1458 // ask form (not iEntry) if it is repeating |
|
1459 // if we launched an old exception, then form has no repeat field |
|
1460 // if creating a new exception, then form has repeat field |
|
1461 TBool EventIsInFuture = (IsTimedEntry() && (startTime > now)) || |
|
1462 (!IsTimedEntry() && (startTime.DaysFrom(now) >= TTimeIntervalDays(0))); |
|
1463 if( !aSeries && (alarm < now) && ( iEdited->EntryType()!=CCalEntry::EAnniv ) ) |
|
1464 { |
|
1465 // dont let non-repeating future entries have alarms in past |
|
1466 error = EFormErrAlarmTimePast; |
|
1467 } |
|
1468 /* otherwise, save alarm to past: |
|
1469 * new/old non-repeating & in past |
|
1470 * repeating new/old repeating in past/future |
|
1471 */ |
|
1472 } |
|
1473 } |
|
1474 |
|
1475 TRACE_EXIT_POINT; |
|
1476 return error; |
|
1477 } |
|
1478 |
|
1479 // ----------------------------------------------------------------------------- |
|
1480 // CCalenEditorDataHandler::IsAlarmInAcceptablePeriod |
|
1481 // Check alarm time validity |
|
1482 // (other items were commented in a header). |
|
1483 // ----------------------------------------------------------------------------- |
|
1484 // |
|
1485 TBool CCalenEditorDataHandler::IsAlarmInAcceptablePeriod(TError& aError, |
|
1486 const TTime& aAlarmTime, const TTime& aStartTime) const |
|
1487 { |
|
1488 TRACE_ENTRY_POINT; |
|
1489 |
|
1490 TTime upperLimit = IsTimedEntry() ? |
|
1491 aStartTime : |
|
1492 CalenDateUtils::BeginningOfDay(aStartTime) + TTimeIntervalDays(1); |
|
1493 TTime lowerLimit = aStartTime - TTimeIntervalDays(31); |
|
1494 TBool acceptable = ETrue; |
|
1495 if(aAlarmTime < lowerLimit) |
|
1496 { |
|
1497 acceptable = EFalse; |
|
1498 aError = EFormErrAlarmDateTooManyDaysBeforeNote; |
|
1499 } |
|
1500 else if(aAlarmTime > upperLimit) |
|
1501 { |
|
1502 acceptable = EFalse; |
|
1503 aError = EFormErrAlarmTimeLaterThanNote; |
|
1504 } |
|
1505 |
|
1506 TRACE_EXIT_POINT; |
|
1507 return acceptable; |
|
1508 } |
|
1509 |
|
1510 // ----------------------------------------------------------------------------- |
|
1511 // CCalenEditorDataHandler::ForceValidValuesL |
|
1512 // Force the form to use valid values. This function gets called when the user |
|
1513 // forces the application to exit, for example by pressing the off button. |
|
1514 // We attempt to save as much data as possible from the form. |
|
1515 // (other items were commented in a header). |
|
1516 // ----------------------------------------------------------------------------- |
|
1517 // |
|
1518 void CCalenEditorDataHandler::ForceValidValuesL( CalCommon::TRecurrenceRange aRepeatTarget ) |
|
1519 { |
|
1520 TRACE_ENTRY_POINT; |
|
1521 |
|
1522 // Checks and valid values are |
|
1523 // from S60 Calendar UI spec, chapter 4.6.4.1 Exiting Note Editor: |
|
1524 |
|
1525 // We modify values as we go, thus we can't pre-read fields. |
|
1526 // E.g. when start time is needed in check, it should be always read |
|
1527 // from model, because previous check might have modified it. |
|
1528 |
|
1529 // 2) if ends earlier than starts |
|
1530 if ( Edited().EndDateTime() < Edited().StartDateTime() ) |
|
1531 { |
|
1532 // a) (for new entry) set end time equal to start time |
|
1533 if ( IsCreatingNew() ) |
|
1534 { |
|
1535 Edited().SetEndDateTimeL( Edited().StartDateTime() ); |
|
1536 } |
|
1537 // b) (for existing entries) replace with original end time |
|
1538 else |
|
1539 { |
|
1540 Edited().SetEndDateTimeL( Original().EndDateTime() ); |
|
1541 // if still wrong, replace start time also |
|
1542 Edited().SetStartDateTimeL( Original().StartDateTime() ); |
|
1543 } |
|
1544 } // END end < start check |
|
1545 |
|
1546 // 1) Alarm validation |
|
1547 if ( Edited().IsAlarmActivated() ) |
|
1548 { |
|
1549 TTime now; |
|
1550 now.HomeTime(); |
|
1551 |
|
1552 // Note: all three checks are done for each alarm. |
|
1553 // Alarm time is read always again, because modifications are done after each check |
|
1554 |
|
1555 // 1.1) a) if alarm more than 31 days before start, alarm is set 31 days before start |
|
1556 // b) (for todos) - "" - before due date |
|
1557 TTime maxAlarmBeforeStart = Edited().StartDateTime() - TTimeIntervalDays( 31 ); |
|
1558 if ( Edited().AlarmDateTime() < maxAlarmBeforeStart ) |
|
1559 { |
|
1560 Edited().SetAlarmDateTimeL( maxAlarmBeforeStart ); |
|
1561 } |
|
1562 |
|
1563 // 1.2) a) (meetings) if alarm later than start, set it to default alarm time |
|
1564 // b) (for todos & annivs) - "" - later than due date |
|
1565 TTime atLatest = Edited().StartDateTime(); |
|
1566 if(!IsTimedEntry()) |
|
1567 { |
|
1568 atLatest += TTimeIntervalDays(1); |
|
1569 atLatest -= TTimeIntervalSeconds(1); |
|
1570 // at Latest for ToDo/Anniv would be DD @ 23:59:59 |
|
1571 } |
|
1572 if( Edited().AlarmDateTime() > atLatest ) |
|
1573 { |
|
1574 SetDefaultAlarmDateTimeL(); |
|
1575 } |
|
1576 |
|
1577 // 1.3) if alarm is set to passed time, |
|
1578 if ( Edited().AlarmDateTime() < now ) |
|
1579 { |
|
1580 // a) it is set off for |
|
1581 // - new/old NON-REPEATING entries |
|
1582 if (!Edited().IsRepeating() && Edited().EntryType() != CCalEntry::EAnniv ) |
|
1583 { |
|
1584 Edited().SetAlarmOffL(); |
|
1585 } |
|
1586 // b) (for existing entries) it is saved, unless it has failed 1.1 or 1.2 |
|
1587 else |
|
1588 { |
|
1589 // keep, if it is repeating entry, since repeating entries |
|
1590 // can have alarms in past |
|
1591 } |
|
1592 } |
|
1593 } // END alarm checks |
|
1594 |
|
1595 // 3) Repeat rule checks |
|
1596 if ( Edited().IsRepeating() ) |
|
1597 { |
|
1598 // if repeating note's repeat until date |
|
1599 // a) (for new entries) isn't one day later than start date |
|
1600 // b) (for existing entries) is before start date |
|
1601 // set it to one year later from start date |
|
1602 TTime repeatUntilDay = CalenDateUtils::BeginningOfDay( |
|
1603 Edited().RepeatUntilDateTime() ); |
|
1604 TTime startDay = CalenDateUtils::BeginningOfDay( Edited().StartDateTime() ); |
|
1605 if ( ( IsCreatingNew() && repeatUntilDay <= startDay) || |
|
1606 (! IsCreatingNew() && repeatUntilDay < startDay) ) |
|
1607 { |
|
1608 Edited().SetRepeatUntilDateTimeL( startDay + TTimeIntervalYears(1) ); |
|
1609 } |
|
1610 } |
|
1611 |
|
1612 // 4) if due date of todo is passed or invalid, save it with entered date |
|
1613 // no operation (this is just clarification in UI spec |
|
1614 |
|
1615 |
|
1616 // 5) Check for out of sequence for exceptions |
|
1617 // 6) Check for duration > rpt interval for series |
|
1618 |
|
1619 if( aRepeatTarget == CalCommon::EThisOnly ) |
|
1620 { |
|
1621 TError error = CheckForOutOfSequenceL(); |
|
1622 |
|
1623 if( error != EFormErrNone ) |
|
1624 { |
|
1625 // Revert start/end times |
|
1626 Edited().SetStartDateTimeL( Original().StartDateTime() ); |
|
1627 Edited().SetEndDateTimeL( Original().EndDateTime() ); |
|
1628 } |
|
1629 } |
|
1630 else if( aRepeatTarget == CalCommon::EThisAndAll ) |
|
1631 { |
|
1632 if( DurationGreaterThanRepeatIntervalError() ) |
|
1633 { |
|
1634 // Revert start/end times |
|
1635 Edited().SetStartDateTimeL( Original().StartDateTime() ); |
|
1636 Edited().SetEndDateTimeL( Original().EndDateTime() ); |
|
1637 } |
|
1638 } |
|
1639 |
|
1640 TRACE_EXIT_POINT; |
|
1641 } |
|
1642 |
|
1643 // ----------------------------------------------------------------------------- |
|
1644 // CCalenEditorDataHandler::IsOldEntry |
|
1645 // Returns ETrue if the entry was already created previously so that |
|
1646 // we are now editing it, returns EFalse otherwise. |
|
1647 // (other items were commented in a header). |
|
1648 // ----------------------------------------------------------------------------- |
|
1649 // |
|
1650 TBool CCalenEditorDataHandler::IsOldEntry() |
|
1651 { |
|
1652 TRACE_ENTRY_POINT; |
|
1653 |
|
1654 TRACE_EXIT_POINT; |
|
1655 return !IsCreatingNew(); |
|
1656 } |
|
1657 |
|
1658 // ----------------------------------------------------------------------------- |
|
1659 // CCalenEditorDataHandler::AreTextFieldsEmptyL |
|
1660 // Returns ETrue if summary && location && description text fields are all empty |
|
1661 // Returns EFalse otherwise. |
|
1662 // (other items were commented in a header). |
|
1663 // ----------------------------------------------------------------------------- |
|
1664 // |
|
1665 TBool CCalenEditorDataHandler::AreTextFieldsEmptyL() |
|
1666 { |
|
1667 TRACE_ENTRY_POINT; |
|
1668 |
|
1669 // We have to consider texts empty, if only summary is empty, in case |
|
1670 // location is not supported, because location can still exists in database. |
|
1671 TBool summaryAndDescriptionEmpty = CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) && |
|
1672 CalenAgendaUtils::IsEmptyText( iEdited->Description() ); |
|
1673 |
|
1674 if(LocationEnabledInUiL()) |
|
1675 { |
|
1676 TRACE_EXIT_POINT; |
|
1677 return summaryAndDescriptionEmpty && CalenAgendaUtils::IsEmptyText( iEdited->Location() ); |
|
1678 } |
|
1679 |
|
1680 TRACE_EXIT_POINT; |
|
1681 |
|
1682 return summaryAndDescriptionEmpty; // and location is empty implicitly |
|
1683 } |
|
1684 |
|
1685 // ----------------------------------------------------------------------------- |
|
1686 // CCalenEditorDataHandler::AreTextFieldsClearedL |
|
1687 // Returns ETrue if the user cleared the text in the location and summary fields. |
|
1688 // (other items were commented in a header). |
|
1689 // ----------------------------------------------------------------------------- |
|
1690 // |
|
1691 TBool CCalenEditorDataHandler::AreTextFieldsClearedL() |
|
1692 { |
|
1693 TRACE_ENTRY_POINT; |
|
1694 |
|
1695 if ( CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) && |
|
1696 CalenAgendaUtils::IsEmptyText( iEdited->Description() ) ) |
|
1697 { |
|
1698 if ( LocationEnabledInUiL() ) |
|
1699 { |
|
1700 if ( CalenAgendaUtils::IsEmptyText( iEdited->Location() ) ) |
|
1701 { |
|
1702 if ( IsSummaryEmptied() || IsDescriptionEmptied() || IsLocationEmptied() ) |
|
1703 { |
|
1704 TRACE_EXIT_POINT; |
|
1705 return ETrue; |
|
1706 } |
|
1707 } |
|
1708 } |
|
1709 |
|
1710 else if ( IsSummaryEmptied() || IsDescriptionEmptied() ) |
|
1711 { |
|
1712 TRACE_EXIT_POINT; |
|
1713 return ETrue; |
|
1714 } |
|
1715 } |
|
1716 |
|
1717 TRACE_EXIT_POINT; |
|
1718 |
|
1719 return EFalse; |
|
1720 } |
|
1721 |
|
1722 // ----------------------------------------------------------------------------- |
|
1723 // CCalenEditorDataHandler::IsDescriptionEmptied |
|
1724 // Returns ETrue, the description was not empty in original && is empty |
|
1725 // in the edited note |
|
1726 // Returns EFalse, otherwise |
|
1727 // (other items were commented in a header). |
|
1728 // ----------------------------------------------------------------------------- |
|
1729 TBool CCalenEditorDataHandler::IsDescriptionEmptied() |
|
1730 { |
|
1731 TRACE_ENTRY_POINT; |
|
1732 |
|
1733 if( !CalenAgendaUtils::IsEmptyText( iOriginal->Description() ) && |
|
1734 CalenAgendaUtils::IsEmptyText( iEdited->Description() ) ) |
|
1735 { |
|
1736 TRACE_EXIT_POINT; |
|
1737 return ETrue; |
|
1738 } |
|
1739 |
|
1740 TRACE_EXIT_POINT; |
|
1741 |
|
1742 return EFalse; |
|
1743 } |
|
1744 |
|
1745 // ----------------------------------------------------------------------------- |
|
1746 // CCalenEditorDataHandler::IsSummaryEmptied |
|
1747 // Returns ETrue, the summary was not empty in original && is empty |
|
1748 // in the edited note |
|
1749 // Returns EFalse, otherwise |
|
1750 // (other items were commented in a header). |
|
1751 // ----------------------------------------------------------------------------- |
|
1752 TBool CCalenEditorDataHandler::IsSummaryEmptied() |
|
1753 { |
|
1754 TRACE_ENTRY_POINT; |
|
1755 |
|
1756 if( !CalenAgendaUtils::IsEmptyText( iOriginal->Summary() ) && |
|
1757 CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) ) |
|
1758 { |
|
1759 TRACE_EXIT_POINT; |
|
1760 return ETrue; |
|
1761 } |
|
1762 |
|
1763 TRACE_EXIT_POINT; |
|
1764 return EFalse; |
|
1765 } |
|
1766 |
|
1767 // ----------------------------------------------------------------------------- |
|
1768 // CCalenEditorDataHandler::IsLocationEmptied |
|
1769 // Returns ETrue, the summary was not empty in original && is empty |
|
1770 // in the edited note |
|
1771 // Returns EFalse, otherwise |
|
1772 // (other items were commented in a header). |
|
1773 // ----------------------------------------------------------------------------- |
|
1774 TBool CCalenEditorDataHandler::IsLocationEmptied() |
|
1775 { |
|
1776 TRACE_ENTRY_POINT; |
|
1777 |
|
1778 if( !CalenAgendaUtils::IsEmptyText( iOriginal->Location() ) && |
|
1779 CalenAgendaUtils::IsEmptyText( iEdited->Location() ) ) |
|
1780 { |
|
1781 TRACE_EXIT_POINT; |
|
1782 return ETrue; |
|
1783 } |
|
1784 |
|
1785 TRACE_EXIT_POINT; |
|
1786 return EFalse; |
|
1787 } |
|
1788 |
|
1789 // ----------------------------------------------------------------------------- |
|
1790 // CCalenEditorDataHandler::IsEntryTypeEdited |
|
1791 // Returns ETrue if the 'Entry Type' is edited, EFalse otherwise. |
|
1792 // (other items were commented in a header). |
|
1793 // ----------------------------------------------------------------------------- |
|
1794 // |
|
1795 TBool CCalenEditorDataHandler::IsEntryTypeEdited() |
|
1796 { |
|
1797 TRACE_ENTRY_POINT; |
|
1798 |
|
1799 TRACE_EXIT_POINT; |
|
1800 return iOriginal->EntryType() != iEdited->EntryType(); |
|
1801 } |
|
1802 |
|
1803 // ----------------------------------------------------------------------------- |
|
1804 // CCalenEditorDataHandler::IsStartDateTimeEdited |
|
1805 // Returns ETrue if the start date/time has been edited, EFalse otherwise. |
|
1806 // (other items were commented in a header). |
|
1807 // ----------------------------------------------------------------------------- |
|
1808 // |
|
1809 TBool CCalenEditorDataHandler::IsStartDateTimeEdited() |
|
1810 { |
|
1811 TRACE_ENTRY_POINT; |
|
1812 |
|
1813 TBool isEdited = EFalse; |
|
1814 |
|
1815 TTime orgTTime = iOriginal->StartDateTime(); |
|
1816 TTime editedTTime = iEdited->StartDateTime(); |
|
1817 |
|
1818 // Get TDateTime of Original & Edited entries. |
|
1819 TDateTime orgDT = orgTTime.DateTime(); |
|
1820 TDateTime editedDT = editedTTime.DateTime(); |
|
1821 |
|
1822 if( !IsTimedEntry() && IsCreatingNew() ) |
|
1823 { |
|
1824 // For non-timed event,on while creating new entry. |
|
1825 // check for only Date field change only. |
|
1826 if( orgDT.Day() != editedDT.Day() || |
|
1827 orgDT.Month() != editedDT.Month() || |
|
1828 orgDT.Year() != editedDT.Year() ) |
|
1829 { |
|
1830 isEdited = ETrue; |
|
1831 } |
|
1832 } |
|
1833 else |
|
1834 { |
|
1835 |
|
1836 // For timed entry, check for Entry Date/Time Changes |
|
1837 if( orgTTime != editedTTime ) |
|
1838 { |
|
1839 isEdited = ETrue; |
|
1840 } |
|
1841 } |
|
1842 |
|
1843 TRACE_EXIT_POINT; |
|
1844 return isEdited; |
|
1845 |
|
1846 //return iOriginal->StartDateTime() != iEdited->StartDateTime(); |
|
1847 |
|
1848 } |
|
1849 |
|
1850 // ----------------------------------------------------------------------------- |
|
1851 // CCalenEditorDataHandler::IsEndDateTimeEdited |
|
1852 // Returns ETrue if the end date/time has been edited, EFalse otherwise. |
|
1853 // (other items were commented in a header). |
|
1854 // ----------------------------------------------------------------------------- |
|
1855 // |
|
1856 TBool CCalenEditorDataHandler::IsEndDateTimeEdited() |
|
1857 { |
|
1858 TRACE_ENTRY_POINT; |
|
1859 TBool isEdited = EFalse; |
|
1860 |
|
1861 TTime orgTTime = iOriginal->EndDateTime(); |
|
1862 TTime editedTTime = iEdited->EndDateTime(); |
|
1863 |
|
1864 // Get TDateTime of Original & Edited entries. |
|
1865 TDateTime orgDT = orgTTime.DateTime(); |
|
1866 TDateTime editedDT = editedTTime.DateTime(); |
|
1867 |
|
1868 if( !IsTimedEntry() && IsCreatingNew() ) |
|
1869 { |
|
1870 |
|
1871 // For non-timed event, check for only Date field change. |
|
1872 // No need to check for Entry time change. |
|
1873 if( orgDT.Day() != editedDT.Day() || |
|
1874 orgDT.Month() != editedDT.Month() || |
|
1875 orgDT.Year() != editedDT.Year() ) |
|
1876 { |
|
1877 isEdited = ETrue; |
|
1878 } |
|
1879 } |
|
1880 else |
|
1881 { |
|
1882 // For timed entry, check for Entry Date/Time Changes |
|
1883 if( orgTTime != editedTTime ) |
|
1884 { |
|
1885 isEdited = ETrue; |
|
1886 } |
|
1887 } |
|
1888 |
|
1889 TRACE_EXIT_POINT; |
|
1890 return isEdited; |
|
1891 |
|
1892 //return iOriginal->EndDateTime() != iEdited->EndDateTime(); |
|
1893 } |
|
1894 |
|
1895 // ----------------------------------------------------------------------------- |
|
1896 // CCalenEditorDataHandler::IsDescriptionEdited |
|
1897 // Returns ETrue if the description has been modified, EFalse otherwise. |
|
1898 // (other items were commented in a header). |
|
1899 // ----------------------------------------------------------------------------- |
|
1900 // |
|
1901 TBool CCalenEditorDataHandler::IsDescriptionEdited() |
|
1902 { |
|
1903 TRACE_ENTRY_POINT; |
|
1904 |
|
1905 TRACE_EXIT_POINT; |
|
1906 return iOriginal->Description() != iEdited->Description(); |
|
1907 } |
|
1908 |
|
1909 // ----------------------------------------------------------------------------- |
|
1910 // CCalenEditorDataHandler::IsPriorityEdited |
|
1911 // Returns ETrue if the priotity has been modified, EFalse otherwise. |
|
1912 // (other items were commented in a header). |
|
1913 // ----------------------------------------------------------------------------- |
|
1914 // |
|
1915 TBool CCalenEditorDataHandler::IsPriorityEdited() |
|
1916 { |
|
1917 TRACE_ENTRY_POINT; |
|
1918 |
|
1919 TRACE_EXIT_POINT; |
|
1920 return iOriginal->Priority() != iEdited->Priority(); |
|
1921 } |
|
1922 |
|
1923 // ----------------------------------------------------------------------------- |
|
1924 // CCalenEditorDataHandler::IsCalendarEditedL |
|
1925 // Returns ETrue if the calendar filed has been edited, EFalse otherwise. |
|
1926 // (other items were commented in a header). |
|
1927 // ----------------------------------------------------------------------------- |
|
1928 // |
|
1929 TBool CCalenEditorDataHandler::IsCalendarEditedL() |
|
1930 { |
|
1931 TRACE_ENTRY_POINT; |
|
1932 |
|
1933 TRACE_EXIT_POINT; |
|
1934 return iCalendarFieldEdited; |
|
1935 } |
|
1936 |
|
1937 // ----------------------------------------------------------------------------- |
|
1938 // CCalenEditorDataHandler::IsSummaryEdited |
|
1939 // Returns ETrue if the summary has been edited, EFalse otherwise. |
|
1940 // (other items were commented in a header). |
|
1941 // ----------------------------------------------------------------------------- |
|
1942 // |
|
1943 TBool CCalenEditorDataHandler::IsSummaryEdited() |
|
1944 { |
|
1945 TRACE_ENTRY_POINT; |
|
1946 |
|
1947 // For summary and location, we compare only that part of text |
|
1948 // that fits to editor. If it's equal, then we don't go and unnecessarily |
|
1949 // truncate existing data. |
|
1950 TRACE_EXIT_POINT; |
|
1951 return ( iOriginal->Summary().Left( iMaxTextEditorLength ) |
|
1952 != iEdited->Summary().Left( iMaxTextEditorLength ) ); |
|
1953 } |
|
1954 |
|
1955 // ----------------------------------------------------------------------------- |
|
1956 // CCalenEditorDataHandler::IsLocationEdited |
|
1957 // Returns ETrue if the location has been edited, EFalse otherwise. |
|
1958 // (other items were commented in a header). |
|
1959 // ----------------------------------------------------------------------------- |
|
1960 // |
|
1961 TBool CCalenEditorDataHandler::IsLocationEdited() |
|
1962 { |
|
1963 TRACE_ENTRY_POINT; |
|
1964 |
|
1965 // For summary and location, we compare only that part of text |
|
1966 // that fits to editor. If it's equal, then we don't go and unnecessarily |
|
1967 // truncate existing data. |
|
1968 TRACE_EXIT_POINT; |
|
1969 return ( iOriginal->Location().Left( iMaxTextEditorLength ) |
|
1970 != iEdited->Location().Left( iMaxTextEditorLength ) ); |
|
1971 } |
|
1972 |
|
1973 // ----------------------------------------------------------------------------- |
|
1974 // CCalenEditorDataHandler::IsAlarmEditedL |
|
1975 // Returns ETrue if the alarm has been edited, EFalse otherwise. |
|
1976 // (other items were commented in a header). |
|
1977 // ----------------------------------------------------------------------------- |
|
1978 // |
|
1979 TBool CCalenEditorDataHandler::IsAlarmEditedL() |
|
1980 { |
|
1981 TRACE_ENTRY_POINT; |
|
1982 |
|
1983 if ( iOriginal->IsAlarmActivated() && iEdited->IsAlarmActivated() ) |
|
1984 { |
|
1985 // The alarm must be flagged as changed if the interval between the entry start |
|
1986 // and the alarm is different. (We can't just compare alarm times directly because |
|
1987 // the start date of the entry may have changed.) |
|
1988 TTimeIntervalMinutes origOffset, editedOffset; |
|
1989 |
|
1990 User::LeaveIfError( iOriginal->AlarmDateTime().MinutesFrom( iOriginal->StartDateTime(), origOffset ) ); |
|
1991 User::LeaveIfError( iEdited->AlarmDateTime().MinutesFrom( iEdited->StartDateTime(), editedOffset ) ); |
|
1992 |
|
1993 TBool alarmTimeChanged = origOffset != editedOffset; |
|
1994 |
|
1995 TRACE_EXIT_POINT; |
|
1996 return alarmTimeChanged; |
|
1997 } |
|
1998 else |
|
1999 { |
|
2000 TBool statusChanged = iOriginal->IsAlarmActivated() != iEdited->IsAlarmActivated(); |
|
2001 |
|
2002 TRACE_EXIT_POINT; |
|
2003 return statusChanged; |
|
2004 } |
|
2005 } |
|
2006 |
|
2007 // ----------------------------------------------------------------------------- |
|
2008 // CCalenEditorDataHandler::IsRepeatRuleEdited |
|
2009 // Returns ETrue if the repeat rule has been edited, EFalse otherwise. |
|
2010 // (other items were commented in a header). |
|
2011 // ----------------------------------------------------------------------------- |
|
2012 // |
|
2013 TBool CCalenEditorDataHandler::IsRepeatRuleEdited() |
|
2014 { |
|
2015 TRACE_ENTRY_POINT; |
|
2016 |
|
2017 if ( iOriginal->IsRepeating() && iEdited->IsRepeating() ) |
|
2018 { |
|
2019 TBool repeatTypeChanged = iOriginal->RepeatType() != iEdited->RepeatType(); |
|
2020 TBool untilDateChanged = iOriginal->RepeatUntilDateTime() != iEdited->RepeatUntilDateTime(); |
|
2021 |
|
2022 TRACE_EXIT_POINT; |
|
2023 return repeatTypeChanged || untilDateChanged; |
|
2024 } |
|
2025 else |
|
2026 { |
|
2027 TBool statusChanged = iOriginal->IsRepeating() != iEdited->IsRepeating(); |
|
2028 |
|
2029 TRACE_EXIT_POINT; |
|
2030 return statusChanged; |
|
2031 } |
|
2032 } |
|
2033 |
|
2034 // ----------------------------------------------------------------------------- |
|
2035 // CCalenEditorDataHandler::LocationEnabledInUiL |
|
2036 // Returns ETrue if the location is a valid field for this type of entry |
|
2037 // (i.e. meetings & reminders only), EFalse otherwise. |
|
2038 // (other items were commented in a header). |
|
2039 // ----------------------------------------------------------------------------- |
|
2040 // |
|
2041 TBool CCalenEditorDataHandler::LocationEnabledInUiL() |
|
2042 { |
|
2043 TRACE_ENTRY_POINT; |
|
2044 |
|
2045 // Location is enabled for timed entries (i.e. an appointment or a |
|
2046 // reminder) |
|
2047 TRACE_EXIT_POINT; |
|
2048 return IsTimedEntry(); |
|
2049 } |
|
2050 |
|
2051 // ----------------------------------------------------------------------------- |
|
2052 // CCalenEditorDataHandler::IsTimedEntry |
|
2053 // Returns ETrue if this is a timed entry, EFalse otherwise. |
|
2054 // (other items were commented in a header). |
|
2055 // ----------------------------------------------------------------------------- |
|
2056 // |
|
2057 TBool CCalenEditorDataHandler::IsTimedEntry() const |
|
2058 { |
|
2059 TRACE_ENTRY_POINT; |
|
2060 |
|
2061 TRACE_EXIT_POINT; |
|
2062 return IsTimed( iEdited->EntryType() ); |
|
2063 } |
|
2064 |
|
2065 // ----------------------------------------------------------------------------- |
|
2066 // CCalenEditorDataHandler::IsCreatingNew |
|
2067 // Returns ETrue if the user is creating a new entry, EFalse if the user is |
|
2068 // editing an existing entry. |
|
2069 // (other items were commented in a header). |
|
2070 // ----------------------------------------------------------------------------- |
|
2071 // |
|
2072 TBool CCalenEditorDataHandler::IsCreatingNew() const |
|
2073 { |
|
2074 TRACE_ENTRY_POINT; |
|
2075 |
|
2076 TRACE_EXIT_POINT; |
|
2077 return iIsCreatingNew; |
|
2078 } |
|
2079 |
|
2080 // ----------------------------------------------------------------------------- |
|
2081 // CCalenEditorDataHandler::IsStartDateChanged |
|
2082 // Returns ETrue if the start date of the entry has been changed, |
|
2083 // EFalse otherwise. Note that this function only checks the date, |
|
2084 // and not the time of day, of the entry. |
|
2085 // (other items were commented in a header). |
|
2086 // ----------------------------------------------------------------------------- |
|
2087 // |
|
2088 TBool CCalenEditorDataHandler::IsStartDateChanged() |
|
2089 { |
|
2090 TRACE_ENTRY_POINT; |
|
2091 |
|
2092 TRACE_EXIT_POINT; |
|
2093 return ! CalenDateUtils::OnSameDay( iOriginal->StartDateTime(), |
|
2094 iEdited->StartDateTime() ); |
|
2095 } |
|
2096 |
|
2097 // ----------------------------------------------------------------------------- |
|
2098 // CCalenEditorDataHandler::IsAttachmentExists |
|
2099 // Returns ETrue calendar entry is having attachments |
|
2100 // (other items were commented in a header). |
|
2101 // ----------------------------------------------------------------------------- |
|
2102 // |
|
2103 TBool CCalenEditorDataHandler::IsAttachmentExists() |
|
2104 { |
|
2105 TRACE_ENTRY_POINT; |
|
2106 TBool attachmentExits(EFalse); |
|
2107 |
|
2108 // TODO: Uncomment this when enabling attachment support |
|
2109 |
|
2110 if( (iOriginal->AttachmentCount() != iEdited->AttachmentCount()) |
|
2111 || iServices.GetAttachmentData()->NumberOfItems() ) |
|
2112 { |
|
2113 attachmentExits = ETrue; |
|
2114 } |
|
2115 |
|
2116 TRACE_EXIT_POINT; |
|
2117 return attachmentExits; |
|
2118 } |
|
2119 |
|
2120 // ----------------------------------------------------------------------------- |
|
2121 // CCalenEditorDataHandler::IsEventTypeEdited |
|
2122 // (other items were commented in a header). |
|
2123 // ----------------------------------------------------------------------------- |
|
2124 // |
|
2125 TBool CCalenEditorDataHandler::IsEventTypeEdited() |
|
2126 { |
|
2127 TRACE_ENTRY_POINT; |
|
2128 TBool fieldModified = EFalse; |
|
2129 |
|
2130 // Check EventType field is edited for already saved Entry |
|
2131 // For Newly created entry, ignore the EventTypeChange |
|
2132 if( (iOriginal->EntryType() != iEdited->EntryType()) && !IsCreatingNew() ) |
|
2133 { |
|
2134 fieldModified = ETrue; |
|
2135 } |
|
2136 |
|
2137 TRACE_EXIT_POINT; |
|
2138 return fieldModified; |
|
2139 } |
|
2140 |
|
2141 // ----------------------------------------------------------------------------- |
|
2142 // CCalenEditorDataHandler::AllDayFieldEdited |
|
2143 // Returns ETrue if `All day event' line has been modified. |
|
2144 // (other items were commented in a header). |
|
2145 // ----------------------------------------------------------------------------- |
|
2146 // |
|
2147 TBool CCalenEditorDataHandler::AllDayFieldEdited() |
|
2148 { |
|
2149 TRACE_ENTRY_POINT; |
|
2150 TBool fieldModified = EFalse; |
|
2151 |
|
2152 if( iOriginal->IsAllDayEvent() != iEdited->IsAllDayEvent() ) |
|
2153 { |
|
2154 fieldModified = ETrue; |
|
2155 } |
|
2156 |
|
2157 TRACE_EXIT_POINT; |
|
2158 return fieldModified; |
|
2159 } |
|
2160 |
|
2161 // ----------------------------------------------------------------------------- |
|
2162 // CCalenEditorDataHandler::SetDefaultAlarmDateTimeL |
|
2163 // Sets the alarm to the default value. This function is called after the user |
|
2164 // forces an exit, e.g. when pressing the power off button. |
|
2165 // (other items were commented in a header). |
|
2166 // ----------------------------------------------------------------------------- |
|
2167 // |
|
2168 void CCalenEditorDataHandler::SetDefaultAlarmDateTimeL() |
|
2169 { |
|
2170 TRACE_ENTRY_POINT; |
|
2171 |
|
2172 /** |
|
2173 * Default alarm time is UI spec logic. |
|
2174 * It is important that this is here, because there shouldn't be UI spec logic in CCalenEntryUtil, |
|
2175 * only in CCalenEditorDataHandler. |
|
2176 * |
|
2177 * It is still a bit odd, that other set methods are in CCalenEntryUtil but not here. |
|
2178 * Maybe I add wrapper set methods for edited data also in *Handler. |
|
2179 * e.g. void SetAlarmOffL() { Edited().SetAlarmOffL(); } |
|
2180 * |
|
2181 */ |
|
2182 TTime defaultAlarm; |
|
2183 |
|
2184 if ( IsTimedEntry() ) |
|
2185 { |
|
2186 TTimeIntervalMinutes defaultOffsetM( 15 ); // FIXME: should be read from central repository |
|
2187 defaultAlarm = Edited().StartDateTime() - defaultOffsetM; |
|
2188 } |
|
2189 else |
|
2190 { |
|
2191 TTimeIntervalHours defaultOffsetH( -8 ); |
|
2192 defaultAlarm = CalenDateUtils::BeginningOfDay( Edited().EventDateTime() ) - defaultOffsetH; |
|
2193 } |
|
2194 |
|
2195 Edited().SetAlarmOnL( defaultAlarm ); |
|
2196 |
|
2197 TRACE_EXIT_POINT; |
|
2198 } |
|
2199 |
|
2200 // ----------------------------------------------------------------------------- |
|
2201 // CCalenEditorDataHandler::CalculateRepeatRuleL |
|
2202 // Calculates the repeat rule for a given entry. |
|
2203 // (other items were commented in a header). |
|
2204 // ----------------------------------------------------------------------------- |
|
2205 // |
|
2206 void CCalenEditorDataHandler::CalculateRepeatRuleL( |
|
2207 const TTime& aStartDateTime, |
|
2208 TCalenRepeatIndex aNewRepeatType, |
|
2209 const TTime& aRepeatUntil, |
|
2210 TCalRRule& aRRule) |
|
2211 { |
|
2212 TRACE_ENTRY_POINT; |
|
2213 |
|
2214 // FIXME: This is copy-pasted from old implementation. |
|
2215 // This should be rewritten with care. |
|
2216 //If it ain't broke...? |
|
2217 TTime startDateTime = aStartDateTime; |
|
2218 TTime repeatUntil = aRepeatUntil; |
|
2219 |
|
2220 TCalRRule origRRule; |
|
2221 TBool hasOrigRRule = iEntry.GetRRuleL( origRRule ); |
|
2222 |
|
2223 TBool isStartDateSame = CalenDateUtils::OnSameDay( |
|
2224 Original().StartDateTime(), Edited().StartDateTime() ); |
|
2225 |
|
2226 // |
|
2227 // If repeat type is changed, repeat start date |
|
2228 // is replaced to the date of "Start date" field. |
|
2229 // |
|
2230 if ( hasOrigRRule && |
|
2231 isStartDateSame && |
|
2232 aNewRepeatType == Original().RepeatType() ) |
|
2233 { |
|
2234 aRRule = origRRule; // keep the original setting... |
|
2235 // until date changed? |
|
2236 } |
|
2237 else if (aNewRepeatType == ERepeatOther) |
|
2238 { |
|
2239 // prevRptDef is ALWAYS non-NULL in this block, |
|
2240 // because previous note's repeat ALWAYS exists. |
|
2241 aRRule = origRRule; |
|
2242 TCalTime repeatStart; |
|
2243 if ( UseFloatingTimeL() ) |
|
2244 { |
|
2245 repeatStart.SetTimeLocalFloatingL( startDateTime ); |
|
2246 } |
|
2247 else |
|
2248 { |
|
2249 repeatStart.SetTimeLocalL( startDateTime ); |
|
2250 } |
|
2251 aRRule.SetDtStart( repeatStart ); |
|
2252 } |
|
2253 else |
|
2254 { |
|
2255 TCalTime repeatSt; |
|
2256 if ( UseFloatingTimeL() ) |
|
2257 { |
|
2258 repeatSt.SetTimeLocalFloatingL( startDateTime ); |
|
2259 } |
|
2260 else |
|
2261 { |
|
2262 repeatSt.SetTimeLocalL( startDateTime ); |
|
2263 } |
|
2264 aRRule.SetDtStart( repeatSt ); |
|
2265 aRRule.SetInterval( 1 ); |
|
2266 |
|
2267 TInt interval(1); |
|
2268 |
|
2269 switch ( aNewRepeatType ) |
|
2270 { |
|
2271 case (ERepeatDaily): // Daily |
|
2272 { |
|
2273 aRRule.SetType( TCalRRule::EDaily ); |
|
2274 break; |
|
2275 } |
|
2276 case (ERepeatWeekly): // Weekly |
|
2277 { |
|
2278 if (hasOrigRRule && origRRule.Type() == TCalRRule::EDaily && |
|
2279 origRRule.Interval() == 7) |
|
2280 { |
|
2281 // If old note's repeat is every 7 days, |
|
2282 // set repeat to every 7 days to Agenda, NOT every week. |
|
2283 // |
|
2284 aRRule.SetType( TCalRRule::EDaily ); |
|
2285 interval = 7; |
|
2286 } |
|
2287 else |
|
2288 { |
|
2289 aRRule.SetType( TCalRRule::EWeekly ); |
|
2290 |
|
2291 RArray<TDay> dayArray; |
|
2292 CleanupClosePushL( dayArray ); |
|
2293 dayArray.Append( aRRule.DtStart().TimeLocalL().DayNoInWeek() ); |
|
2294 aRRule.SetByDay( dayArray ); |
|
2295 CleanupStack::PopAndDestroy( &dayArray ); |
|
2296 } |
|
2297 break; |
|
2298 } |
|
2299 case (ERepeatBiWeekly): // Bi-weekly |
|
2300 { |
|
2301 if ( hasOrigRRule && origRRule.Type() == TCalRRule::EDaily && |
|
2302 origRRule.Interval() == 14) |
|
2303 { |
|
2304 // If old note's repeat is every 14 days, |
|
2305 // set repeat to every 14 days to Agenda, NOT every 2 weeks. |
|
2306 // |
|
2307 aRRule.SetType( TCalRRule::EDaily ); |
|
2308 interval = 14; |
|
2309 } |
|
2310 else |
|
2311 { |
|
2312 aRRule.SetType( TCalRRule::EWeekly ); |
|
2313 interval = 2; |
|
2314 |
|
2315 RArray<TDay> dayArray; |
|
2316 CleanupClosePushL( dayArray ); |
|
2317 dayArray.Append( aRRule.DtStart().TimeLocalL().DayNoInWeek() ); |
|
2318 aRRule.SetByDay( dayArray ); |
|
2319 CleanupStack::PopAndDestroy( &dayArray ); |
|
2320 } |
|
2321 break; |
|
2322 } |
|
2323 case ERepeatWorkdays:// Weekly |
|
2324 { |
|
2325 TLocale iLocale; |
|
2326 TUint iWorkDays = iLocale.WorkDays(); |
|
2327 if (hasOrigRRule && origRRule.Type() == TCalRRule::EDaily |
|
2328 && origRRule.Interval() == 7) |
|
2329 { |
|
2330 // If old note's repeat is every 7 days, |
|
2331 // set repeat to every 7 days to Agenda, NOT every week. |
|
2332 // |
|
2333 aRRule.SetType(TCalRRule::EDaily); |
|
2334 interval = 7; |
|
2335 } |
|
2336 else |
|
2337 { |
|
2338 aRRule.SetType(TCalRRule::EWeekly); |
|
2339 RArray<TDay> dayArray; |
|
2340 CleanupClosePushL(dayArray); |
|
2341 TInt fixedNum = 1; |
|
2342 TInt ruleday = 0; |
|
2343 for (TInt i =0 ; i < KNoOfDaysInWeek ; i++) |
|
2344 { |
|
2345 ruleday = fixedNum << i; |
|
2346 if(iWorkDays & ruleday) |
|
2347 { |
|
2348 dayArray.Append((TDay)i); |
|
2349 aRRule.SetByDay(dayArray); |
|
2350 } |
|
2351 } |
|
2352 CleanupStack::PopAndDestroy(&dayArray); |
|
2353 } |
|
2354 break; |
|
2355 |
|
2356 } |
|
2357 case (ERepeatMonthly): |
|
2358 // Monthly By Position |
|
2359 { |
|
2360 aRRule.SetType( TCalRRule::EMonthly ); |
|
2361 |
|
2362 RArray<TInt> dateArray; |
|
2363 CleanupClosePushL( dateArray ); |
|
2364 dateArray.Append( aRRule.DtStart().TimeLocalL().DayNoInMonth() ); |
|
2365 aRRule.SetByMonthDay( dateArray ); |
|
2366 CleanupStack::PopAndDestroy( &dateArray ); |
|
2367 |
|
2368 break; |
|
2369 } |
|
2370 case (ERepeatYearly): // Yearly |
|
2371 { |
|
2372 // If old note's repeat is every 12 months, |
|
2373 // set repeat to every 12 months to Agenda, NOT every year. |
|
2374 // |
|
2375 if ( hasOrigRRule && origRRule.Type() == TCalRRule::EMonthly && |
|
2376 origRRule.Interval() == 12) |
|
2377 { |
|
2378 aRRule.SetType( TCalRRule::EMonthly ); |
|
2379 interval = 12; |
|
2380 } |
|
2381 else |
|
2382 { |
|
2383 aRRule.SetType( TCalRRule::EYearly ); |
|
2384 } |
|
2385 break; |
|
2386 } |
|
2387 default: // Repeat item is "Other" |
|
2388 { |
|
2389 interval = aRRule.Interval(); // To copy previous note's interval |
|
2390 break; |
|
2391 } |
|
2392 } |
|
2393 |
|
2394 aRRule.SetInterval( interval ); |
|
2395 } |
|
2396 |
|
2397 // If repeat until is max date of Calendar, |
|
2398 // note repeat is set to forever. |
|
2399 if ( ! CalenDateUtils::IsValidDay(repeatUntil) || IsForeverDate( repeatUntil ) ) |
|
2400 { |
|
2401 // Set repeat to forever: |
|
2402 aRRule.SetCount( 0 ); |
|
2403 } |
|
2404 else |
|
2405 { |
|
2406 // Change repeatuntil so that hours, minutes, ... are same as in start date |
|
2407 TDateTime dtUntil = repeatUntil.DateTime(); |
|
2408 TDateTime dtStart= iEntry.StartTimeL().TimeLocalL().DateTime(); |
|
2409 |
|
2410 dtUntil.Set( dtUntil.Year(), dtUntil.Month(), dtUntil.Day(), |
|
2411 dtStart.Hour(), dtStart.Minute(), dtStart.Second(), dtStart.MicroSecond()); |
|
2412 |
|
2413 TCalTime calRepeatUntil; |
|
2414 if ( UseFloatingTimeL() ) |
|
2415 { |
|
2416 calRepeatUntil.SetTimeLocalFloatingL( TTime( dtUntil ) ); |
|
2417 } |
|
2418 else |
|
2419 { |
|
2420 calRepeatUntil.SetTimeLocalL( TTime( dtUntil ) ); |
|
2421 } |
|
2422 aRRule.SetUntil( calRepeatUntil ); |
|
2423 } |
|
2424 |
|
2425 TRACE_EXIT_POINT; |
|
2426 } |
|
2427 |
|
2428 // ----------------------------------------------------------------------------- |
|
2429 // CCalenEditorDataHandler::SetDefaultNewValuesL |
|
2430 // Sets the default values when creating a new entry. |
|
2431 // (other items were commented in a header). |
|
2432 // ----------------------------------------------------------------------------- |
|
2433 // |
|
2434 void CCalenEditorDataHandler::SetDefaultNewValuesL(CCalenEntryUtil& aData) |
|
2435 { |
|
2436 TRACE_ENTRY_POINT; |
|
2437 |
|
2438 // FIXME: I don't know if this method should be needed or not. |
|
2439 // It's a bit unclear that if pass entry that is new, |
|
2440 // should we set default data in caller (application) or |
|
2441 // here. |
|
2442 // But to replicate old editor functionality, we set in editor |
|
2443 // side |
|
2444 |
|
2445 ASSERT( IsCreatingNew() ); |
|
2446 // start time and end time are taken from passed entry. |
|
2447 // They have to be initialized outside of editors |
|
2448 |
|
2449 // subject, location, description are by default empty |
|
2450 |
|
2451 // repeat rule is by default off |
|
2452 |
|
2453 // alarm is by default off |
|
2454 |
|
2455 // synch value |
|
2456 aData.SetSynchTypeL( CCalenEntryUtil::ESynchPrivate ); |
|
2457 |
|
2458 // priority |
|
2459 aData.SetPriorityL( CCalenEntryUtil::ETodoPriorityNormal ); |
|
2460 |
|
2461 TRACE_EXIT_POINT; |
|
2462 } |
|
2463 |
|
2464 // ----------------------------------------------------------------------------- |
|
2465 // CCalenEditorDataHandler::IsChildL |
|
2466 // Returns ETrue if the entry is a child, EFalse otherwise. |
|
2467 // (other items were commented in a header). |
|
2468 // ----------------------------------------------------------------------------- |
|
2469 // |
|
2470 TBool CCalenEditorDataHandler::IsChildL() const |
|
2471 { |
|
2472 TRACE_ENTRY_POINT; |
|
2473 |
|
2474 TRACE_EXIT_POINT; |
|
2475 return iRecurrenceId.TimeUtcL() != Time::NullTTime(); |
|
2476 } |
|
2477 |
|
2478 // ----------------------------------------------------------------------------- |
|
2479 // CCalenEditorDataHandler::UseFloatingTimeL |
|
2480 // Returns ETrue if the entry should use floating time, EFalse otherwise. |
|
2481 // (other items were commented in a header). |
|
2482 // ----------------------------------------------------------------------------- |
|
2483 // |
|
2484 TBool CCalenEditorDataHandler::UseFloatingTimeL() const |
|
2485 { |
|
2486 TRACE_ENTRY_POINT; |
|
2487 |
|
2488 // Use floating time based on type |
|
2489 // This way we ensure that entries _created_ with Calendar Editors |
|
2490 // are consistent regarding time mode. |
|
2491 // |
|
2492 TRACE_EXIT_POINT; |
|
2493 return (! IsTimedEntry()); // use floating time for non-timed entries |
|
2494 |
|
2495 } |
|
2496 |
|
2497 // ----------------------------------------------------------------------------- |
|
2498 // CCalenEditorDataHandler::WriteStartAndEndTimesToEntryL |
|
2499 // Writes the start and end times from the form to the CCalEntry. |
|
2500 // (other items were commented in a header). |
|
2501 // ----------------------------------------------------------------------------- |
|
2502 // |
|
2503 void CCalenEditorDataHandler::WriteStartAndEndTimesToEntryL( CalCommon::TRecurrenceRange aRepeatTarget ) |
|
2504 { |
|
2505 TRACE_ENTRY_POINT; |
|
2506 |
|
2507 const TBool unDatedTodo=(iEntry.EntryTypeL()==CCalEntry::ETodo) && (iEntry.EndTimeL().TimeLocalL()==Time::NullTTime()); |
|
2508 const TBool unDatedTodoWithAlarm=unDatedTodo && (Edited().IsAlarmActivated()); |
|
2509 |
|
2510 TBool shouldWriteBothTimes = |
|
2511 // For new entries |
|
2512 IsCreatingNew() || |
|
2513 // When creating exception entry (exception entry's time are read from editors) |
|
2514 ( aRepeatTarget != CalCommon::EThisAndAll ) || |
|
2515 // when repeating entry is modified to be non-repeating (entry's times are read from editors) |
|
2516 ( Original().IsRepeating() && ! Edited().IsRepeating() ); |
|
2517 |
|
2518 if ( shouldWriteBothTimes || IsStartDateTimeEdited() || IsEndDateTimeEdited() || unDatedTodoWithAlarm ) |
|
2519 { |
|
2520 |
|
2521 TCalTime entryStart; |
|
2522 TCalTime entryEnd; |
|
2523 |
|
2524 // 1) Initialize entryStart and entryEnd with original times. |
|
2525 // But for todos we need to be careful, because there might not be them originally |
|
2526 // In S60 UI, todos don't have starttime, so we use same for both start and end time. |
|
2527 if (iEntry.EntryTypeL()==CCalEntry::ETodo) |
|
2528 { |
|
2529 // if undated todo and it has alarm activated |
|
2530 if ((iEntry.EndTimeL().TimeLocalL()==Time::NullTTime()) && (Edited().IsAlarmActivated())) |
|
2531 { |
|
2532 entryStart.SetTimeLocalL(Edited().EventDateTime()); |
|
2533 entryEnd.SetTimeLocalL(Edited().EventDateTime()); |
|
2534 shouldWriteBothTimes=ETrue; // Ensures that times are written later |
|
2535 } |
|
2536 else |
|
2537 { |
|
2538 entryStart = iEntry.EndTimeL(); |
|
2539 entryEnd = iEntry.EndTimeL(); |
|
2540 } |
|
2541 } |
|
2542 else |
|
2543 { |
|
2544 entryStart = iEntry.StartTimeL(); |
|
2545 entryEnd = iEntry.EndTimeL(); |
|
2546 } |
|
2547 |
|
2548 // 2) Decide start time |
|
2549 if ( shouldWriteBothTimes || IsStartDateTimeEdited() ) |
|
2550 { |
|
2551 TTime newStart = Edited().StartDateTime(); |
|
2552 TDateTime newStartDT = newStart.DateTime(); |
|
2553 // Special case: |
|
2554 // In case c) only start time (hh:mm) of d) existing a) repeating b) series is edited, |
|
2555 // we need to preserve start date (dd.mm.yyy), because start date in editors |
|
2556 // is instance's start date. |
|
2557 // (Example of problematic cases that brings up, when UI represents |
|
2558 // two different concepts in same start date field) |
|
2559 // a) repeating b) series is edited c) only start time is edited d) existing |
|
2560 if ( Edited().IsRepeating() && aRepeatTarget == CalCommon::EThisAndAll && ! IsStartDateChanged() && ! IsCreatingNew() ) |
|
2561 { |
|
2562 TDateTime oldDt = iEntry.StartTimeL().TimeLocalL().DateTime(); |
|
2563 TDateTime editDt = newStart.DateTime(); |
|
2564 newStart = TTime( TDateTime( oldDt.Year(), oldDt.Month(), oldDt.Day(), |
|
2565 editDt.Hour(), editDt.Minute(), |
|
2566 oldDt.Second(), oldDt.MicroSecond() ) ); |
|
2567 } |
|
2568 else if ( ( Edited().RepeatType() == ERepeatOther ) && IsStartDateChanged() ) |
|
2569 { |
|
2570 // The start time might have been disguised because the entry |
|
2571 // consists of an rRule and rDates. The actual start time |
|
2572 // needs to be extracted |
|
2573 RArray<TCalTime> rDates; |
|
2574 CleanupClosePushL( rDates ); |
|
2575 |
|
2576 iEntry.GetRDatesL( rDates ); |
|
2577 if ( rDates.Count() > 0 ) |
|
2578 { |
|
2579 // As we have rDates, check to see if there is an |
|
2580 // rRule |
|
2581 TCalRRule rRule; |
|
2582 if ( iEntry.GetRRuleL( rRule ) ) |
|
2583 { |
|
2584 TTime firstRDate = rDates[ 0 ].TimeLocalL(); |
|
2585 TTime rRuleStart = iEntry.StartTimeL().TimeLocalL(); |
|
2586 TTime lastRDate = rDates[ rDates.Count() - 1 ].TimeLocalL(); |
|
2587 TTimeIntervalMinutes startDateShiftInterval = 0; |
|
2588 if ( firstRDate < rRuleStart ) |
|
2589 { |
|
2590 // The first rDate is before the start of the rRule |
|
2591 // So adjust the start date accordingly |
|
2592 |
|
2593 User::LeaveIfError( newStart.MinutesFrom( firstRDate, startDateShiftInterval ) ); |
|
2594 } |
|
2595 else |
|
2596 { |
|
2597 // The start of the rRule comes first |
|
2598 User::LeaveIfError( newStart.MinutesFrom( rRuleStart, startDateShiftInterval ) ); |
|
2599 } |
|
2600 |
|
2601 newStart = rRuleStart + startDateShiftInterval; |
|
2602 |
|
2603 TInt rRuleCount = rRule.Count(); |
|
2604 rRule.SetCount( rRuleCount ); |
|
2605 |
|
2606 TCalTime rRuleDT; |
|
2607 if ( UseFloatingTimeL() ) |
|
2608 { |
|
2609 rRuleDT.SetTimeLocalFloatingL( newStart ); |
|
2610 } |
|
2611 else |
|
2612 { |
|
2613 rRuleDT.SetTimeLocalL( newStart ); |
|
2614 } |
|
2615 |
|
2616 rRule.SetDtStart( rRuleDT ); |
|
2617 |
|
2618 // For rearranging the recurrence pattern for an |
|
2619 // entry having rdates |
|
2620 |
|
2621 TInt repeatType = rRule.Type(); |
|
2622 switch ( repeatType ) |
|
2623 { |
|
2624 case ( TCalRRule::EWeekly ): //For Weekly repeating event |
|
2625 { |
|
2626 RArray<TDay> dayArray; |
|
2627 CleanupClosePushL( dayArray ); |
|
2628 dayArray.Append( rRule.DtStart().TimeLocalL().DayNoInWeek() ); |
|
2629 rRule.SetByDay( dayArray ); |
|
2630 CleanupStack::PopAndDestroy( &dayArray ); |
|
2631 |
|
2632 // Adjust the RepeatUntil date |
|
2633 ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() ); |
|
2634 break; |
|
2635 } |
|
2636 case ( TCalRRule::EMonthly ):// For Monthly repeating event |
|
2637 { |
|
2638 RArray<TInt> dateArray; |
|
2639 CleanupClosePushL( dateArray ); |
|
2640 dateArray.Append( rRule.DtStart().TimeLocalL().DayNoInMonth() ); |
|
2641 rRule.SetByMonthDay( dateArray ); |
|
2642 CleanupStack::PopAndDestroy( &dateArray ); |
|
2643 |
|
2644 // Adjust the RepeatUntil date |
|
2645 ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() ); |
|
2646 break; |
|
2647 } |
|
2648 |
|
2649 case ( TCalRRule::EDaily ):// For Daily repeating event |
|
2650 { |
|
2651 TCalRRule curRule; |
|
2652 iEntry.GetRRuleL( curRule ); |
|
2653 |
|
2654 // Adjust the RepeatUntil date |
|
2655 if(lastRDate < curRule.Until().TimeLocalL() ) |
|
2656 { |
|
2657 ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() ); |
|
2658 } |
|
2659 |
|
2660 |
|
2661 break; |
|
2662 } |
|
2663 default: |
|
2664 { |
|
2665 break; |
|
2666 } |
|
2667 } |
|
2668 |
|
2669 |
|
2670 iEntry.SetRRuleL( rRule ); |
|
2671 } |
|
2672 } |
|
2673 |
|
2674 CleanupStack::PopAndDestroy(); // rDates |
|
2675 } |
|
2676 |
|
2677 if ( UseFloatingTimeL() ) |
|
2678 { |
|
2679 entryStart.SetTimeLocalFloatingL( newStart ); |
|
2680 } |
|
2681 else |
|
2682 { |
|
2683 entryStart.SetTimeLocalL( newStart ); |
|
2684 } |
|
2685 } |
|
2686 |
|
2687 // 3) Decide end time |
|
2688 if ( shouldWriteBothTimes || IsEndDateTimeEdited() ) |
|
2689 { |
|
2690 TTime start = Edited().StartDateTime(); |
|
2691 TTime end = Edited().EndDateTime(); |
|
2692 |
|
2693 // For all-day events, we add 24 hours to end date |
|
2694 // to make it full day long |
|
2695 /*if ( iEntryType == CCalEntry::EEvent) |
|
2696 { |
|
2697 end += TTimeIntervalDays(1); |
|
2698 }*/ |
|
2699 |
|
2700 TTimeIntervalMinutes duration; |
|
2701 TInt err = end.MinutesFrom( start, duration ); |
|
2702 ASSERT( err == KErrNone ); |
|
2703 ASSERT( duration >= TTimeIntervalMinutes(0) ); |
|
2704 |
|
2705 if ( UseFloatingTimeL() ) |
|
2706 { |
|
2707 entryEnd.SetTimeLocalFloatingL( entryStart.TimeLocalL() + duration ); |
|
2708 } |
|
2709 else |
|
2710 { |
|
2711 entryEnd.SetTimeLocalL( entryStart.TimeLocalL() + duration ); |
|
2712 } |
|
2713 } |
|
2714 |
|
2715 // If EntryType is changed as Non-timed/Timed entry, along with StartTime(AND/OR)EndTime, |
|
2716 // Both Start/End time TimeMode should be changed accordingly. |
|
2717 if ( UseFloatingTimeL() ) |
|
2718 { |
|
2719 entryStart.SetTimeLocalFloatingL( entryStart.TimeLocalL() ); |
|
2720 entryEnd.SetTimeLocalFloatingL( entryEnd.TimeLocalL() ); |
|
2721 } |
|
2722 else |
|
2723 { |
|
2724 entryStart.SetTimeLocalL( entryStart.TimeLocalL() ); |
|
2725 entryEnd.SetTimeLocalL( entryEnd.TimeLocalL() ); |
|
2726 } |
|
2727 |
|
2728 // Write times to entry |
|
2729 iEntry.SetStartAndEndTimeL( entryStart, entryEnd ); |
|
2730 } |
|
2731 |
|
2732 TRACE_EXIT_POINT; |
|
2733 } |
|
2734 |
|
2735 //---------------------------------------------------------------------- |
|
2736 // CCalenEditorDataHandler::ResetOriginalDataL |
|
2737 // Reset original editor data |
|
2738 // (other items were commented in a header). |
|
2739 //---------------------------------------------------------------------- |
|
2740 void CCalenEditorDataHandler::ResetOriginalDataL() |
|
2741 { |
|
2742 TRACE_ENTRY_POINT; |
|
2743 |
|
2744 if(iOriginal) |
|
2745 { |
|
2746 delete iOriginal; |
|
2747 iOriginal=NULL; |
|
2748 } |
|
2749 iOriginal = CCalenEntryUtil::NewL( iEntry, iInstanceDateTime ); |
|
2750 |
|
2751 TRACE_EXIT_POINT; |
|
2752 } |
|
2753 |
|
2754 //---------------------------------------------------------------------- |
|
2755 // CCalenEditorDataHandler::EntryViewL |
|
2756 // Temp function to get to work |
|
2757 // (other items were commented in a header). |
|
2758 //---------------------------------------------------------------------- |
|
2759 CCalEntryView& CCalenEditorDataHandler::EntryViewL() |
|
2760 { |
|
2761 TRACE_ENTRY_POINT; |
|
2762 |
|
2763 CCalEntryView* entryView = iServices.EntryViewL(CurrentDbCollectionId()); |
|
2764 |
|
2765 TRACE_EXIT_POINT; |
|
2766 return *entryView; |
|
2767 } |
|
2768 |
|
2769 //---------------------------------------------------------------------- |
|
2770 // CCalenEditorDataHandler::InstanceViewL |
|
2771 // Temp function to get to work |
|
2772 // (other items were commented in a header). |
|
2773 //---------------------------------------------------------------------- |
|
2774 CCalInstanceView& CCalenEditorDataHandler::InstanceViewL() |
|
2775 { |
|
2776 TRACE_ENTRY_POINT; |
|
2777 |
|
2778 CCalInstanceView* instanceView = iServices.InstanceViewL(iCollectionIds); |
|
2779 |
|
2780 TRACE_EXIT_POINT; |
|
2781 return *instanceView; |
|
2782 } |
|
2783 |
|
2784 // ----------------------------------------------------------------------------- |
|
2785 // CCalenEditorDataHandler::GetPreviousInstanceForRepeatOtherL() |
|
2786 // Returns the time of the previous instance of a particular repeating entry |
|
2787 // (other items were commented in a header). |
|
2788 // ----------------------------------------------------------------------------- |
|
2789 // |
|
2790 TTime CCalenEditorDataHandler::GetPreviousInstanceForRepeatOtherL(CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange) |
|
2791 { |
|
2792 RPointerArray<CCalInstance> allInstances; |
|
2793 CleanupResetAndDestroyPushL( allInstances ); |
|
2794 |
|
2795 TInt filter; |
|
2796 // Get the entry type to be filtered |
|
2797 switch(aEntry.EntryTypeL()) |
|
2798 { |
|
2799 case CCalEntry::EAppt: |
|
2800 filter = CalCommon::EIncludeAppts; |
|
2801 break; |
|
2802 case CCalEntry::ETodo: |
|
2803 filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos; |
|
2804 break; |
|
2805 case CCalEntry::EEvent: |
|
2806 filter = CalCommon::EIncludeEvents; |
|
2807 break; |
|
2808 case CCalEntry::EReminder: |
|
2809 filter = CalCommon::EIncludeReminder; |
|
2810 break; |
|
2811 case CCalEntry::EAnniv: |
|
2812 filter = CalCommon::EIncludeAnnivs; |
|
2813 break; |
|
2814 default: |
|
2815 filter = CalCommon::EIncludeAll; |
|
2816 break; |
|
2817 }; |
|
2818 |
|
2819 iServices.InstanceViewL()->FindInstanceL( allInstances, |
|
2820 (CalCommon::TCalViewFilterFlags)filter, |
|
2821 timeRange); |
|
2822 |
|
2823 TTime previousTime = Time::NullTTime(); |
|
2824 |
|
2825 for( TInt i = allInstances.Count() - 1; i >= 0; i-- ) |
|
2826 { |
|
2827 if( allInstances[i]->Entry().UidL() == aEntry.UidL() ) |
|
2828 { |
|
2829 TRACE_EXIT_POINT; |
|
2830 previousTime = allInstances[i]->Time().TimeLocalL(); |
|
2831 break; |
|
2832 } |
|
2833 } |
|
2834 |
|
2835 CleanupStack::PopAndDestroy( &allInstances ); |
|
2836 return previousTime; |
|
2837 } |
|
2838 |
|
2839 // ----------------------------------------------------------------------------- |
|
2840 // CCalenEditorDataHandler::GetNextInstanceForRepeatOtherL() |
|
2841 // Returns the time of the next instance of a particular repeating entry |
|
2842 // (other items were commented in a header). |
|
2843 // ----------------------------------------------------------------------------- |
|
2844 // |
|
2845 TTime CCalenEditorDataHandler::GetNextInstanceForRepeatOtherL( CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange ) |
|
2846 { |
|
2847 RPointerArray<CCalInstance> allInstances; |
|
2848 CleanupResetAndDestroyPushL( allInstances ); |
|
2849 |
|
2850 TInt filter; |
|
2851 // Get the entry type to be filtered |
|
2852 switch( aEntry.EntryTypeL() ) |
|
2853 { |
|
2854 case CCalEntry::EAppt: |
|
2855 filter = CalCommon::EIncludeAppts; |
|
2856 break; |
|
2857 case CCalEntry::ETodo: |
|
2858 filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos; |
|
2859 break; |
|
2860 case CCalEntry::EEvent: |
|
2861 filter = CalCommon::EIncludeEvents; |
|
2862 break; |
|
2863 case CCalEntry::EReminder: |
|
2864 filter = CalCommon::EIncludeReminder; |
|
2865 break; |
|
2866 case CCalEntry::EAnniv: |
|
2867 filter = CalCommon::EIncludeAnnivs; |
|
2868 break; |
|
2869 default: |
|
2870 filter = CalCommon::EIncludeAll; |
|
2871 break; |
|
2872 }; |
|
2873 |
|
2874 iServices.InstanceViewL()->FindInstanceL( allInstances, |
|
2875 ( CalCommon::TCalViewFilterFlags )filter, |
|
2876 timeRange); |
|
2877 |
|
2878 TTime nextTime = Time::NullTTime(); |
|
2879 |
|
2880 TInt i( 0 ); |
|
2881 for( ; i < allInstances.Count(); i++ ) |
|
2882 { |
|
2883 if( allInstances[i]->Entry().UidL() == aEntry.UidL() ) |
|
2884 { |
|
2885 TRACE_EXIT_POINT; |
|
2886 nextTime = allInstances[i]->Time().TimeLocalL(); |
|
2887 break; |
|
2888 } |
|
2889 } |
|
2890 |
|
2891 CleanupStack::PopAndDestroy( &allInstances ); |
|
2892 return nextTime; |
|
2893 } |
|
2894 |
|
2895 // ----------------------------------------------------------------------------- |
|
2896 // CCalenEditorDataHandler::SetEntryType |
|
2897 // add attachments to the entry as ccalattachments |
|
2898 // ----------------------------------------------------------------------------- |
|
2899 // |
|
2900 void CCalenEditorDataHandler::SetEntryType( CCalEntry::TType aNewEntryType ) |
|
2901 { |
|
2902 iEntryType = aNewEntryType; |
|
2903 } |
|
2904 |
|
2905 // ----------------------------------------------------------------------------- |
|
2906 // CCalenEditorDataHandler::AddAttachementsToEntryL |
|
2907 // add attachments to the entry as ccalattachments |
|
2908 // ----------------------------------------------------------------------------- |
|
2909 // |
|
2910 void CCalenEditorDataHandler::AddAttachementsToEntryL() |
|
2911 { |
|
2912 TRACE_ENTRY_POINT; |
|
2913 |
|
2914 // Get the list of attachments from model and add them to entry |
|
2915 RPointerArray<CCalenAttachmentInfo> attachmentInfoList; |
|
2916 iServices.GetAttachmentData()->GetAttachmentListL( attachmentInfoList ); |
|
2917 TInt attachmentCount = iEntry.AttachmentCountL(); |
|
2918 TInt modelCount = attachmentInfoList.Count(); |
|
2919 |
|
2920 if( attachmentCount > 0 && modelCount == 0 ) |
|
2921 { |
|
2922 // This means that all the attachments in the entry have been deleted |
|
2923 // by the user. So remove all attchments from the entry |
|
2924 for( int index = 0 ; index < attachmentCount ; index++ ) |
|
2925 { |
|
2926 iEntry.DeleteAttachmentL( *iEntry.AttachmentL( 0 ) ); |
|
2927 } |
|
2928 |
|
2929 // No attachments need to be added at this point, we can simply return. |
|
2930 attachmentInfoList.Close(); |
|
2931 TRACE_EXIT_POINT; |
|
2932 return; |
|
2933 } |
|
2934 |
|
2935 // Delete all the attachmenst of the entry which are not present in the model |
|
2936 TInt currentIndex = 0; |
|
2937 for( TInt index=0; index < attachmentCount; index++ ) |
|
2938 { |
|
2939 CCalAttachment* attachment = iEntry.AttachmentL( currentIndex ); |
|
2940 TBool matchFound = EFalse; |
|
2941 for( int modelIndex = 0 ; modelIndex < modelCount ; modelIndex++ ) |
|
2942 { |
|
2943 CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[ modelIndex ]; |
|
2944 if( attachmentInfo->StoreType() == |
|
2945 CCalenAttachmentInfo::ECalenAttachmentFetchedFromEntry ) |
|
2946 { |
|
2947 // We are only interested in those attachments which have been |
|
2948 // fetched from the entry because any newly added attachments |
|
2949 // will not yet be updated in the entry |
|
2950 RFile attachmentHandle; |
|
2951 CleanupClosePushL( attachmentHandle ); |
|
2952 attachment->FileAttachment()->FetchFileHandleL( attachmentHandle ); |
|
2953 |
|
2954 TFileName systemFileName; |
|
2955 attachmentHandle.FullName( systemFileName ); |
|
2956 |
|
2957 if( systemFileName == attachmentInfo->SystemFileName() ) |
|
2958 { |
|
2959 // There is an attachment in the model which matches the |
|
2960 // attachment in the entry. So do not delete it |
|
2961 matchFound = ETrue; |
|
2962 CleanupStack::PopAndDestroy( &attachmentHandle ); |
|
2963 break; |
|
2964 } |
|
2965 CleanupStack::PopAndDestroy( &attachmentHandle ); |
|
2966 } |
|
2967 } |
|
2968 if( !matchFound ) |
|
2969 { |
|
2970 // There is no matching attachment in the model. Delete it from entry |
|
2971 // This will compress the attachment array. Hence do not increment the currentIndex |
|
2972 iEntry.DeleteAttachmentL( *iEntry.AttachmentL( currentIndex ) ); |
|
2973 } |
|
2974 else |
|
2975 { |
|
2976 // Move to the next attachment |
|
2977 currentIndex++; |
|
2978 } |
|
2979 } |
|
2980 |
|
2981 // Now add the remaining newly added attachments to the entry |
|
2982 for( TInt index=0 ; index< modelCount ; index++ ) |
|
2983 { |
|
2984 CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[ index ]; |
|
2985 if( attachmentInfo->StoreType() == CCalenAttachmentInfo::ECalenNewAttachment ) |
|
2986 { |
|
2987 TParsePtrC fileNameParser(attachmentInfo->FileName()); |
|
2988 RFile fileHandle; |
|
2989 CEikonEnv* eikonEnv = CEikonEnv::Static(); |
|
2990 RFs& fs = eikonEnv->FsSession(); |
|
2991 User::LeaveIfError(fs.ShareProtected()); |
|
2992 |
|
2993 TInt err = fileHandle.Open( fs, attachmentInfo->FileName(), EFileWrite ); |
|
2994 if( KErrNone != err ) |
|
2995 { |
|
2996 attachmentInfoList.Close(); |
|
2997 TRACE_EXIT_POINT; |
|
2998 return; |
|
2999 } |
|
3000 CleanupClosePushL(fileHandle); |
|
3001 |
|
3002 CCalAttachment* attachment = CCalAttachment::NewFileL(fileHandle); |
|
3003 CleanupStack::PopAndDestroy(&fileHandle); |
|
3004 |
|
3005 CleanupStack::PushL( attachment ); |
|
3006 // Sets the label for the attachment |
|
3007 attachment->SetLabelL( fileNameParser.NameAndExt() ); |
|
3008 // Sets mime type for the attachment |
|
3009 attachment->SetMimeTypeL( attachmentInfo->DataType().Des8() ); |
|
3010 attachment->SetAttribute(CCalAttachment::EExportInline); |
|
3011 iEntry.AddAttachmentL( *attachment ); |
|
3012 CleanupStack::Pop( attachment ); |
|
3013 } |
|
3014 } |
|
3015 attachmentInfoList.Close(); |
|
3016 |
|
3017 TRACE_EXIT_POINT; |
|
3018 } |
|
3019 |
|
3020 |
|
3021 // ----------------------------------------------------------------------------- |
|
3022 // CCalenEditorDataHandler::SetCalendarFieldEditedL |
|
3023 // Set if calendar is been edited or not with previous and current collection id |
|
3024 // ----------------------------------------------------------------------------- |
|
3025 // |
|
3026 void CCalenEditorDataHandler::SetCalendarFieldEditedL(TBool aEdited , |
|
3027 TCalCollectionId aPreviousDbColId, |
|
3028 TCalCollectionId aCurrentDbColId) |
|
3029 { |
|
3030 TRACE_ENTRY_POINT |
|
3031 iCalendarFieldEdited = aEdited; |
|
3032 iPreviousDbColId = aPreviousDbColId; |
|
3033 iCurrentDbColId = aCurrentDbColId; |
|
3034 TRACE_EXIT_POINT |
|
3035 } |
|
3036 |
|
3037 // ----------------------------------------------------------------------------- |
|
3038 // CCalenEditorDataHandler::PreviousDbCollectionId |
|
3039 // Get previous collection id |
|
3040 // ----------------------------------------------------------------------------- |
|
3041 // |
|
3042 TCalCollectionId CCalenEditorDataHandler::PreviousDbCollectionId() |
|
3043 { |
|
3044 TRACE_ENTRY_POINT |
|
3045 TRACE_EXIT_POINT |
|
3046 return iPreviousDbColId; |
|
3047 } |
|
3048 |
|
3049 // ----------------------------------------------------------------------------- |
|
3050 // CCalenEditorDataHandler::CurrentDbCollectionId |
|
3051 // Get current collection id |
|
3052 // ----------------------------------------------------------------------------- |
|
3053 // |
|
3054 TCalCollectionId CCalenEditorDataHandler::CurrentDbCollectionId() |
|
3055 { |
|
3056 TRACE_ENTRY_POINT |
|
3057 TRACE_EXIT_POINT |
|
3058 return iCurrentDbColId; |
|
3059 } |
|
3060 |
|
3061 // ----------------------------------------------------------------------------- |
|
3062 // CCalenEditorDataHandler::CalenInstanceId |
|
3063 // Returns the instance id. |
|
3064 // (other items were commented in a header). |
|
3065 // ----------------------------------------------------------------------------- |
|
3066 // |
|
3067 const TCalenInstanceId CCalenEditorDataHandler::CalenInstanceId() |
|
3068 { |
|
3069 TRACE_ENTRY_POINT; |
|
3070 |
|
3071 TRACE_EXIT_POINT; |
|
3072 |
|
3073 return iInstanceId; |
|
3074 } |
|
3075 |
|
3076 // End of file --Don't remove this. |