|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <s32mem.h> |
|
17 #include <vtzrules.h> |
|
18 #include <utf.h> |
|
19 #include <tz.h> |
|
20 |
|
21 #include <calentry.h> |
|
22 #include <calcontent.h> |
|
23 #include <calrrule.h> |
|
24 #include <caluser.h> |
|
25 #include <calalarm.h> |
|
26 #include <calattachment.h> |
|
27 |
|
28 #include "agmvcal.h" |
|
29 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
30 #include <vpropbinaryfile.h> |
|
31 #endif |
|
32 |
|
33 |
|
34 /** Specifies number of years backward from current year for which DAYLIGHT properties are exported.*/ |
|
35 const TInt KDaylightPropertyYearsBackwards(2); |
|
36 |
|
37 /** Specifies number of years forward from current year, or the repeat start year, for which DAYLIGHT properties are exported.*/ |
|
38 const TInt KDaylightPropertyYearsForwards(5); |
|
39 |
|
40 |
|
41 // Utility method to ensure proper cleanup in OOM |
|
42 // |
|
43 void CAgendaEntryToVCalConverter::ResetAndDestroyArrayOfParams(TAny* aObject) |
|
44 { |
|
45 CArrayPtr<CParserParam>* array=reinterpret_cast<CArrayPtr<CParserParam>*>(aObject); |
|
46 if (array) |
|
47 { |
|
48 array->ResetAndDestroy(); |
|
49 } |
|
50 delete array; |
|
51 } |
|
52 |
|
53 void CAgendaEntryToVCalConverter::ResetAndDestroyArrayOfVersitDateTime(TAny* aObject) |
|
54 { |
|
55 CArrayPtr<TVersitDateTime>* array=reinterpret_cast<CArrayPtr<TVersitDateTime>*>(aObject); |
|
56 if (array) |
|
57 { |
|
58 array->ResetAndDestroy(); |
|
59 } |
|
60 delete array; |
|
61 } |
|
62 |
|
63 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
64 * Public |
|
65 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
66 |
|
67 // Export agenda entry aEntry to the given parser |
|
68 // |
|
69 void CAgendaEntryToVCalConverter::ExportEntryL(CCalEntry* aEntry, CVersitParser& aParser) |
|
70 { |
|
71 CParserVCalEntity* entity = CParserVCalEntity::NewL(); |
|
72 CleanupStack::PushL(entity); |
|
73 |
|
74 if (aEntry->EntryTypeL() == CCalEntry::ETodo) |
|
75 { |
|
76 entity->SetEntityNameL(KVersitVarTokenVTODO); |
|
77 } |
|
78 else |
|
79 { |
|
80 entity->SetEntityNameL(KVersitVarTokenVEVENT); |
|
81 } |
|
82 |
|
83 if ((aEntry->StartTimeL()).TimeMode() == TCalTime::EFloating) |
|
84 { |
|
85 iTimeType = TVersitDateTime::EIsMachineLocal; |
|
86 iTimeFlag = TVersitDateTime::EExportLeaveAsLocalTime; |
|
87 } |
|
88 else |
|
89 { |
|
90 iTimeType=TVersitDateTime::EIsUTC; |
|
91 iTimeFlag=TVersitDateTime::EExportTimeZoneDesignator; |
|
92 } |
|
93 |
|
94 AddEntryPropertiesL(aEntry, *entity); |
|
95 CleanupStack::Pop(); // entity |
|
96 aParser.AddEntityL(entity); // takes ownership |
|
97 } |
|
98 |
|
99 CAgendaEntryToVCalConverter::~CAgendaEntryToVCalConverter() |
|
100 { |
|
101 } |
|
102 |
|
103 |
|
104 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
105 * Private |
|
106 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
|
107 |
|
108 /** AddTzPropertyL() |
|
109 * |
|
110 * Adds TZ property to aParser. |
|
111 * |
|
112 * @param aParser - a vCal entity or sub-entity (VEVENT or VTODO); |
|
113 * @param aStdOffset - standard time zone offset from UTC in seconds. |
|
114 */ |
|
115 void CAgendaEntryToVCalConverter::AddTzPropertyL(CVersitParser& aParser, |
|
116 TTimeIntervalSeconds aStdOffsetInSeconds) |
|
117 { |
|
118 if (!iAddedTzProperty) |
|
119 { |
|
120 CParserPropertyValue* vValue = new (ELeave) CParserPropertyValueTimeZone(aStdOffsetInSeconds); |
|
121 CleanupStack::PushL(vValue); |
|
122 |
|
123 CParserProperty* vProp = CParserProperty::NewL(*vValue, KVersitTokenTZ, NULL); |
|
124 CleanupStack::Pop(vValue); |
|
125 |
|
126 aParser.AddPropertyL(vProp); |
|
127 } |
|
128 iAddedTzProperty = ETrue; |
|
129 } |
|
130 |
|
131 |
|
132 /** MapToRelativeTime() |
|
133 * |
|
134 * Provides mapping between iTimeReference of TVTzActualisedRule and iRelativeTime of TVersitDateTime. |
|
135 * |
|
136 * CTzRules::AddActualisedRulesL() guarantees that TVTzActualisedRule is always UTC or |
|
137 * local(ETzWallTimeReference), and is never STD. The func maps everything to |
|
138 * TVersitDateTime::EIsMachineLocal, unless iTimeReference is ETzUtcTimeReference, which is mapped |
|
139 * to TVersitDateTime::EIsUTC. |
|
140 * |
|
141 * This is local helper function. |
|
142 * Used exclusively by CAgendaEntryToVCalConverter::AddTimeZonePropertiesL() to export DAYLIGHT properties. |
|
143 */ |
|
144 static inline TVersitDateTime::TRelativeTime MapToRelativeTime(TTzTimeReference& aTzTimeRef) |
|
145 { |
|
146 return (aTzTimeRef==ETzUtcTimeReference) ? (TVersitDateTime::EIsUTC) : (TVersitDateTime::EIsMachineLocal); |
|
147 } |
|
148 |
|
149 /* AddDaylightPropertyL() |
|
150 * |
|
151 * Export a DAYLIGHT property to describe the daylight saving period and its offset. |
|
152 * There can be more than one DAYLIGHT property for a year (depenging on number of DST rules for the year). |
|
153 * Time designators (i.e EST, EDT) are not exported. |
|
154 * |
|
155 * @param aParser - a vCal entity or sub-entity (VEVENT or VTODO); |
|
156 * @param aOffsetInSeconds - offset in seconds from UTC (i.e. STD + DST) for the period when the |
|
157 daylight saving rule is in effect, |
|
158 for instance, for time zone "Vancouver/America (PST)" aOffsetInSeconds is |
|
159 -480*60=-28800 secs in winter time, and -420*60=-25200 secs when DST is observed; |
|
160 * @param aStartTime - exact time when a rule starts (usually 02:00:00 local time); |
|
161 * @param aEndTime - time when rule ends (usually 03:00:00 local time). |
|
162 */ |
|
163 void CAgendaEntryToVCalConverter::AddDaylightPropertyL(CVersitParser& aParser, |
|
164 TTimeIntervalSeconds aOffsetInSeconds, |
|
165 TTimeWithReference aStartTime, |
|
166 TTimeWithReference aEndTime) |
|
167 { |
|
168 TVersitDateTime* vStartTime = new(ELeave) TVersitDateTime(aStartTime.iTime.DateTime(), |
|
169 MapToRelativeTime(aStartTime.iTimeReference)); |
|
170 CleanupStack::PushL(vStartTime); |
|
171 |
|
172 TVersitDateTime* vEndTime = new (ELeave) TVersitDateTime(aEndTime.iTime.DateTime(), |
|
173 MapToRelativeTime(aEndTime.iTimeReference)); |
|
174 CleanupStack::PushL(vEndTime); |
|
175 |
|
176 CVersitDaylight* vDaylight = CVersitDaylight::NewL(ETrue, |
|
177 aOffsetInSeconds, |
|
178 vStartTime, |
|
179 vEndTime, |
|
180 KNullDesC(), |
|
181 KNullDesC()); |
|
182 |
|
183 CleanupStack::Pop(vEndTime); // CVersitDaylight takes ownership. |
|
184 CleanupStack::Pop(vStartTime); // CVersitDaylight takes ownership. |
|
185 |
|
186 CleanupStack::PushL(vDaylight); |
|
187 CParserPropertyValue* vValue = new (ELeave) CParserPropertyValueDaylight(vDaylight); |
|
188 CleanupStack::Pop(vDaylight); |
|
189 |
|
190 CleanupStack::PushL(vValue); |
|
191 CParserProperty* vProp = CParserProperty::NewL(*vValue, KVersitTokenDAYLIGHT, NULL); |
|
192 CleanupStack::Pop(vValue); |
|
193 |
|
194 aParser.AddPropertyL(vProp); |
|
195 } |
|
196 |
|
197 |
|
198 /** Adds DAYLIGHT properties for a range of years from aStartYear to aEndYear inclusive to |
|
199 * a vCalendar entity (aParser). |
|
200 * |
|
201 * @param aParser - a vCalendar object where properties added |
|
202 * @param aRules - time zone rules used to retrieve DST information |
|
203 * @param aRepeatStartTime - start of entry range, including the repeat rule |
|
204 * @param aRepeatEndTime - end of entry range, including the repeat rule |
|
205 * |
|
206 */ |
|
207 void CAgendaEntryToVCalConverter::AddDaylightPropertiesL(CVersitParser& aParser, const CTzRules* aRules, TInt aStdOffset, TTime aRepeatStartTime, TTime aRepeatEndTime) |
|
208 { |
|
209 const TInt KRepeatStartYear = aRepeatStartTime.DateTime().Year(); |
|
210 const TInt KRepeatEndYear = aRepeatEndTime.DateTime().Year(); |
|
211 |
|
212 // actualise the rules starting a year before our period of interest |
|
213 CVTzActualisedRules* actRules = CVTzActualisedRules::NewL(KRepeatStartYear - 1, KRepeatEndYear + 1); |
|
214 |
|
215 if (actRules) |
|
216 { |
|
217 CleanupStack::PushL(actRules); |
|
218 aRules->GetActualisedRulesL(*actRules); |
|
219 |
|
220 TTime now; |
|
221 now.HomeTime(); |
|
222 const TInt KThisYear = now.DateTime().Year(); |
|
223 |
|
224 // Set up the time range for exported DAYLIGHT properties |
|
225 const TInt KRangeBeginYear(Max(KThisYear - KDaylightPropertyYearsBackwards, KRepeatStartYear)); |
|
226 const TInt KRangeEndYear(Min(Max(KThisYear + KDaylightPropertyYearsForwards, KRepeatStartYear + KDaylightPropertyYearsForwards), KRepeatEndYear + 1)); |
|
227 const TTime KRangeBeginTime(TDateTime(KRangeBeginYear, EJanuary, 0, 0, 0, 0, 0)); |
|
228 const TTime KRangeEndTime(TDateTime(KRangeEndYear, EJanuary, 0, 0, 0, 0, 0)); |
|
229 |
|
230 const TInt KRulesCount(actRules->Count()); |
|
231 for (TInt i(0) ; i < KRulesCount - 1 ; ++i) |
|
232 { |
|
233 TVTzActualisedRule& actRule = (*actRules)[i]; |
|
234 |
|
235 if (aStdOffset < actRule.iNewOffset) // work with DST rules only |
|
236 { |
|
237 // End time of a rule is start time of the next rule |
|
238 TVTzActualisedRule& actRuleNext = (*actRules)[i+1]; |
|
239 |
|
240 TTimeWithReference ruleStart(TTimeWithReference(actRule.iTimeOfChange, actRule.iTimeReference)); |
|
241 TTimeWithReference ruleEnd(TTimeWithReference(actRuleNext.iTimeOfChange, actRuleNext.iTimeReference)); |
|
242 |
|
243 TTime ruleStartTime = ruleStart.iTime; |
|
244 TTime ruleEndTime = ruleEnd.iTime; |
|
245 |
|
246 if (actRule.iTimeReference == ETzStdTimeReference) |
|
247 { |
|
248 ruleStartTime -= TTimeIntervalMinutes(aRules->InitialStdTimeOffset()); |
|
249 } |
|
250 else if (actRule.iTimeReference == ETzWallTimeReference) |
|
251 { |
|
252 ruleStartTime -= TTimeIntervalMinutes(actRule.iNewOffset); |
|
253 } |
|
254 |
|
255 if (actRule.iTimeReference == ETzStdTimeReference) |
|
256 { |
|
257 ruleEndTime -= TTimeIntervalMinutes(aRules->InitialStdTimeOffset()); |
|
258 } |
|
259 else if (actRule.iTimeReference == ETzWallTimeReference) |
|
260 { |
|
261 ruleEndTime -= TTimeIntervalMinutes(actRule.iNewOffset); |
|
262 } |
|
263 |
|
264 // Export rule if the first instance occours when dst is on |
|
265 // or if the rule covers the range defined above |
|
266 if ( (aRepeatStartTime >= ruleStartTime) && (aRepeatStartTime <= ruleEndTime) || (ruleEndTime >= KRangeBeginTime) && (ruleStartTime <= KRangeEndTime) ) |
|
267 { |
|
268 // Export DAYLIGHT property for concrete DST rule |
|
269 AddDaylightPropertyL(aParser, actRule.iNewOffset * 60, ruleStart, ruleEnd); |
|
270 } |
|
271 } |
|
272 } |
|
273 CleanupStack::PopAndDestroy(actRules); |
|
274 } |
|
275 } |
|
276 |
|
277 void CAgendaEntryToVCalConverter::NextVCalendarL() |
|
278 { |
|
279 iAddedTzProperty = EFalse; |
|
280 } |
|
281 |
|
282 /** CAgendaEntryToVCalConverter::AddTimeZonePropertiesL() |
|
283 * |
|
284 * Adds TZ and DAYLIGHT properties to a vCalendar entity. |
|
285 * |
|
286 * @param aEntry - an agenda entry which supplies timezone and tz rules information |
|
287 * (has to have a repeat definition, otherwise function will do nothing); |
|
288 * @param aParser - a vCalendar object to which the properties are added. |
|
289 * |
|
290 * aParser can be 1) a vCalendar object (also referrred to as "vCalendar entity"), |
|
291 * as well as 2) a vEvent or vTodo objects (also referred to as "vCalendar sub-entities"). |
|
292 * |
|
293 * TZ and DAYLIGHT properties (as per vCalendar v1.0 spec) apply to the vCalendar object as a whole; UNLESS |
|
294 * overriden by a property within the scope of an event or todo entity. |
|
295 * |
|
296 * @internalComponent |
|
297 */ |
|
298 void CAgendaEntryToVCalConverter::AddTimeZonePropertiesL(CVersitParser& aParser, CCalEntry* aEntry) |
|
299 { |
|
300 TCalRRule rrule; |
|
301 |
|
302 if (aEntry->GetRRuleL(rrule) && aEntry->StartTimeL().TimeMode() != TCalTime::EFloating) |
|
303 { |
|
304 // Only export the TZ property when the entry is repeating. |
|
305 // Do not export TZ rules for floating entry. |
|
306 CTzRules* rules = aEntry->TzRulesL(); |
|
307 |
|
308 if (rules) |
|
309 { |
|
310 CleanupStack::PushL( rules ); |
|
311 |
|
312 // find the standard offset for this time zone |
|
313 // which is the lowest offset from the rules for the entry's repeat range |
|
314 CVTzActualisedRules* actRules = CVTzActualisedRules::NewL(rrule.DtStart().TimeUtcL().DateTime().Year() - 1, rrule.Until().TimeUtcL().DateTime().Year() + 1); |
|
315 CleanupStack::PushL(actRules); |
|
316 rules->GetActualisedRulesL(*actRules); |
|
317 |
|
318 TInt stdOffset(KMaxTInt); |
|
319 |
|
320 const TInt KRulesCount = actRules->Count(); |
|
321 for (TInt i(0) ; i < KRulesCount ; ++i) |
|
322 { |
|
323 if ((*actRules)[i].iNewOffset < stdOffset) |
|
324 { |
|
325 stdOffset = (*actRules)[i].iNewOffset; |
|
326 } |
|
327 } |
|
328 |
|
329 if (stdOffset == KMaxTInt) |
|
330 { |
|
331 // there were no offsets found so use the current system utc offset |
|
332 stdOffset = (User::UTCOffset().Int() / 60); |
|
333 } |
|
334 |
|
335 CleanupStack::PopAndDestroy(actRules); |
|
336 AddTzPropertyL(aParser, stdOffset * 60); |
|
337 AddDaylightPropertiesL(aParser, rules, stdOffset, rrule.DtStart().TimeUtcL(), rrule.Until().TimeUtcL()); |
|
338 |
|
339 CleanupStack::PopAndDestroy(rules); |
|
340 } |
|
341 } |
|
342 } |
|
343 |
|
344 // This function specifies the ordering of the vCalendar properties as exported by Versit. |
|
345 // |
|
346 // The UID property should be the first property. |
|
347 // |
|
348 // The following three properties of a vCalendar should be DESCRIPTION, DTSTART and DTEND for appointments, |
|
349 // anniversaries & events. To-do entries should have DESCRIPTION and DUE as the following two properties. |
|
350 // This is to assist processing by Connectivity (as requested by Time Technology) |
|
351 // |
|
352 void CAgendaEntryToVCalConverter::AddEntryPropertiesL(CCalEntry* aEntry, CVersitParser& aParser) |
|
353 { |
|
354 // UID |
|
355 |
|
356 HBufC* guid16 = HBufC::NewLC(aEntry->UidL().Length()); |
|
357 TPtr ptr16 = guid16->Des(); |
|
358 CnvUtfConverter::ConvertToUnicodeFromUtf8(ptr16, aEntry->UidL()); |
|
359 AddDesPropertyL(aParser, KVersitTokenUID, guid16->Des()); |
|
360 CleanupStack::PopAndDestroy(guid16); |
|
361 |
|
362 // CAgnEntry::RichTextL() => SUMMARY |
|
363 // CAgnEntry::NotesTextL() => DESCRIPTION |
|
364 |
|
365 if (aEntry->DescriptionL().Length() > 0) |
|
366 { |
|
367 AddDesPropertyL(aParser, KVersitTokenDESCRIPTION, aEntry->DescriptionL()); |
|
368 } |
|
369 |
|
370 if (aEntry->SummaryL().Length() > 0) |
|
371 { |
|
372 AddDesPropertyL(aParser, KVersitTokenSUMMARY, aEntry->SummaryL()); |
|
373 } |
|
374 |
|
375 // Add DTSTART and DTEND (or DUE, PRIORITY and todo list information for to-do items), then add X-EPOCAGENDAENTRYTYPE |
|
376 switch (aEntry->EntryTypeL()) |
|
377 { |
|
378 case CCalEntry::EAppt: |
|
379 { |
|
380 AddEventPropertiesL(aParser, aEntry); |
|
381 AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeAPPT); |
|
382 break; |
|
383 } |
|
384 case CCalEntry::EReminder: |
|
385 { |
|
386 AddEventPropertiesL(aParser, aEntry); |
|
387 AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeREMINDER); |
|
388 break; |
|
389 } |
|
390 case CCalEntry::EAnniv: |
|
391 { |
|
392 AddEventPropertiesL(aParser, aEntry); |
|
393 AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeANNIV); |
|
394 break; |
|
395 } |
|
396 case CCalEntry::EEvent: |
|
397 { |
|
398 AddEventPropertiesL(aParser, aEntry); |
|
399 AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeEVENT); |
|
400 break; |
|
401 } |
|
402 case CCalEntry::ETodo: |
|
403 { |
|
404 AddTodoPropertiesL(aParser, aEntry); |
|
405 AddDesPropertyL(aParser, KVCalToken8ENTRYTYPE, KVCalTokenTypeTODO); |
|
406 break; |
|
407 } |
|
408 default: break; |
|
409 } |
|
410 |
|
411 // Class |
|
412 CCalEntry::TReplicationStatus status = aEntry->ReplicationStatusL(); |
|
413 switch(status) |
|
414 { |
|
415 case CCalEntry::EOpen: |
|
416 AddDesPropertyL(aParser, KVersitTokenCLASS, KVCalTokenPUBLIC); |
|
417 break; |
|
418 case CCalEntry::EPrivate: |
|
419 AddDesPropertyL(aParser, KVersitTokenCLASS, KVCalTokenPRIVATE); |
|
420 break; |
|
421 case CCalEntry::ERestricted: |
|
422 AddDesPropertyL(aParser, KVersitTokenCLASS, KVCalTokenCONFIDENTIAL); |
|
423 break; |
|
424 } |
|
425 |
|
426 // Location |
|
427 const TDesC& location = aEntry->LocationL(); |
|
428 if (location.Length() != 0) |
|
429 { |
|
430 AddDesPropertyL(aParser, KVersitTokenLOCATION, location); |
|
431 } |
|
432 |
|
433 // DTSTAMP |
|
434 TCalTime dTStamp = aEntry->DTStampL(); |
|
435 |
|
436 if ( dTStamp.TimeUtcL() != Time::NullTTime() ) |
|
437 { |
|
438 AddDateTimePropertyL(aParser, KVersitTokenXDTSTAMP, dTStamp.TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag); |
|
439 } |
|
440 |
|
441 // Sequence Number |
|
442 AddIntegerPropertyL(aParser, KVersitTokenSEQUENCE, aEntry->SequenceNumberL()); |
|
443 |
|
444 //X-Method property |
|
445 CCalEntry::TMethod methodStatus = aEntry->MethodL(); |
|
446 TPtrC methodStr; |
|
447 switch(methodStatus) |
|
448 { |
|
449 case CCalEntry::EMethodNone: |
|
450 methodStr.Set(KVCalTokenMethodStatusENone); |
|
451 break; |
|
452 case CCalEntry::EMethodPublish: |
|
453 methodStr.Set(KVCalTokenMethodStatusEPublish); |
|
454 break; |
|
455 case CCalEntry::EMethodRequest: |
|
456 methodStr.Set(KVCalTokenMethodStatusERequest); |
|
457 break; |
|
458 case CCalEntry::EMethodReply: |
|
459 methodStr.Set(KVCalTokenMethodStatusEReply); |
|
460 break; |
|
461 case CCalEntry::EMethodAdd: |
|
462 methodStr.Set(KVCalTokenMethodStatusEAdd); |
|
463 break; |
|
464 case CCalEntry::EMethodCancel: |
|
465 methodStr.Set(KVCalTokenMethodStatusECancel); |
|
466 break; |
|
467 case CCalEntry::EMethodRefresh: |
|
468 methodStr.Set(KVCalTokenMethodStatusERefresh); |
|
469 break; |
|
470 case CCalEntry::EMethodCounter: |
|
471 methodStr.Set(KVCalTokenMethodStatusECounter); |
|
472 break; |
|
473 case CCalEntry::EMethodDeclineCounter: |
|
474 methodStr.Set(KVCalTokenMethodStatusEDeclineCounter); |
|
475 break; |
|
476 default: |
|
477 User::Leave(KErrArgument); |
|
478 } |
|
479 |
|
480 AddDesPropertyL(aParser, KVersitTokenXMETHOD, methodStr); |
|
481 // X-Recurrence-ID |
|
482 TCalTime recurrenceDate = aEntry->RecurrenceIdL(); |
|
483 |
|
484 if (recurrenceDate.TimeUtcL() != Time::NullTTime()) |
|
485 { |
|
486 TTime recId; |
|
487 if(iTimeType==TVersitDateTime::EIsUTC) |
|
488 { |
|
489 recId = recurrenceDate.TimeUtcL(); |
|
490 } |
|
491 else |
|
492 { |
|
493 recId = recurrenceDate.TimeLocalL(); |
|
494 } |
|
495 AddDateTimePropertyL(aParser, KVersitTokenXRECURRENCEID, recId, iTimeType, iTimeFlag); |
|
496 } |
|
497 |
|
498 // Attendees |
|
499 RPointerArray<CCalAttendee> attendees = aEntry->AttendeesL(); |
|
500 |
|
501 TInt count=attendees.Count(); |
|
502 CCalUser* phoneowner=aEntry->PhoneOwnerL(); |
|
503 for (TInt ii=0; ii<count; ii++) |
|
504 { |
|
505 if(phoneowner==attendees[ii]) |
|
506 { |
|
507 AddAttendeePropertyL(aParser, attendees[ii],ETrue, EFalse); |
|
508 } |
|
509 else |
|
510 { |
|
511 AddAttendeePropertyL(aParser, attendees[ii],EFalse, EFalse); |
|
512 } |
|
513 |
|
514 } |
|
515 |
|
516 CCalUser* organizer=aEntry->OrganizerL(); |
|
517 if(organizer) |
|
518 { |
|
519 if(phoneowner==organizer) |
|
520 { |
|
521 AddAttendeePropertyL(aParser, organizer,ETrue, ETrue); |
|
522 } |
|
523 else |
|
524 { |
|
525 AddAttendeePropertyL(aParser, organizer,EFalse, ETrue); |
|
526 } |
|
527 } |
|
528 |
|
529 // Recurrence details |
|
530 TCalRRule rule; |
|
531 TBool isrepeat = aEntry->GetRRuleL(rule); |
|
532 if (isrepeat) |
|
533 { |
|
534 CTzRules* repeatRule = aEntry->TzRulesL(); |
|
535 CleanupStack::PushL(repeatRule); |
|
536 AddRepeatPropertiesL(aParser, rule, repeatRule); |
|
537 CleanupStack::PopAndDestroy(repeatRule); |
|
538 } |
|
539 |
|
540 // RDates |
|
541 RArray<TCalTime>rdates; |
|
542 CleanupClosePushL(rdates); |
|
543 aEntry->GetRDatesL(rdates); |
|
544 |
|
545 if (rdates.Count()>0) |
|
546 { |
|
547 AddRDatePropertyL(aParser, rdates); |
|
548 isrepeat = ETrue; |
|
549 } |
|
550 |
|
551 CleanupStack::PopAndDestroy(&rdates); |
|
552 |
|
553 if (isrepeat) |
|
554 { |
|
555 // Recurrence Exception details |
|
556 RArray<TCalTime> exceptions; |
|
557 CleanupClosePushL(exceptions); |
|
558 aEntry->GetExceptionDatesL(exceptions); |
|
559 |
|
560 if (exceptions.Count()>0) |
|
561 { |
|
562 AddRepeatExceptionPropertiesL(aParser, exceptions); |
|
563 } |
|
564 CleanupStack::PopAndDestroy(&exceptions); |
|
565 } |
|
566 |
|
567 // Alarm |
|
568 CCalAlarm* alarm = aEntry->AlarmL(); |
|
569 if (alarm) |
|
570 { |
|
571 TCalTime alarmOrigin; |
|
572 CleanupStack::PushL(alarm); |
|
573 if(aEntry->EntryTypeL()==CCalEntry::ETodo && (aEntry->EndTimeL()).TimeUtcL()!=Time::NullTTime()) |
|
574 { |
|
575 alarmOrigin = aEntry->EndTimeL(); |
|
576 } |
|
577 else |
|
578 { |
|
579 alarmOrigin = aEntry->StartTimeL(); |
|
580 } |
|
581 |
|
582 TTime alarmtime; |
|
583 if (aEntry->StartTimeL().TimeMode() != TCalTime::EFloating) |
|
584 { |
|
585 alarmtime = alarmOrigin.TimeUtcL() - TTimeIntervalMinutes(alarm->TimeOffset()); |
|
586 } |
|
587 else |
|
588 { |
|
589 alarmtime = alarmOrigin.TimeLocalL() - TTimeIntervalMinutes(alarm->TimeOffset()); |
|
590 } |
|
591 AddAlarmPropertyL(aParser, KVersitTokenAALARM, alarmtime, alarm->AlarmSoundNameL()); |
|
592 |
|
593 |
|
594 CCalContent* alarmAction = alarm->AlarmAction(); |
|
595 if (alarmAction != NULL) |
|
596 { |
|
597 AddExtendedAlarmPropertyL(aParser, KVersitTokenXALARM, *alarmAction); |
|
598 } |
|
599 CleanupStack::PopAndDestroy(alarm); |
|
600 } |
|
601 |
|
602 // Add Last Changed Date |
|
603 AddDateTimePropertyL(aParser, KVersitTokenLASTMODIFIED, (aEntry->LastModifiedDateL()).TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag); |
|
604 |
|
605 // Category Support |
|
606 const RPointerArray<CCalCategory>& categories = aEntry->CategoryListL(); |
|
607 |
|
608 if (categories.Count()>0) |
|
609 { |
|
610 AddCategoryPropertyL(aParser, categories); |
|
611 } |
|
612 |
|
613 // ADDITION FOR VERSIT COMPLIANCE |
|
614 // Merged priorities into one place - ToDo priority was previously in AddTodoPropertiesL() |
|
615 TInt priority = aEntry->PriorityL(); |
|
616 AddIntegerPropertyL(aParser, KVersitTokenPRIORITY, priority); |
|
617 if (aEntry->EntryTypeL() != CCalEntry::ETodo) |
|
618 { |
|
619 AddStatusPropertyL(aParser, aEntry); |
|
620 } |
|
621 AddIntegerPropertyL(aParser, KVersitTokenXLOCALUID, aEntry->LocalUidL()); |
|
622 AddIntegerPropertyL(aParser, KVersitTokenTRANSP, aEntry->TimeTransparencyL()); |
|
623 |
|
624 // Add GEO |
|
625 CCalGeoValue* geoValue = aEntry->GeoValueL(); |
|
626 |
|
627 // Check that the GEO values are not NULL |
|
628 if(geoValue) |
|
629 { |
|
630 CleanupStack::PushL(geoValue); |
|
631 |
|
632 TReal geoLatitude; |
|
633 TReal geoLongitude; |
|
634 |
|
635 // Extract latitude and longitude values |
|
636 // Check if it returns EFalse |
|
637 geoValue->GetLatLong(geoLatitude,geoLongitude); |
|
638 |
|
639 // Convert the geo values from numbers to string |
|
640 // Create GEO string buffer to be constructed from a latitude, delimiter and a longitude value |
|
641 TBuf<KGEOMaxWidthOfGeoValue*2+1> geoString; |
|
642 TBuf<KGEOMaxWidthOfGeoValue> geoLatString; |
|
643 TBuf<KGEOMaxWidthOfGeoValue> geoLongString; |
|
644 |
|
645 // Maximum width of a GEO value and max number of decimal places |
|
646 TRealFormat geoFormat(KGEOMaxWidthOfGeoValue,KCalGEOMaxDecimalPlaces); |
|
647 |
|
648 _LIT(KGeoStringFormat,"%S%c%S"); |
|
649 |
|
650 // Ensure correct conversion from stored numeric values to descriptors |
|
651 if((geoLatString.Num(geoLatitude,geoFormat)>0) && (geoLongString.Num(geoLongitude,geoFormat)>0)) |
|
652 { |
|
653 geoString.AppendFormat(KGeoStringFormat,&geoLatString,KVersitTokenCommaVal,&geoLongString); |
|
654 |
|
655 // Add the GEO property |
|
656 AddDesPropertyL(aParser,KVersitTokenGEO,geoString); |
|
657 } |
|
658 |
|
659 CleanupStack::PopAndDestroy(geoValue); |
|
660 } |
|
661 |
|
662 TUint attachCount = aEntry->AttachmentCountL(); |
|
663 for(TInt ii = 0; ii<attachCount; ++ii) |
|
664 { |
|
665 CCalAttachment* attach = aEntry->AttachmentL(ii); |
|
666 AddAttachmentPropertyL(aParser, *attach); |
|
667 } |
|
668 } |
|
669 |
|
670 |
|
671 // Add appointment properties to parser |
|
672 // |
|
673 void CAgendaEntryToVCalConverter::AddEventPropertiesL(CVersitParser& aParser, CCalEntry* aEntry) |
|
674 { |
|
675 //If this is an untimed appt the start time will be the default start time |
|
676 //If the alarm time is *after* this time we need to move the start time to the alarm time |
|
677 TTime startTime; |
|
678 TTime endTime; |
|
679 if((aEntry->StartTimeL()).TimeMode() == TCalTime::EFloating ) |
|
680 { |
|
681 startTime = (aEntry->StartTimeL()).TimeLocalL(); |
|
682 if(aEntry->EntryTypeL()==CCalEntry::EReminder) |
|
683 { |
|
684 endTime = startTime; |
|
685 } |
|
686 else |
|
687 { |
|
688 endTime =(aEntry->EndTimeL()).TimeLocalL(); |
|
689 } |
|
690 |
|
691 } |
|
692 else |
|
693 { |
|
694 startTime = (aEntry->StartTimeL()).TimeUtcL(); |
|
695 if(aEntry->EntryTypeL()==CCalEntry::EReminder) |
|
696 { |
|
697 endTime = startTime; |
|
698 } |
|
699 else |
|
700 { |
|
701 endTime = (aEntry->EndTimeL()).TimeUtcL(); |
|
702 } |
|
703 |
|
704 } |
|
705 |
|
706 iStartTime=startTime.DateTime(); |
|
707 |
|
708 |
|
709 AddDateTimePropertyL(aParser, KVersitTokenDTSTART, startTime, iTimeType, iTimeFlag); |
|
710 AddDateTimePropertyL(aParser, KVersitTokenDTEND, endTime, iTimeType, iTimeFlag); |
|
711 } |
|
712 |
|
713 // Add todo properties |
|
714 // |
|
715 void CAgendaEntryToVCalConverter::AddTodoPropertiesL(CVersitParser& aParser, CCalEntry* aEntry) |
|
716 { |
|
717 TBool isUtc = ETrue; |
|
718 if ((aEntry->EndTimeL()).TimeUtcL() != Time::NullTTime()) |
|
719 { |
|
720 if ((aEntry->StartTimeL()).TimeMode() == TCalTime::EFloating) |
|
721 { |
|
722 isUtc = EFalse; |
|
723 AddDateTimePropertyL(aParser, KVersitTokenDUE, (aEntry->EndTimeL()).TimeLocalL(), iTimeType, iTimeFlag); |
|
724 } |
|
725 else |
|
726 { |
|
727 AddDateTimePropertyL(aParser, KVersitTokenDUE, (aEntry->EndTimeL()).TimeUtcL(), iTimeType, iTimeFlag); |
|
728 } |
|
729 } |
|
730 |
|
731 // Add todo name list is now done with rest of category implementation |
|
732 TTime startDate; |
|
733 |
|
734 if (isUtc) |
|
735 { |
|
736 startDate = aEntry->StartTimeL().TimeUtcL(); |
|
737 } |
|
738 else |
|
739 { |
|
740 startDate = aEntry->StartTimeL().TimeLocalL(); |
|
741 } |
|
742 iStartTime=startDate.DateTime(); |
|
743 |
|
744 // We have already checked the start and end times so we do not need |
|
745 // further checks here. After discussion with MV. |
|
746 if (startDate != Time::NullTTime()) |
|
747 { |
|
748 AddDateTimePropertyL(aParser, KVersitTokenDTSTART, startDate, iTimeType, iTimeFlag); |
|
749 } |
|
750 |
|
751 // Is the entry completed - if so export completed date/time and COMPLETED status |
|
752 if ((aEntry->CompletedTimeL()).TimeUtcL() != Time::NullTTime()) |
|
753 { |
|
754 AddDateTimePropertyL(aParser,KVCalTokenCOMPLETED, (aEntry->CompletedTimeL()).TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag); |
|
755 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCOMPLETED); |
|
756 } |
|
757 else |
|
758 { |
|
759 if (aEntry->StatusL()==CCalEntry::ETodoCompleted) |
|
760 { |
|
761 // If entry status is COMPLETED, ensure COMPLETED date is exported too |
|
762 if ((aEntry->EndTimeL()).TimeUtcL()!= Time::NullTTime()) |
|
763 { |
|
764 aEntry->SetCompletedL(ETrue,aEntry->EndTimeL()); |
|
765 } |
|
766 else |
|
767 { |
|
768 //No valid due date, set the completed date to the today's date |
|
769 TTime today; |
|
770 today.UniversalTime(); |
|
771 TCalTime caltime; |
|
772 caltime.SetTimeUtcL(today); |
|
773 aEntry->SetCompletedL(ETrue, caltime); |
|
774 } |
|
775 AddDateTimePropertyL(aParser,KVCalTokenCOMPLETED, (aEntry->CompletedTimeL()).TimeUtcL(), TVersitDateTime::EIsUTC, iTimeFlag); |
|
776 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCOMPLETED); |
|
777 } |
|
778 else |
|
779 { |
|
780 // Entry is not completed and doesn't have status==Completed |
|
781 // So, add status property as normal |
|
782 AddStatusPropertyL(aParser,aEntry); |
|
783 } |
|
784 |
|
785 } |
|
786 |
|
787 } |
|
788 |
|
789 // Construct an integer property |
|
790 // |
|
791 void CAgendaEntryToVCalConverter::AddIntegerPropertyL(CVersitParser& aParser, const TDesC8& aToken, TCalLocalUid aInt) |
|
792 { |
|
793 CParserPropertyValue* value = new(ELeave)CParserPropertyValueInt(aInt); |
|
794 CleanupStack::PushL(value); |
|
795 CParserProperty* prop = CParserProperty::NewL(*value, aToken, NULL); |
|
796 CleanupStack::Pop(value); |
|
797 // Add to the parser |
|
798 aParser.AddPropertyL(prop); |
|
799 } |
|
800 |
|
801 void CAgendaEntryToVCalConverter::AddDateTimePropertyL(CVersitParser& aParser, const TDesC8& aToken, const TTime& aTime, const TVersitDateTime::TRelativeTime aRelativeTime, TVersitDateTime::TVersitDateTimeFlags aTimeFlag) |
|
802 { |
|
803 // Construct a date-time property |
|
804 TVersitDateTime* versitDateTime = new(ELeave)TVersitDateTime(aTime.DateTime(), aRelativeTime); |
|
805 CleanupStack::PushL(versitDateTime); |
|
806 CParserPropertyValue* value = new(ELeave)CParserPropertyValueDateTime(versitDateTime); |
|
807 CleanupStack::Pop(versitDateTime); |
|
808 versitDateTime->SetFlag(aTimeFlag); |
|
809 |
|
810 CleanupStack::PushL(value); |
|
811 CParserProperty* prop = CParserProperty::NewL(*value, aToken, NULL); |
|
812 CleanupStack::Pop(value); |
|
813 // Add to the parser |
|
814 aParser.AddPropertyL(prop); |
|
815 |
|
816 } |
|
817 |
|
818 void CAgendaEntryToVCalConverter::AddDesPropertyL(CVersitParser& aParser, const TDesC8& aToken, const TDesC& aDes) |
|
819 { |
|
820 HBufC* buf=AgnConvertUtil::EncodeL(aDes,KUidEtextToText); |
|
821 CleanupStack::PushL(buf); |
|
822 CParserPropertyValue* value = CParserPropertyValueHBufC::NewL(buf->Des()); |
|
823 CleanupStack::PopAndDestroy(buf); |
|
824 CleanupStack::PushL(value); |
|
825 CParserProperty* prop = CParserProperty::NewL(*value, aToken, NULL); |
|
826 CleanupStack::Pop(value); |
|
827 // Add to the parser |
|
828 aParser.AddPropertyL(prop); |
|
829 } |
|
830 |
|
831 void CAgendaEntryToVCalConverter::AddAlarmPropertyL(CVersitParser& aParser, const TDesC8& aToken, const TTime& aAlarmTime, const TDesC& aAlarmName) |
|
832 { |
|
833 // Create an array of paramaters for this property |
|
834 CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(4); |
|
835 CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams)); |
|
836 |
|
837 CParserParam* typeParam = CParserParam::NewL(KVCalToken8TYPE, KNullDesC8); |
|
838 CleanupStack::PushL(typeParam); |
|
839 typeParam->SetValueL(KVCalValue8EPOCSOUND); |
|
840 arrayOfParams->AppendL(typeParam); // takes ownership |
|
841 CleanupStack::Pop(typeParam); |
|
842 |
|
843 // Construct a date-time property |
|
844 |
|
845 TVersitDateTime* versitDateTime = new(ELeave)TVersitDateTime(aAlarmTime.DateTime(), iTimeType); |
|
846 CleanupStack::PushL(versitDateTime); |
|
847 |
|
848 CVersitAlarm* alarm = CVersitAlarm::NewL(versitDateTime, NULL, 0, aAlarmName, TPtrC()); |
|
849 CleanupStack::Pop(versitDateTime); |
|
850 versitDateTime->SetFlag(iTimeFlag); |
|
851 CleanupStack::PushL(alarm); |
|
852 CParserPropertyValue* value = new(ELeave)CParserPropertyValueAlarm(alarm); |
|
853 CleanupStack::Pop(alarm); |
|
854 CleanupStack::PushL(value); |
|
855 |
|
856 CParserProperty* prop = CParserProperty::NewL(*value, aToken, arrayOfParams); |
|
857 CleanupStack::Pop(2,arrayOfParams); // value, arrayOfParams |
|
858 |
|
859 // Add to the parser |
|
860 aParser.AddPropertyL(prop); |
|
861 } |
|
862 |
|
863 void CAgendaEntryToVCalConverter::AddExtendedAlarmPropertyL(CVersitParser& aParser, const TDesC8& aToken, const CCalContent& aAlarmAction) |
|
864 { |
|
865 // Create an array of parameters for this property |
|
866 CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(4); |
|
867 CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams)); |
|
868 |
|
869 // Create content disposition parameter |
|
870 CParserParam* dispositionParam = CParserParam::NewL(KVersitTokenVALUE, KNullDesC8); |
|
871 CleanupStack::PushL(dispositionParam); |
|
872 CCalContent::TDisposition disposition = aAlarmAction.Disposition(); |
|
873 switch (disposition) |
|
874 { |
|
875 case CCalContent::EDispositionUrl: |
|
876 { |
|
877 dispositionParam->SetValueL(KVCalContentValueUrl); |
|
878 break; |
|
879 } |
|
880 case CCalContent::EDispositionInline: |
|
881 { |
|
882 dispositionParam->SetValueL(KVCalContentValueInline); |
|
883 break; |
|
884 } |
|
885 default: |
|
886 { |
|
887 // In the default case, the property is unsupported. So we'll clean up |
|
888 // and then return |
|
889 CleanupStack::PopAndDestroy(2); //arrayOfParams, dispositionParam |
|
890 return; |
|
891 } |
|
892 } |
|
893 arrayOfParams->AppendL(dispositionParam); // takes ownership |
|
894 CleanupStack::Pop(dispositionParam); |
|
895 |
|
896 // Create content MIME type parameter |
|
897 CParserParam* mimeTypeParam = CParserParam::NewL(KVersitTokenCONTENTTYPE, KNullDesC8); |
|
898 CleanupStack::PushL(mimeTypeParam); |
|
899 TPtrC8 mimeType(aAlarmAction.MimeType()); |
|
900 mimeTypeParam->SetValueL(mimeType); |
|
901 arrayOfParams->AppendL(mimeTypeParam); |
|
902 CleanupStack::Pop(mimeTypeParam); |
|
903 |
|
904 |
|
905 // Construct X-EPOC-ALARM property and initialise with parameters and content |
|
906 CVersitExtendedAlarm* alarm = CVersitExtendedAlarm::NewL(aAlarmAction.Content(), aAlarmAction.MimeType(), static_cast<CVersitExtendedAlarm::TDisposition>(aAlarmAction.Disposition())); |
|
907 CleanupStack::PushL(alarm); |
|
908 CParserPropertyValue* value = new(ELeave)CParserPropertyValueExtendedAlarm(alarm); |
|
909 CleanupStack::Pop(alarm); |
|
910 CleanupStack::PushL(value); |
|
911 CParserProperty* prop = CParserProperty::NewL(*value, aToken, arrayOfParams); |
|
912 CleanupStack::Pop(2,arrayOfParams); // value, arrayOfParams |
|
913 |
|
914 // Add to the parser |
|
915 aParser.AddPropertyL(prop); // takes ownership of prop |
|
916 } |
|
917 |
|
918 void CAgendaEntryToVCalConverter::AddAttachmentPropertyL(CVersitParser& aParser, CCalAttachment& aAttachment) |
|
919 { |
|
920 // Create an array of parameters for this property |
|
921 CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(4); |
|
922 CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams)); |
|
923 |
|
924 // Create value parameter |
|
925 CParserParam* valueType = CParserParam::NewL(KVersitTokenVALUE, KNullDesC8); |
|
926 CleanupStack::PushL(valueType); |
|
927 CCalAttachment::TType type = aAttachment.Type(); |
|
928 TBool exportBinaryData = EFalse; |
|
929 switch (type) |
|
930 { |
|
931 case CCalAttachment::EUri: |
|
932 { |
|
933 valueType->SetValueL(KVCalContentValueUrl); |
|
934 break; |
|
935 } |
|
936 case CCalAttachment::EFile: |
|
937 { |
|
938 if (aAttachment.FileAttachment()->ContentId().Length() > 0) |
|
939 { |
|
940 valueType->SetValueL(KVCalContentValueContentId); |
|
941 } |
|
942 else if (aAttachment.IsAttributeSet(CCalAttachment::EExportInline)) |
|
943 { |
|
944 valueType->SetValueL(KVCalContentValueInline); |
|
945 exportBinaryData = ETrue; |
|
946 } |
|
947 break; |
|
948 } |
|
949 default: |
|
950 // Do nothing. In this case the value will not be set |
|
951 break; |
|
952 } |
|
953 if (valueType->Value().Length() == 0) |
|
954 { |
|
955 // The property is unsupported. So we'll clean up and then return |
|
956 CleanupStack::PopAndDestroy(2, arrayOfParams); //arrayOfParams, valueType |
|
957 return; |
|
958 } |
|
959 arrayOfParams->AppendL(valueType); // takes ownership |
|
960 CleanupStack::Pop(valueType); |
|
961 |
|
962 // Create content MIME type parameter |
|
963 TPtrC8 mimeType(aAttachment.MimeType()); |
|
964 if(mimeType != KNullDesC8) |
|
965 { |
|
966 CParserParam* mimeTypeParam = CParserParam::NewL(KVersitAttachMimeType, mimeType); |
|
967 CleanupStack::PushL(mimeTypeParam); |
|
968 arrayOfParams->AppendL(mimeTypeParam); |
|
969 CleanupStack::Pop(mimeTypeParam); |
|
970 } |
|
971 |
|
972 const TPtrC fileName(aAttachment.Label()); |
|
973 if(fileName != KNullDesC) |
|
974 { |
|
975 HBufC8* filenameUtf8 = HBufC8::NewLC(2 * fileName.Length()); // need room to convert from 16 bit to 8 bit (x2) |
|
976 TPtr8 pfileName(filenameUtf8->Des()); |
|
977 User::LeaveIfError(CnvUtfConverter::ConvertFromUnicodeToUtf8(pfileName, fileName)); |
|
978 CParserParam* fileNameParameter = CParserParam::NewL(KVersitAttachLabel, pfileName); |
|
979 CleanupStack::PopAndDestroy(filenameUtf8); |
|
980 CleanupStack::PushL(fileNameParameter); |
|
981 arrayOfParams->AppendL(fileNameParameter); |
|
982 CleanupStack::Pop(fileNameParameter); |
|
983 } |
|
984 // Create File Date parameter |
|
985 TTime lastModifiedFileTime = Time::NullTTime(); |
|
986 if (aAttachment.FileAttachment()) |
|
987 { |
|
988 lastModifiedFileTime = aAttachment.FileAttachment()->LastModifiedTimeUtc(); |
|
989 } |
|
990 if(lastModifiedFileTime != Time::NullTTime()) |
|
991 { |
|
992 _LIT(KStringFormat, "%F%Y%M%DT%H%T%SZ"); // locale-independent formatting YYMMDD"T"HHMMSS"Z" (day,month,year,hour,minute,second) |
|
993 TBuf<KMaxTimeStringSize> dateString; |
|
994 lastModifiedFileTime.FormatL(dateString,KStringFormat); |
|
995 TBuf8<KMaxTimeStringSize> dateString8; |
|
996 dateString8.Copy(dateString); |
|
997 CParserParam* fileDate = CParserParam::NewL(KVCalAttachFileDate, dateString8); |
|
998 CleanupStack::PushL(fileDate); |
|
999 arrayOfParams->AppendL(fileDate); |
|
1000 CleanupStack::Pop(fileDate); |
|
1001 } |
|
1002 |
|
1003 CParserPropertyValue* propertyValue = NULL; |
|
1004 |
|
1005 if (exportBinaryData) |
|
1006 { |
|
1007 RFile file; |
|
1008 TRAPD(err,aAttachment.FileAttachment()->FetchFileHandleL(file)); |
|
1009 if(err == KErrNone) |
|
1010 { |
|
1011 CleanupClosePushL(file); |
|
1012 propertyValue = CParserPropertyValueBinaryFile::NewL(file); |
|
1013 CleanupStack::PopAndDestroy(&file); |
|
1014 } |
|
1015 else if(err == KErrArgument) |
|
1016 {//FetchFileHandleL leaves with KErrArgument if there is no file handle has been set, eg. the entry hasn't been saved to Calendar file which isn't common user case |
|
1017 TRAP(err, aAttachment.FileAttachment()->LoadBinaryDataL()); |
|
1018 |
|
1019 if(err != KErrNone) |
|
1020 {//The user can keep synching if, e.g. it is out of memory, or the attachment file is on a drive where the media has been removed, or the attachment has been deleted from the calendar store by other clients. |
|
1021 CleanupStack::PopAndDestroy(arrayOfParams); |
|
1022 return; |
|
1023 } |
|
1024 |
|
1025 propertyValue = CParserPropertyValueBinary::NewL(aAttachment.Value()); |
|
1026 } |
|
1027 else |
|
1028 { |
|
1029 User::Leave(err); |
|
1030 } |
|
1031 } |
|
1032 else |
|
1033 { |
|
1034 TPtrC8 attach8; |
|
1035 if (type == CCalAttachment::EFile) |
|
1036 { |
|
1037 attach8.Set(aAttachment.FileAttachment()->ContentId()); |
|
1038 } |
|
1039 else |
|
1040 { |
|
1041 attach8.Set(aAttachment.Value()); |
|
1042 } |
|
1043 |
|
1044 HBufC* attach16 = HBufC::NewLC(attach8.Length()); |
|
1045 attach16->Des().Copy(attach8); |
|
1046 propertyValue = CParserPropertyValueHBufC::NewL(attach16->Des()); |
|
1047 CleanupStack::PopAndDestroy(attach16); |
|
1048 } |
|
1049 CleanupStack::PushL(propertyValue); |
|
1050 CParserProperty* property = CParserProperty::NewL(*propertyValue, KVersitTokenATTACH, arrayOfParams); |
|
1051 aParser.AddPropertyL(property); |
|
1052 CleanupStack::Pop(2,arrayOfParams); // propertyValue, arrayOfParams |
|
1053 } |
|
1054 |
|
1055 void CAgendaEntryToVCalConverter::AddAttendeeParameterL(CArrayPtr<CParserParam>* aArrayOfParams, CCalAttendee* aAttendee) |
|
1056 { |
|
1057 // Create an array of paramaters for this property |
|
1058 CParserParam* expectParam = CParserParam::NewL(KVCalAttendee8EXPECT, KNullDesC8); |
|
1059 CleanupStack::PushL(expectParam); |
|
1060 switch (aAttendee->VCalExpect()) |
|
1061 { |
|
1062 case CCalAttendee::EVCalFyi: |
|
1063 expectParam->SetValueL(KVCalAttendeeExpect8FYI); |
|
1064 break; |
|
1065 case CCalAttendee::EVCalRequire: |
|
1066 expectParam->SetValueL(KVCalAttendeeExpect8REQUIRE); |
|
1067 break; |
|
1068 case CCalAttendee::EVCalRequest: |
|
1069 expectParam->SetValueL(KVCalAttendeeExpect8REQUEST); |
|
1070 break; |
|
1071 case CCalAttendee::EVCalImmediate: |
|
1072 expectParam->SetValueL(KVCalAttendeeExpect8IMMEDIATE); |
|
1073 break; |
|
1074 default: |
|
1075 break; |
|
1076 } |
|
1077 aArrayOfParams->AppendL(expectParam); // takes ownership |
|
1078 CleanupStack::Pop(expectParam); |
|
1079 |
|
1080 CParserParam* rsvpParam = CParserParam::NewL(KVCalAttendee8RSVP, KNullDesC8); |
|
1081 CleanupStack::PushL(rsvpParam); |
|
1082 switch (aAttendee->ResponseRequested()) |
|
1083 { |
|
1084 case ETrue: |
|
1085 rsvpParam->SetValueL(KVCalAttendeeRsvp8YES); |
|
1086 break; |
|
1087 case EFalse: |
|
1088 rsvpParam->SetValueL(KVCalAttendeeRsvp8NO); |
|
1089 break; |
|
1090 default: |
|
1091 break; |
|
1092 } |
|
1093 aArrayOfParams->AppendL(rsvpParam); // takes ownership |
|
1094 CleanupStack::Pop(rsvpParam); |
|
1095 |
|
1096 CParserParam* calroleParam = CParserParam::NewL(KICalAttendeeCalRole8, KNullDesC8); |
|
1097 CleanupStack::PushL(calroleParam); |
|
1098 |
|
1099 CParserParam* vcalroleParam = CParserParam::NewL(KICalAttendeeCalRole8, KNullDesC8); |
|
1100 CleanupStack::PushL(vcalroleParam); |
|
1101 |
|
1102 switch (aAttendee->RoleL()) |
|
1103 { |
|
1104 case CCalAttendee::EChair: |
|
1105 calroleParam->SetValueL(KICalAttendeeCalRole8CHAIR); |
|
1106 break; |
|
1107 case CCalAttendee::EReqParticipant: |
|
1108 calroleParam->SetValueL(KICalAttendeeCalRole8REQUIRED); |
|
1109 break; |
|
1110 case CCalAttendee::EOptParticipant: |
|
1111 calroleParam->SetValueL(KICalAttendeeCalRole8OPTIONAL); |
|
1112 break; |
|
1113 case CCalAttendee::ENonParticipant: |
|
1114 calroleParam->SetValueL(KICalAttendeeCalRole8NONPARTICIPANT); |
|
1115 break; |
|
1116 |
|
1117 case CCalAttendee::EVCalAttendee: |
|
1118 vcalroleParam->SetValueL(KVCalAttendeeRole8ATTENDEE); |
|
1119 break; |
|
1120 case CCalAttendee::EVCalDelegate: |
|
1121 vcalroleParam->SetValueL(KVCalAttendeeRole8DELEGATE); |
|
1122 break; |
|
1123 case CCalAttendee::EVCalOwner: |
|
1124 vcalroleParam->SetValueL(KVCalAttendeeRole8OWNER); |
|
1125 break; |
|
1126 default: |
|
1127 break; |
|
1128 } |
|
1129 if (calroleParam->Value().Length() > 0) |
|
1130 { |
|
1131 aArrayOfParams->AppendL(calroleParam); // takes ownership |
|
1132 CleanupStack::PopAndDestroy(vcalroleParam); // delete the vCal role as it is not used |
|
1133 CleanupStack::Pop(calroleParam); |
|
1134 } |
|
1135 else |
|
1136 { |
|
1137 aArrayOfParams->AppendL(vcalroleParam); // takes ownership |
|
1138 CleanupStack::Pop(vcalroleParam); |
|
1139 CleanupStack::PopAndDestroy(calroleParam); // delete the iCal role as it is not used |
|
1140 } |
|
1141 |
|
1142 CParserParam* calStatusParam = CParserParam::NewL(KICalAttendeeCalStatus8, KNullDesC8); |
|
1143 CleanupStack::PushL(calStatusParam); |
|
1144 |
|
1145 CParserParam* vcalStatusParam = CParserParam::NewL(KVCalAttendee8STATUS, KNullDesC8); |
|
1146 CleanupStack::PushL(vcalStatusParam); |
|
1147 |
|
1148 switch (aAttendee->StatusL()) |
|
1149 { |
|
1150 case CCalAttendee::EAccepted: |
|
1151 calStatusParam->SetValueL(KVCalAttendeeStatus8ACCEPTED); |
|
1152 vcalStatusParam->SetValueL(KVCalAttendeeStatus8ACCEPTED); |
|
1153 break; |
|
1154 case CCalAttendee::ENeedsAction: |
|
1155 calStatusParam->SetValueL(KICalAttendeeCalStatus8NEEDSACTION); |
|
1156 vcalStatusParam->SetValueL(KVCalAttendeeStatus8NEEDSACTION); |
|
1157 break; |
|
1158 case CCalAttendee::ETentative: |
|
1159 calStatusParam->SetValueL(KVCalAttendeeStatus8TENTATIVE); |
|
1160 vcalStatusParam->SetValueL(KVCalAttendeeStatus8TENTATIVE); |
|
1161 break; |
|
1162 case CCalAttendee::EConfirmed: |
|
1163 calStatusParam->SetValueL(KVCalAttendeeStatus8CONFIRMED); |
|
1164 vcalStatusParam->SetValueL(KVCalAttendeeStatus8CONFIRMED); |
|
1165 break; |
|
1166 case CCalAttendee::EDeclined: |
|
1167 calStatusParam->SetValueL(KVCalAttendeeStatus8DECLINED); |
|
1168 vcalStatusParam->SetValueL(KVCalAttendeeStatus8DECLINED); |
|
1169 break; |
|
1170 case CCalAttendee::ECompleted: |
|
1171 calStatusParam->SetValueL(KVCalAttendeeStatus8COMPLETED); |
|
1172 vcalStatusParam->SetValueL(KVCalAttendeeStatus8COMPLETED); |
|
1173 break; |
|
1174 case CCalAttendee::EDelegated: |
|
1175 calStatusParam->SetValueL(KVCalAttendeeStatus8DELEGATED); |
|
1176 vcalStatusParam->SetValueL(KVCalAttendeeStatus8DELEGATED); |
|
1177 break; |
|
1178 case CCalAttendee::EInProcess: |
|
1179 calStatusParam->SetValueL(KICalAttendeeCalStatus8INPROCESS); |
|
1180 break; |
|
1181 case CCalAttendee::EVCalSent: |
|
1182 vcalStatusParam->SetValueL(KVCalAttendeeStatus8SENT); |
|
1183 break; |
|
1184 case CCalAttendee::EVCalXReceived: |
|
1185 vcalStatusParam->SetValueL(KVCalAttendeeStatus8XDASHRECEIVED); |
|
1186 break; |
|
1187 default: |
|
1188 break; |
|
1189 } |
|
1190 |
|
1191 if (vcalStatusParam->Value().Length() > 0) |
|
1192 { |
|
1193 aArrayOfParams->AppendL(vcalStatusParam); // takes ownership |
|
1194 CleanupStack::Pop(vcalStatusParam); |
|
1195 } |
|
1196 else |
|
1197 { |
|
1198 CleanupStack::PopAndDestroy(vcalStatusParam); |
|
1199 } |
|
1200 |
|
1201 if (calStatusParam->Value().Length() > 0) |
|
1202 { |
|
1203 aArrayOfParams->AppendL(calStatusParam); // takes ownership |
|
1204 CleanupStack::Pop(calStatusParam); |
|
1205 } |
|
1206 else |
|
1207 { |
|
1208 CleanupStack::PopAndDestroy(calStatusParam); |
|
1209 } |
|
1210 } |
|
1211 |
|
1212 void CAgendaEntryToVCalConverter::AddAttendeePropertyL(CVersitParser& aParser, CCalUser* aAttendee, TBool isPhoneOwner, TBool isOrganizer) |
|
1213 { |
|
1214 CArrayPtr<CParserParam>* arrayOfParams = new(ELeave)CArrayPtrFlat<CParserParam>(9); |
|
1215 CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams)); |
|
1216 |
|
1217 if( aAttendee->SentBy() != KNullDesC) |
|
1218 { |
|
1219 CParserParam* sentByParam = CParserParam::NewL(KICalAttendeeSentBy8, aAttendee->SentBy()); |
|
1220 CleanupStack::PushL(sentByParam); |
|
1221 arrayOfParams->AppendL(sentByParam); |
|
1222 CleanupStack::Pop(sentByParam); |
|
1223 } |
|
1224 |
|
1225 if( aAttendee->CommonName() != KNullDesC) |
|
1226 { |
|
1227 CParserParam* commonNameParam = CParserParam::NewL(KICalAttendeeCommonName8, aAttendee->CommonName()); |
|
1228 CleanupStack::PushL(commonNameParam); |
|
1229 arrayOfParams->AppendL(commonNameParam); // takes ownership |
|
1230 CleanupStack::Pop(commonNameParam); |
|
1231 } |
|
1232 |
|
1233 if(isPhoneOwner) |
|
1234 { |
|
1235 CParserParam* phoneOwnerParam = CParserParam::NewL(KICalAttendee8XDASHPHONEOWNER, KNullDesC8); |
|
1236 CleanupStack::PushL(phoneOwnerParam); |
|
1237 arrayOfParams->AppendL(phoneOwnerParam); // takes ownership |
|
1238 CleanupStack::Pop(phoneOwnerParam); |
|
1239 } |
|
1240 |
|
1241 if (isOrganizer) |
|
1242 { |
|
1243 CParserParam* organizerParam = CParserParam::NewL(KVCalAttendee8ROLE, KVCalAttendeeRole8ORGANIZER); |
|
1244 CleanupStack::PushL(organizerParam); |
|
1245 arrayOfParams->AppendL(organizerParam); // takes ownership |
|
1246 CleanupStack::Pop(organizerParam); |
|
1247 } |
|
1248 else |
|
1249 { |
|
1250 // these properties are not supported in CCalUser so don't need to be exported for an organizer |
|
1251 AddAttendeeParameterL(arrayOfParams,static_cast<CCalAttendee*>(aAttendee)); |
|
1252 } |
|
1253 |
|
1254 CParserPropertyValue* value = CParserPropertyValueHBufC::NewL(aAttendee->Address()); |
|
1255 CleanupStack::PushL(value); |
|
1256 CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenATTENDEE, arrayOfParams); |
|
1257 // Add to the parser |
|
1258 aParser.AddPropertyL(prop); |
|
1259 CleanupStack::Pop(2,arrayOfParams); // value, arrayOfParams |
|
1260 } |
|
1261 |
|
1262 |
|
1263 |
|
1264 void CAgendaEntryToVCalConverter::AddRepeatPropertiesL(CVersitParser& aParser, TCalRRule& aRpt, CTzRules* aEntryTzRule) |
|
1265 { |
|
1266 CVersitRecurrence* recurrence = NULL; |
|
1267 TCalRRule::TType rType = aRpt.Type(); |
|
1268 |
|
1269 TVersitDateTime* endTime = NULL; |
|
1270 TUint duration = 0; |
|
1271 if (aRpt.Count() != 0) |
|
1272 { |
|
1273 TTime untilTime; |
|
1274 if(aEntryTzRule) |
|
1275 { |
|
1276 untilTime = aRpt.Until().TimeUtcL(); |
|
1277 //convert utc to repeat local |
|
1278 aEntryTzRule->ConvertToLocalL(untilTime); |
|
1279 } |
|
1280 else |
|
1281 {//use system local |
|
1282 untilTime = aRpt.Until().TimeLocalL(); |
|
1283 } |
|
1284 TDateTime end=untilTime.DateTime(); |
|
1285 endTime = new(ELeave) TVersitDateTime(end, TVersitDateTime::EIsVCardLocal); |
|
1286 endTime->SetFlag(TVersitDateTime::EExportLeaveAsLocalTime); |
|
1287 duration = aRpt.Count(); |
|
1288 } |
|
1289 CleanupStack::PushL(endTime); |
|
1290 |
|
1291 switch (aRpt.Type()) |
|
1292 { |
|
1293 // Daily Repeat |
|
1294 case TCalRRule::EDaily: |
|
1295 recurrence = new(ELeave)CVersitRecurrenceDaily(aRpt.Interval(), duration, endTime); |
|
1296 break; |
|
1297 // Weekly Repeat |
|
1298 case TCalRRule::EWeekly: |
|
1299 recurrence = CreateWeeklyRepeatL(aRpt, duration, endTime); |
|
1300 break; |
|
1301 // Monthly By Days Repeat |
|
1302 case TCalRRule::EMonthly: |
|
1303 recurrence = CreateMonthlyRepeatL(aRpt, duration, endTime); |
|
1304 break; |
|
1305 // Yearly By Day Repeat |
|
1306 case TCalRRule::EYearly: |
|
1307 recurrence = CreateYearlyRepeatL(aRpt, duration, endTime); |
|
1308 break; |
|
1309 default: |
|
1310 delete endTime; |
|
1311 break; |
|
1312 } |
|
1313 CleanupStack::Pop(); // endTime (owned by recurrence) |
|
1314 |
|
1315 if (recurrence) |
|
1316 { |
|
1317 CleanupStack::PushL(recurrence); |
|
1318 CParserPropertyValue* value = new(ELeave)CParserPropertyValueRecurrence(recurrence); // takes ownership |
|
1319 CleanupStack::Pop(); // recurrence |
|
1320 CleanupStack::PushL(value); |
|
1321 CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenRRULE, NULL); |
|
1322 CleanupStack::Pop(value); |
|
1323 |
|
1324 // Add to the parser |
|
1325 aParser.AddPropertyL(prop); |
|
1326 } |
|
1327 } |
|
1328 |
|
1329 CVersitRecurrence* CAgendaEntryToVCalConverter::CreateWeeklyRepeatL(TCalRRule& aRpt,TInt aDuration, TVersitDateTime* aEndTime) |
|
1330 { |
|
1331 // Convert the agenda weekly repeat to a versit recurrence |
|
1332 |
|
1333 CWeekDayArray* dayArray = new(ELeave)CWeekDayArray(); |
|
1334 CleanupStack::PushL(dayArray); |
|
1335 dayArray->iArray = new(ELeave)CArrayFixFlat<TDay>(1); |
|
1336 |
|
1337 // Iterate through the days to check which days are set |
|
1338 RArray<TDay> daysinweek; |
|
1339 CleanupClosePushL(daysinweek); |
|
1340 aRpt.GetByDayL(daysinweek); |
|
1341 TInt count=daysinweek.Count(); |
|
1342 for (TInt ii=0; ii<count; ++ii) |
|
1343 { |
|
1344 dayArray->iArray->AppendL(daysinweek[ii]); |
|
1345 } |
|
1346 CleanupStack::PopAndDestroy(&daysinweek); |
|
1347 CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceWeekly(aRpt.Interval(), aDuration, aEndTime, dayArray); // takes ownership |
|
1348 CleanupStack::Pop(dayArray); |
|
1349 |
|
1350 return recurrence; |
|
1351 } |
|
1352 |
|
1353 CVersitRecurrence* CAgendaEntryToVCalConverter::CreateMonthlyRepeatL(TCalRRule& aRpt, TInt aDuration, TVersitDateTime* aEndTime) |
|
1354 { |
|
1355 // Convert Agenda Monthly By Days repeat to a versit recurrence |
|
1356 RArray<TCalRRule::TDayOfMonth> days; |
|
1357 aRpt.GetByDayL(days); |
|
1358 TInt count=days.Count(); |
|
1359 if(count>0) |
|
1360 {//e.g. every Monday of first week and every Friday of the third week. |
|
1361 CleanupClosePushL(days); |
|
1362 CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>* monthPositions = new(ELeave)CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>(1); |
|
1363 CleanupStack::PushL(monthPositions); |
|
1364 |
|
1365 // Iterate through the five weeks for the month |
|
1366 // (First,Second,Third,Fourth,Last) |
|
1367 |
|
1368 for (TInt ii=0; ii<count; ++ii) |
|
1369 { |
|
1370 CVersitRecurrenceMonthlyByPos::CMonthPosition* monthPos = new(ELeave)CVersitRecurrenceMonthlyByPos::CMonthPosition(); |
|
1371 CleanupStack::PushL(monthPos); |
|
1372 |
|
1373 TInt8 weekNo = days[ii].WeekInMonth(); |
|
1374 if(weekNo>0) |
|
1375 { |
|
1376 monthPos->iSign = CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromStartOfMonth; |
|
1377 monthPos->iWeekNo = weekNo; |
|
1378 } |
|
1379 else |
|
1380 { |
|
1381 monthPos->iSign = CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromEndOfMonth; |
|
1382 monthPos->iWeekNo = Abs(weekNo); |
|
1383 } |
|
1384 monthPos->iArrayOfWeekDays = new(ELeave)CWeekDayArray(); |
|
1385 monthPos->iArrayOfWeekDays->iArray = new(ELeave)CArrayFixFlat<TDay>(1); |
|
1386 monthPos->iArrayOfWeekDays->iArray->AppendL(days[ii].Day()); |
|
1387 monthPositions->AppendL(monthPos); |
|
1388 CleanupStack::Pop(); // monthPos; |
|
1389 } |
|
1390 |
|
1391 CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceMonthlyByPos(aRpt.Interval(), aDuration, aEndTime, monthPositions); |
|
1392 CleanupStack::Pop(); // monthPositions (owned by recurrence) |
|
1393 CleanupStack::PopAndDestroy(&days); |
|
1394 return recurrence; |
|
1395 } |
|
1396 else |
|
1397 { |
|
1398 RArray<TInt> dayofmonth; |
|
1399 aRpt.GetByMonthDayL(dayofmonth); |
|
1400 TInt count=dayofmonth.Count(); |
|
1401 if(count>0) |
|
1402 { |
|
1403 CleanupClosePushL(dayofmonth); |
|
1404 CArrayFixFlat<TInt>* dayList = new(ELeave)CArrayFixFlat<TInt>(1); |
|
1405 CleanupStack::PushL(dayList); |
|
1406 |
|
1407 // Iterate through each day in the month |
|
1408 |
|
1409 for (TInt ii=0; ii<count; ++ii) |
|
1410 { |
|
1411 dayList->AppendL(dayofmonth[ii]+1); // add 1, since 0 means 1st |
|
1412 } |
|
1413 |
|
1414 CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aRpt.Interval(), aDuration, aEndTime, dayList, NULL, EFalse); |
|
1415 |
|
1416 CleanupStack::Pop(); // dayList; |
|
1417 |
|
1418 CleanupStack::PopAndDestroy(&dayofmonth); |
|
1419 return recurrence; |
|
1420 } |
|
1421 } |
|
1422 return NULL; |
|
1423 } |
|
1424 |
|
1425 CVersitRecurrence* CAgendaEntryToVCalConverter::CreateYearlyRepeatL(TCalRRule& aRpt, TInt aDuration, TVersitDateTime* aEndTime) |
|
1426 { |
|
1427 // Convert Agenda Yearly By Days repeat to a versit recurrence |
|
1428 |
|
1429 // There is no vCal equivalent of a yearly 'by day' repeat, |
|
1430 // e.g. repeat on the first monday of october, |
|
1431 // so a monthly repeat with an interval of 12* the yearly repeat |
|
1432 // is used instead |
|
1433 RArray<TCalRRule::TDayOfMonth> days; |
|
1434 aRpt.GetByDayL(days); |
|
1435 TInt count=days.Count(); |
|
1436 if(count>0) |
|
1437 { |
|
1438 CleanupClosePushL(days); |
|
1439 CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>* monthPositions = new(ELeave)CArrayPtrFlat<CVersitRecurrenceMonthlyByPos::CMonthPosition>(1); |
|
1440 CleanupStack::PushL(monthPositions); |
|
1441 |
|
1442 // Iterate through the five weeks for the month |
|
1443 // (First,Second,Third,Fourth,Last) |
|
1444 |
|
1445 for (TInt ii=0; ii<count; ++ii) |
|
1446 { |
|
1447 CVersitRecurrenceMonthlyByPos::CMonthPosition* monthPos = new(ELeave)CVersitRecurrenceMonthlyByPos::CMonthPosition(); |
|
1448 CleanupStack::PushL(monthPos); |
|
1449 monthPos->iSign = CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromStartOfMonth; |
|
1450 monthPos->iWeekNo = days[ii].WeekInMonth(); // iWeekNo goes from 1-5 |
|
1451 |
|
1452 monthPos->iArrayOfWeekDays = new(ELeave)CWeekDayArray(); |
|
1453 monthPos->iArrayOfWeekDays->iArray = new(ELeave)CArrayFixFlat<TDay>(1); |
|
1454 monthPos->iArrayOfWeekDays->iArray->AppendL(days[ii].Day()); |
|
1455 monthPositions->AppendL(monthPos); |
|
1456 CleanupStack::Pop(); // monthPos; |
|
1457 } |
|
1458 // Interval * 12, since we really want is to repeat yearly |
|
1459 CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceMonthlyByPos(aRpt.Interval() * 12, aDuration, aEndTime, monthPositions); |
|
1460 CleanupStack::Pop(); // monthPositions (owned by recurrence) |
|
1461 CleanupStack::PopAndDestroy(&days);//close the array |
|
1462 |
|
1463 return recurrence; |
|
1464 } |
|
1465 else |
|
1466 { |
|
1467 CArrayFixFlat<TMonth>* monthList = new(ELeave)CArrayFixFlat<TMonth>(1); |
|
1468 CleanupStack::PushL(monthList); |
|
1469 monthList->AppendL(aRpt.DtStart().TimeLocalL().DateTime().Month()); |
|
1470 CVersitRecurrence* recurrence = new(ELeave)CVersitRecurrenceYearlyByMonth(aRpt.Interval(), aDuration, aEndTime, monthList); |
|
1471 CleanupStack::Pop(); // monthList |
|
1472 return recurrence; |
|
1473 } |
|
1474 } |
|
1475 |
|
1476 void CAgendaEntryToVCalConverter::AddRDatePropertyL(CVersitParser& aParser, RArray<TCalTime>& aRdates) |
|
1477 { |
|
1478 CArrayPtrFlat<TVersitDateTime>* dateList = new (ELeave) CArrayPtrFlat<TVersitDateTime>(4); |
|
1479 CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfVersitDateTime,dateList)); |
|
1480 |
|
1481 const TInt KCount(aRdates.Count()); |
|
1482 |
|
1483 for (TInt i = 0; i < KCount; ++i) |
|
1484 { |
|
1485 TCalTime sporadicDate = aRdates[i]; |
|
1486 TDateTime rDate; |
|
1487 if (iTimeType == TVersitDateTime::EIsUTC) |
|
1488 { |
|
1489 rDate=sporadicDate.TimeUtcL().DateTime(); |
|
1490 } |
|
1491 else |
|
1492 { |
|
1493 rDate=sporadicDate.TimeLocalL().DateTime(); |
|
1494 } |
|
1495 |
|
1496 // Construct a versit date-time property |
|
1497 TVersitDateTime* versitDateTime = new(ELeave) TVersitDateTime(rDate, iTimeType); |
|
1498 CleanupStack::PushL(versitDateTime); |
|
1499 versitDateTime->SetFlag(iTimeFlag); |
|
1500 dateList->AppendL(versitDateTime); |
|
1501 CleanupStack::Pop(); // versitDateTime |
|
1502 } |
|
1503 |
|
1504 CParserPropertyValue* value = new(ELeave)CParserPropertyValueMultiDateTime(dateList); |
|
1505 CleanupStack::Pop(dateList); |
|
1506 CleanupStack::PushL(value); |
|
1507 |
|
1508 CParserProperty* property = CParserProperty::NewL(*value, KVersitTokenRDATE, NULL); |
|
1509 CleanupStack::Pop(value); |
|
1510 |
|
1511 // Add to the parser |
|
1512 aParser.AddPropertyL(property);//aParser takes the ownership |
|
1513 } |
|
1514 |
|
1515 // Exception property |
|
1516 // |
|
1517 void CAgendaEntryToVCalConverter::AddRepeatExceptionPropertiesL(CVersitParser& aParser, RArray<TCalTime>& aExceptions) |
|
1518 { |
|
1519 CArrayPtrFlat<TVersitDateTime>* dateList = new(ELeave)CArrayPtrFlat<TVersitDateTime>(1); |
|
1520 CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfVersitDateTime, dateList)); |
|
1521 |
|
1522 TInt size = aExceptions.Count(); |
|
1523 |
|
1524 for (TInt count=0; count<size; count++) |
|
1525 { |
|
1526 TCalTime exception = aExceptions[count]; |
|
1527 |
|
1528 TDateTime date; |
|
1529 if (iTimeType == TVersitDateTime::EIsUTC) |
|
1530 { |
|
1531 date = exception.TimeUtcL().DateTime(); |
|
1532 } |
|
1533 else |
|
1534 { |
|
1535 date = exception.TimeLocalL().DateTime(); |
|
1536 } |
|
1537 |
|
1538 // Construct a date-time property |
|
1539 |
|
1540 TVersitDateTime* versitDateTime = new(ELeave) TVersitDateTime(date, iTimeType); |
|
1541 versitDateTime->SetFlag(iTimeFlag); |
|
1542 CleanupStack::PushL(versitDateTime); |
|
1543 dateList->AppendL(versitDateTime); |
|
1544 CleanupStack::Pop(); // versitDateTime |
|
1545 } |
|
1546 |
|
1547 CParserPropertyValue* value = new(ELeave)CParserPropertyValueMultiDateTime(dateList); |
|
1548 CleanupStack::Pop(); // dateList |
|
1549 |
|
1550 CleanupStack::PushL(value); |
|
1551 CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenEXDATE, NULL); |
|
1552 CleanupStack::Pop(value); |
|
1553 // Add to the parser |
|
1554 aParser.AddPropertyL(prop); |
|
1555 } |
|
1556 |
|
1557 // Creates a stream dictionary, from an embedded store and a stream ID |
|
1558 // |
|
1559 CStreamDictionary* CAgendaEntryToVCalConverter::CreateDictionaryLC(CEmbeddedStore& aEmbeddedStore, TStreamId& aId) |
|
1560 { |
|
1561 CStreamDictionary* dictionary = CStreamDictionary::NewLC(); |
|
1562 RStoreReadStream dicStream; |
|
1563 dicStream.OpenLC(aEmbeddedStore, aId); |
|
1564 dicStream >> *dictionary; |
|
1565 CleanupStack::PopAndDestroy(); //dicStream |
|
1566 return dictionary; |
|
1567 } |
|
1568 |
|
1569 |
|
1570 // The vCalendar CATEGORIES property has multiple property values so the property values |
|
1571 // are stored in an array. |
|
1572 // |
|
1573 // The categories of the entry are iterated through, and each category is added as a |
|
1574 // property value to the array. |
|
1575 // |
|
1576 void CAgendaEntryToVCalConverter::AddCategoryPropertyL(CVersitParser& aParser, const RPointerArray<CCalCategory>& aCategories) |
|
1577 { |
|
1578 CDesCArrayFlat* desArray = new(ELeave) CDesCArrayFlat(4); |
|
1579 CleanupStack::PushL(desArray); |
|
1580 |
|
1581 TInt categories = aCategories.Count(); |
|
1582 for (TInt count=0; count<categories; count++) |
|
1583 { |
|
1584 CCalCategory* category = aCategories[count]; |
|
1585 switch (category->Category()) |
|
1586 { |
|
1587 case CCalCategory::ECalAppointment: |
|
1588 desArray->AppendL(KVCalCategoriesAPPOINTMENT); |
|
1589 break; |
|
1590 case CCalCategory::ECalBusiness: |
|
1591 desArray->AppendL(KVCalCategoriesBUSINESS); |
|
1592 break; |
|
1593 case CCalCategory::ECalEducation: |
|
1594 desArray->AppendL(KVCalCategoriesEDUCATION); |
|
1595 break; |
|
1596 case CCalCategory::ECalHoliday: |
|
1597 desArray->AppendL(KVCalCategoriesHOLIDAY); |
|
1598 break; |
|
1599 case CCalCategory::ECalMeeting: |
|
1600 desArray->AppendL(KVCalCategoriesMEETING); |
|
1601 break; |
|
1602 case CCalCategory::ECalMiscellaneous: |
|
1603 desArray->AppendL(KVCalCategoriesMISCELLANEOUS); |
|
1604 break; |
|
1605 case CCalCategory::ECalPersonal: |
|
1606 desArray->AppendL(KVCalCategoriesPERSONAL); |
|
1607 break; |
|
1608 case CCalCategory::ECalPhoneCall: |
|
1609 desArray->AppendL(KVCalCategoriesPHONECALL); |
|
1610 break; |
|
1611 case CCalCategory::ECalSickDay: |
|
1612 desArray->AppendL(KVCalCategoriesSICKDAY); |
|
1613 break; |
|
1614 case CCalCategory::ECalSpecialOccasion: |
|
1615 desArray->AppendL(KVCalCategoriesSPECIALOCCASION); |
|
1616 break; |
|
1617 case CCalCategory::ECalTravel: |
|
1618 desArray->AppendL(KVCalCategoriesTRAVEL); |
|
1619 break; |
|
1620 case CCalCategory::ECalVacation: |
|
1621 desArray->AppendL(KVCalCategoriesVACATION); |
|
1622 break; |
|
1623 case CCalCategory::ECalExtended: |
|
1624 desArray->AppendL(category->ExtendedCategoryName()); |
|
1625 break; |
|
1626 default: |
|
1627 break; |
|
1628 } |
|
1629 } |
|
1630 |
|
1631 CParserPropertyValue* value = new (ELeave) CParserPropertyValueCDesCArray(desArray); |
|
1632 CleanupStack::Pop(); //desArray |
|
1633 |
|
1634 CleanupStack::PushL(value); |
|
1635 CParserProperty* prop = CParserProperty::NewL(*value, KVersitTokenCATEGORIES, NULL); |
|
1636 CleanupStack::Pop(value); |
|
1637 // Add to the parser |
|
1638 aParser.AddPropertyL(prop); |
|
1639 } |
|
1640 |
|
1641 /** |
|
1642 * Checks the status value and adds the appropriate status value to the export list |
|
1643 * held by the versit parser. |
|
1644 */ |
|
1645 void CAgendaEntryToVCalConverter::AddStatusPropertyL(CVersitParser& aParser, CCalEntry* aEntry) |
|
1646 { |
|
1647 switch(aEntry->StatusL()) |
|
1648 { |
|
1649 case CCalEntry::ETodoInProcess: |
|
1650 case CCalEntry::EVCalAccepted: |
|
1651 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusACCEPTED); |
|
1652 break; |
|
1653 case CCalEntry::ETodoNeedsAction: |
|
1654 case CCalEntry::EVCalNeedsAction: |
|
1655 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusNEEDSACTION); |
|
1656 break; |
|
1657 case CCalEntry::ETodoCompleted: |
|
1658 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCOMPLETED); |
|
1659 break; |
|
1660 |
|
1661 case CCalEntry::EConfirmed: |
|
1662 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusCONFIRMED); |
|
1663 break; |
|
1664 case CCalEntry::ECancelled: |
|
1665 case CCalEntry::EVCalDeclined: |
|
1666 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusDECLINED); |
|
1667 break; |
|
1668 case CCalEntry::ETentative: |
|
1669 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusTENTATIVE); |
|
1670 break; |
|
1671 case CCalEntry::EVCalSent: |
|
1672 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusSENT); |
|
1673 break; |
|
1674 case CCalEntry::EVCalDelegated: |
|
1675 AddDesPropertyL(aParser, KVCalTokenSTATUS, KVCalStatusDELEGATED); |
|
1676 break; |
|
1677 } |
|
1678 |
|
1679 } |
|
1680 |
|
1681 |
|
1682 |