--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pimappservices/calendar/client/src/calentryimpl.cpp Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,1812 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "calentryimpl.h"
+
+#include "calclient.h"
+#include "agsalarm.h"
+#include "agmattachment.h"
+#include "agmdate.h"
+#include "agmentry.h"
+#include "agmpanic.h"
+#include "agmcategory.h"
+#include "agmattendee.h"
+#include "agmcontent.h"
+#include <calalarm.h>
+#include "calcategoryimpl.h"
+#include <calcontent.h>
+#include <calrrule.h>
+#include <calsession.h>
+#include "calsessionimpl.h"
+#include "caluserimpl.h"
+
+const TInt KAttendeeGranularity = 2;
+const TInt KCategoryGranularity = 1;
+const TInt KAttachmentGranularity = 1;
+
+
+CCalEntryImpl::~CCalEntryImpl()
+ {
+ if(iSessionImpl)
+ {
+ iSessionImpl->DecrementReferenceCount();
+ }
+
+ if (iLiteEntry)
+ {
+ iLiteEntry->DecrementRefCount();
+ }
+ if(iCalAttachmentList)
+ {
+ iCalAttachmentList->ResetAndDestroy();
+ delete iCalAttachmentList;
+ }
+ if(iCalAttendeeList)
+ {
+ iCalAttendeeList->ResetAndDestroy();
+ delete iCalAttendeeList;
+ }
+ if(iCalCategoryList)
+ {
+ iCalCategoryList->ResetAndDestroy();
+ delete iCalCategoryList;
+ }
+ delete iCalOrganizer;
+ delete iFullEntry;
+ }
+
+CCalEntryImpl::CCalEntryImpl()
+ {
+ }
+
+CCalEntryImpl::CCalEntryImpl(CAgnEntry& aEntry, CCalSessionImpl& aSessionImpl)
+ : iFullEntry(&aEntry), iSessionImpl(&aSessionImpl)
+ {
+ iSessionImpl->IncrementReferenceCount();
+ }
+
+
+CCalEntryImpl::CCalEntryImpl(CCalLiteEntry& aEntry, CCalSessionImpl& aSessionImpl)
+ : iLiteEntry(&aEntry), iSessionImpl(&aSessionImpl)
+ {
+ iSessionImpl->IncrementReferenceCount();
+ iLiteEntry->IncrementRefCount();
+ }
+
+void CCalEntryImpl::ClearSimpleEntry()
+ {
+ if (iSessionImpl && iLiteEntry)
+ {
+ iLiteEntry->DecrementRefCount();
+ iLiteEntry = NULL;
+ }
+ }
+
+CCalEntryImpl* CCalEntryImpl::NewL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum)
+ {
+ __ASSERT_ALWAYS(aUid && aUid->Length() > 0, User::Leave(KErrArgument));
+
+ CCalEntryImpl* self = new (ELeave) CCalEntryImpl();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aUid, aMethod, aSeqNum); // takes ownership of aUid
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CCalEntryImpl* CCalEntryImpl::NewL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod,
+ TUint aSeqNum, const TCalTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange)
+ {
+ __ASSERT_ALWAYS(aUid && aUid->Length() > 0, User::Leave(KErrArgument));
+
+ CCalEntryImpl* self = new (ELeave) CCalEntryImpl();
+ CleanupStack::PushL(self);
+ self->ConstructL(aType, aUid, aMethod, aSeqNum, CalUtils::TCalTimeToTAgnCalendarTimeL(aRecurrenceId), aRange);
+ // takes ownership of aUid
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CCalEntryImpl* CCalEntryImpl::NewL(CAgnEntry& aEntry, CCalSessionImpl& aSessionImpl)
+ {
+ CCalEntryImpl* self = new (ELeave) CCalEntryImpl(aEntry, aSessionImpl);
+ return self;
+ }
+
+CCalEntryImpl* CCalEntryImpl::NewL(CCalLiteEntry& aEntry, CCalSessionImpl& aSessionImpl)
+ {
+ CCalEntryImpl* self = new (ELeave) CCalEntryImpl(aEntry, aSessionImpl);
+ return self;
+ }
+
+void CCalEntryImpl::ConstructL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum, const TAgnCalendarTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange)
+ {
+ // Create appropriate CAgnEntry type child entry.
+ iFullEntry = CAgnEntry::NewL(aType, aUid, aMethod, aSeqNum, aRecurrenceId, aRange); // takes ownership of aUid
+ }
+
+
+void CCalEntryImpl::ConstructL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum)
+ {
+ // Create appropriate CAgnEntry type parent entry.
+ iFullEntry = CAgnEntry::NewL(aType, aUid, aMethod,aSeqNum);
+ }
+
+void CCalEntryImpl::LoadFullEntryL()
+ {
+ if (iLiteEntry)
+ {
+ // iFullEntry should be NULL at this point
+ __ASSERT_DEBUG(iFullEntry == NULL, User::Leave(KErrCorrupt));
+
+ // extract full CAgnEntry from TAgnLiteEntry and store it in iFullEntry
+ TCalLocalUid id = iLiteEntry->LiteEntry().LocalUid();
+ iFullEntry = iSessionImpl->Server().FetchEntryL(id, iSessionImpl->FileId());
+ __ASSERT_ALWAYS(iFullEntry, User::Leave(KErrNotFound));
+ iFullEntry->SetCollectionId(iLiteEntry->LiteEntry().CollectionId());
+ ClearSimpleEntry();
+ }
+ }
+
+// return the CAgnEntry associated with this entry, loading it from the server if necessary
+CAgnEntry* CCalEntryImpl::GetFullEntryL()
+ {
+ LoadFullEntryL();
+ return iFullEntry;
+ }
+
+void CCalEntryImpl::PopulateCategoryListL()
+ {
+ if (!iCalCategoryList)
+ {
+ LoadFullEntryL();
+ iCalCategoryList = new (ELeave) RPointerArray<CCalCategory>(KCategoryGranularity);
+
+ const TInt KCategoryCount = iFullEntry->CategoryCount();
+ for (TInt i = 0; i < KCategoryCount; ++i)
+ {
+ CAgnCategory& agnCategory = iFullEntry->FetchCategory(i); // ownership not taken
+ CCalCategoryImpl* impl = CCalCategoryImpl::NewL(&agnCategory); // doesn't take ownership of agnCategory
+ CleanupStack::PushL(impl);
+ CCalCategory* category = CCalCategory::NewL(impl); // takes ownership of impl
+ CleanupStack::Pop(impl);
+ CleanupStack::PushL(category);
+ iCalCategoryList->AppendL(category); // takes ownership of category
+ CleanupStack::Pop(category);
+ }
+ }
+ }
+
+void CCalEntryImpl::PopulateAttendeeListL()
+ {
+ if(!iCalAttendeeList)
+ {
+ LoadFullEntryL();
+
+ iCalAttendeeList = new(ELeave) RPointerArray<CCalAttendee>(KAttendeeGranularity);
+
+ const TInt KAttendeeCount = iFullEntry->AttendeeCount();
+ for(TInt i = 0; i < KAttendeeCount; ++i)
+ {
+ CAgnAttendee& agnAttendee = iFullEntry->FetchAttendee(i);
+
+ CCalUserImpl* impl = CCalUserImpl::NewL(&agnAttendee); // doesn't take ownership of agnAttendee
+ CleanupStack::PushL(impl);
+ CCalAttendee* calAttendee = CCalAttendee::NewL(impl); // takes ownership of impl
+ CleanupStack::Pop(impl);
+
+ CleanupStack::PushL(calAttendee);
+ iCalAttendeeList->AppendL(calAttendee);
+ CleanupStack::Pop(calAttendee);
+ }
+ }
+ }
+
+
+void CCalEntryImpl::AddAttendeeL(CCalAttendee* aAttendee)
+ {
+ if (!aAttendee)
+ {
+ User::Leave( KErrArgument );
+ }
+
+ CleanupStack::PushL(aAttendee);
+ __ASSERT_ALWAYS(aAttendee != NULL, User::Leave(KErrArgument));
+ PopulateAttendeeListL();
+
+ CCalUserImpl* userImpl = aAttendee->Impl();
+ CAgnAttendee* attendee = userImpl->Attendee();
+
+ // add attendee to CAgnEntry (no longer owned by CCalAttendee)
+ userImpl->SetOwnsCAgnAttendee(EFalse);
+ iFullEntry->AddAttendeeL(attendee);
+
+ // store attendee in attendee array too
+ iCalAttendeeList->AppendL(aAttendee);
+ CleanupStack::Pop(aAttendee);
+ }
+
+RPointerArray<CCalAttendee>& CCalEntryImpl::AttendeesL()
+ {
+ PopulateAttendeeListL();
+ return *iCalAttendeeList;
+ }
+
+void CCalEntryImpl::DeleteAttendeeL(TInt aIndex)
+ {
+ LoadFullEntryL();
+
+ if(iCalAttendeeList)
+ {
+ if (aIndex < 0 || aIndex >= iCalAttendeeList->Count())
+ {
+ User::Leave(KErrArgument);
+ }
+ delete (*iCalAttendeeList)[aIndex];
+ iCalAttendeeList->Remove(aIndex);
+ }
+
+ iFullEntry->DeleteAttendee(aIndex);
+ }
+
+void CCalEntryImpl::SetOrganizerL(CCalUser* aUser)
+ {
+ CleanupStack::PushL(aUser);
+ __ASSERT_ALWAYS(aUser != NULL, User::Leave(KErrArgument));
+ LoadFullEntryL();
+
+ aUser->Impl()->SetOwnsCAgnAttendee(EFalse);
+ iFullEntry->SetOrganizerL(aUser->Impl()->Attendee()); // takes ownership of user immediately
+
+ delete iCalOrganizer;
+ iCalOrganizer = aUser;
+ CleanupStack::Pop(aUser);
+ }
+
+void CCalEntryImpl::SetPhoneOwnerL(const CCalUser* aOwner)
+ {
+ __ASSERT_ALWAYS(aOwner != NULL, User::Leave(KErrArgument));
+ LoadFullEntryL();
+ CCalUserImpl* userImpl = aOwner->Impl();
+ iFullEntry->SetPhoneOwnerL(userImpl->Attendee());
+ }
+
+CCalUser* CCalEntryImpl::PhoneOwnerL()
+ {
+ LoadFullEntryL();
+
+ CAgnAttendee* agnPhoneOwner = iFullEntry->PhoneOwner();
+
+ if(agnPhoneOwner)
+ {
+ //check to see if phone owner is the organizer
+ if(OrganizerL())
+ {
+ if(agnPhoneOwner == iCalOrganizer->Impl()->Attendee())
+ {
+ return iCalOrganizer;
+ }
+ }
+
+ PopulateAttendeeListL();
+
+ // see if the phone owner is one of the other attendees
+ const TInt KAttendeeCount = iCalAttendeeList->Count();
+ for(TInt i = 0; i < KAttendeeCount; ++i)
+ {
+ CCalAttendee* calAttendee = (*iCalAttendeeList)[i];
+ if(agnPhoneOwner == calAttendee->Impl()->Attendee())
+ {
+ return calAttendee;
+ }
+ }
+ }
+ return NULL;
+ }
+
+
+CCalUser* CCalEntryImpl::OrganizerL()
+ {
+ LoadFullEntryL();
+ if( ! iCalOrganizer)
+ {
+ CAgnAttendee* organizer = iFullEntry->Organizer();
+
+ if(organizer)
+ {
+ CCalUserImpl* impl = CCalUserImpl::NewL(organizer);
+ CleanupStack::PushL(impl);
+ impl->SetOwnsCAgnAttendee(EFalse);
+ iCalOrganizer = CCalUser::NewL(impl);
+ CleanupStack::Pop(impl);
+ }
+ }
+
+ return iCalOrganizer;
+ }
+
+CTzRules* CCalEntryImpl::GetTzRulesL()
+ {
+ CAgnRptDef* rptDef = SimpleEntry()->RptDef();
+
+ if (rptDef == NULL)
+ {
+ return NULL;
+ }
+ return rptDef->CloneTzRulesL();
+ }
+
+void CCalEntryImpl::SetTzRulesL(const CTzRules& aTzRules)
+ {
+ LoadFullEntryL();
+
+ if (TimeMode() == MAgnCalendarTimeMode::EFloating)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ CAgnRptDef* rptDef = SimpleEntry()->RptDef(); // doesn't take ownership
+
+ if (!rptDef)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ rptDef->SetTimeZoneL(aTzRules); // rptDef doesn't take ownership of aTzRules
+ }
+
+void CCalEntryImpl::SetTzRulesL()
+ {
+ LoadFullEntryL();
+
+ if (TimeMode() == MAgnCalendarTimeMode::EFloating)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ CAgnRptDef* rptDef = SimpleEntry()->RptDef();
+ if (rptDef == NULL)
+ {
+ User::Leave(KErrNotFound);
+ }
+ rptDef->SetTimeZoneL();
+ }
+
+void CCalEntryImpl::SetRDatesL(const RArray<TCalTime>& aRDates)
+ {
+ LoadFullEntryL();
+ SetDatesL(ETrue, aRDates);
+ }
+
+void CCalEntryImpl::SetExceptionDatesL(const RArray<TCalTime>& aExDates)
+ {
+ LoadFullEntryL();
+
+ if (iFullEntry->RptDef() == NULL)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ SetDatesL(EFalse, aExDates);
+ }
+
+//if aDateType is ETrue, add dates to sporadic date list
+//if aDateType is EFalse, add dates to exception list
+void CCalEntryImpl::SetDatesL(TBool aDateType, const RArray<TCalTime>& aDates)
+ {
+ const TCalTime::TTimeMode KEntryTimeMode = static_cast<TCalTime::TTimeMode>(TimeMode());
+ const TInt KDateCount = aDates.Count();
+ TInt i = 0;
+ for (i = 0; i < KDateCount; i++)
+ {
+ if (aDates[i].TimeMode() != KEntryTimeMode)
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+ CAgnRptDef* rptDef = SimpleEntry()->RptDef();
+
+ TBool entryHasNoRptDef(rptDef == NULL);
+ if (entryHasNoRptDef)
+ {
+ rptDef = CAgnRptDef::NewL(*SimpleEntry());
+ CleanupStack::PushL(rptDef);
+ }
+ else
+ {
+ if (aDateType)
+ {
+ rptDef->RemoveAllSporadicDates();
+ }
+ else
+ {
+ rptDef->RemoveAllExceptions();
+ }
+ }
+
+ // store the dates
+ for (i = 0; i < KDateCount; ++i)
+ {
+ TAgnCalendarTime agnTime = CalUtils::TCalTimeToTAgnCalendarTimeL(aDates[i]);
+ if (aDateType)
+ {
+ rptDef->AddSporadicDateL(agnTime);
+ }
+ else
+ {
+ rptDef->AddExceptionL(agnTime);
+ }
+ }
+
+ // if the rptDef didn't exist in the entry already, add it
+ if (entryHasNoRptDef)
+ {
+ iFullEntry->SetRptDefL(*rptDef); // makes a copy of rptDef
+ CleanupStack::PopAndDestroy(rptDef);
+ }
+ }
+
+void CCalEntryImpl::GetRDatesL(RArray<TCalTime>& aRDates)
+ {
+ aRDates.Reset();
+ const CAgnRptDef* KRptDef = SimpleEntry()->RptDef();
+ if (KRptDef)
+ {
+ FetchDatesL(KRptDef->SporadicDateList(), aRDates);
+ }
+ }
+
+void CCalEntryImpl::GetExceptionDatesL(RArray<TCalTime>& aExDates)
+ {
+ aExDates.Reset();
+ const CAgnRptDef* KRptDef = SimpleEntry()->RptDef();
+ if (KRptDef)
+ {
+ FetchDatesL(KRptDef->Exceptions(), aExDates);
+ }
+ }
+
+void CCalEntryImpl::FetchDatesL(const RArray<TAgnCalendarTime>* aDateList, RArray<TCalTime>& aRDates)
+ {
+ // aDateList may be NULL
+ if (aDateList)
+ {
+ const TInt KDateCount = aDateList->Count();
+ for (TInt i = 0; i < KDateCount; ++i)
+ {
+ TCalTime calTime = CalUtils::TAgnCalendarTimeToTCalTimeL((*aDateList)[i]);
+ aRDates.AppendL(calTime);
+ }
+ }
+ }
+
+CCalEntry::TMethod CCalEntryImpl::MethodL()
+ {
+ LoadFullEntryL();
+ return iFullEntry->Method();
+ }
+
+TCalTime CCalEntryImpl::RecurrenceIdL()
+ {
+ // If this entry has been committed to store, the Rec-Id can be retrieved from the
+ // CAgnEntryModel by passing the appropraite CAgnEntry.
+ // Else try to retrieve it from CAgnEntry's temporary GS data.
+
+ LoadFullEntryL();
+ return CalUtils::TAgnCalendarTimeToTCalTimeL(iFullEntry->RecurrenceId());
+ }
+
+CalCommon::TRecurrenceRange CCalEntryImpl::RecurrenceRangeL()
+ {
+ LoadFullEntryL();
+ return iFullEntry->RecurrenceRange();
+ }
+
+const TDesC8& CCalEntryImpl::UidL()
+ {
+ LoadFullEntryL();
+ // Does not transfer ownership
+ if(iFullEntry->Guid() == KNullDesC8)
+ {
+ // this entry must be a child entry whose GUID has not been loaded
+ __ASSERT_ALWAYS(iFullEntry->GsDataType() == CGsData::EChild, User::Leave(KErrCorrupt));
+
+ // get parent entry
+ TCalLocalUid parentId = iFullEntry->ParentId();
+ CAgnEntry* parentEntry = iSessionImpl->Server().FetchEntryL(parentId, iSessionImpl->FileId());
+ __ASSERT_ALWAYS(parentEntry, User::Leave(KErrNotFound));
+ CleanupStack::PushL(parentEntry);
+ HBufC8* guidHbuf = parentEntry->Guid().AllocL();
+ CleanupStack::PopAndDestroy(parentEntry);
+
+ iFullEntry->SetGuid(guidHbuf);
+ }
+
+ return iFullEntry->Guid();
+ }
+
+
+TInt CCalEntryImpl::SequenceNumberL()
+ {
+ LoadFullEntryL();
+ return iFullEntry->SequenceNumber();
+ }
+
+
+void CCalEntryImpl::SetMethodL(CCalEntry::TMethod aMethod)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetMethod(aMethod);
+ }
+
+const RPointerArray<CCalCategory>& CCalEntryImpl::CategoryListL()
+ {
+ PopulateCategoryListL();
+
+ return *iCalCategoryList;
+ }
+
+void CCalEntryImpl::AddCategoryL(CCalCategory* aCategory)
+ {
+ CleanupStack::PushL(aCategory);
+ __ASSERT_ALWAYS(aCategory != NULL, User::Leave(KErrArgument));
+
+ PopulateCategoryListL();
+
+ // add the category to the list
+ iCalCategoryList->AppendL(aCategory);
+ CleanupStack::Pop(aCategory);
+
+ TInt err(KErrNone);
+
+ // add category to CAgnEntry
+ TRAP(err , iFullEntry->AddCategoryL( aCategory->Impl()->AgnCategory() ) ); // this can leave before taking ownership
+
+ if (err != KErrNone)
+ {
+ delete (*iCalCategoryList)[iCalCategoryList->Count() - 1];
+ iCalCategoryList->Remove(iCalCategoryList->Count() - 1);
+ User::Leave(err);
+ }
+
+ aCategory->Impl()->SetOwnAgnCategory(EFalse);
+ }
+
+void CCalEntryImpl::DeleteCategoryL(TInt aIndex)
+ {
+ LoadFullEntryL();
+
+ if (aIndex < 0 || aIndex >= iFullEntry->CategoryCount())
+ {
+ User::Leave(KErrArgument);
+ }
+
+ iFullEntry->DeleteCategory(aIndex);
+ if(iCalCategoryList)
+ {
+ delete (*iCalCategoryList)[aIndex];
+ iCalCategoryList->Remove(aIndex);
+
+ // check count of CAgnCategory and CCalCategory is the same
+ __ASSERT_DEBUG(iCalCategoryList->Count() == iFullEntry->CategoryCount(), Panic(EAgmErrCategoryCountCorrupt));
+ }
+ }
+
+TBool CCalEntryImpl::GetRRuleL(TCalRRule& aRule)
+ {
+ const CAgnRptDef* KRptDef = SimpleEntry()->RptDef();
+ if (KRptDef == NULL || KRptDef->RRule() == NULL)
+ {
+ return EFalse;
+ }
+
+ const TAgnRpt* KRpt = KRptDef->RRule();
+
+ // get the DTSTART property
+ if (SimpleEntry()->Type() == CCalEntry::ETodo)
+ {
+ aRule.SetDtStart(EndTimeL());
+ }
+ else
+ {
+ aRule.SetDtStart(StartTimeL());
+ }
+
+ TInt repCount = 0;
+ TCalTime untilCaltime = CalUtils::TAgnCalendarTimeToTCalTimeL(KRpt->UntilTimeL());
+
+ if (untilCaltime.TimeLocalL() == TCalTime::MaxTime())
+ {
+ //Idealy, only UTC maximum time should be used to indicate the repeating forever. However, for a behaviour compatible reason,
+ //when the client sets local or UTC repeating until time to be maximum time, it is treated as repeating forever.
+ untilCaltime.SetTimeUtcL(TCalTime::MaxTime());
+ }
+ else
+ {
+ repCount = KRpt->InstanceCountL();
+ }
+
+ aRule.SetUntilAndCount(untilCaltime, repCount);
+
+ // get the INTERVAL property
+ aRule.SetInterval(KRpt->Interval());
+
+ // get the TCalRRule's type, and type-specific data
+ switch (KRpt->Type())
+ {
+ case TAgnRpt::EDaily:
+ aRule.SetType(TCalRRule::EDaily);
+ break;
+ case TAgnRpt::EYearlyByDate:
+ aRule.SetType(TCalRRule::EYearly);
+ break;
+ case TAgnRpt::EYearlyByDay:
+ {
+ aRule.SetType(TCalRRule::EYearly);
+
+ TDay day;
+ TAgnRpt::TWeekInMonth weekInMonth;
+ TMonth month;
+ TInt year;
+
+ const TAgnYearlyByDayRpt* KYearlyRpt = static_cast<const TAgnYearlyByDayRpt*>(KRpt);
+ KYearlyRpt->GetStartDayL(day, weekInMonth, month, year);
+ TInt8 week = CalUtils::AgnWeekInMonthToWeekNumberL(weekInMonth);
+ TCalRRule::TDayOfMonth dayOfMonth(day, week);
+
+ RArray<TCalRRule::TDayOfMonth> dayOfMonthArray;
+ CleanupClosePushL(dayOfMonthArray);
+ dayOfMonthArray.AppendL(dayOfMonth);
+ aRule.SetByDay(dayOfMonthArray);
+ CleanupStack::PopAndDestroy(&dayOfMonthArray);
+
+ RArray<TMonth> monthArray;
+ CleanupClosePushL(monthArray);
+ monthArray.AppendL(month);
+ aRule.SetByMonth(monthArray);
+ CleanupStack::PopAndDestroy(&monthArray);
+ }
+ break;
+ case TAgnRpt::EWeekly:
+ {
+ aRule.SetType(TCalRRule::EWeekly);
+ const TAgnWeeklyRpt* KWeeklyRpt = static_cast<const TAgnWeeklyRpt*>(KRpt);
+ aRule.SetWkSt(KWeeklyRpt->FirstDayOfWeek());
+
+ RArray<TDay> array;
+ CleanupClosePushL(array);
+ TDay day = EMonday;
+ while (day <= ESunday)
+ {
+ if (KWeeklyRpt->IsDaySet(day))
+ {
+ array.AppendL(day);
+ }
+ day = static_cast<TDay>(static_cast<TInt>(day) + 1);
+ }
+ aRule.SetByDay(array);
+ CleanupStack::PopAndDestroy(&array);
+ }
+ break;
+ case TAgnRpt::EMonthlyByDays:
+ {
+ aRule.SetType(TCalRRule::EMonthly);
+ const TAgnMonthlyByDaysRpt* KMonthlyByDayRpt = static_cast<const TAgnMonthlyByDaysRpt*>(KRpt);
+
+ RArray<TCalRRule::TDayOfMonth> dayArray;
+ CleanupClosePushL(dayArray);
+
+ TAgnRpt::TWeekInMonth week = TAgnRpt::EFirst;
+ while (week <= TAgnRpt::ELast)
+ {
+ TDay day = EMonday;
+ while (day <= ESunday)
+ {
+ if (KMonthlyByDayRpt->IsDaySet(day, week))
+ {
+ TInt8 weekInt = CalUtils::AgnWeekInMonthToWeekNumberL(week);
+ TCalRRule::TDayOfMonth dayOfMonth(day, weekInt);
+ dayArray.AppendL(dayOfMonth);
+ }
+ day = static_cast<TDay>(static_cast<TInt>(day) + 1);
+ }
+
+ week = static_cast<TAgnRpt::TWeekInMonth>(static_cast<TInt>(week) + 1);
+ }
+ //coverity [dead_error_begin]
+ aRule.SetByDay(dayArray);
+
+ CleanupStack::PopAndDestroy(&dayArray); // dayArray.Close()
+ }
+ break;
+ case TAgnRpt::EMonthlyByDates:
+ {
+ aRule.SetType(TCalRRule::EMonthly);
+ const TAgnMonthlyByDatesRpt* KMonthlyByDateRpt = static_cast<const TAgnMonthlyByDatesRpt*>(KRpt);
+
+ RArray<TInt> array;
+ CleanupClosePushL(array);
+ for (TInt i = 0; i < 31; ++i) // dates run from 0 to 30
+ {
+ if (KMonthlyByDateRpt->IsDateSet(i))
+ {
+ array.AppendL(i);
+ }
+ }
+ aRule.SetByMonthDay(array);
+ CleanupStack::PopAndDestroy(&array);
+ }
+ break;
+ default:
+ CalUtils::Panic(EInvalidRepeatRuleType);
+ break;
+ }
+
+ return ETrue;
+ }
+
+TBool CCalEntryImpl::CompareL(const CCalEntry& aEntry)
+ {
+ // load full CAgnEntries before comparison
+ LoadFullEntryL();
+ aEntry.Impl()->LoadFullEntryL();
+
+ // Load both entry's summary, description and alarm action data before comparing - these properties
+ // are stored in separate streams so may not be loaded at this point
+ SummaryL();
+ aEntry.SummaryL();
+ DescriptionL();
+ aEntry.DescriptionL();
+ delete AlarmL();
+ delete aEntry.AlarmL();
+
+ return (iFullEntry->CompareL(*aEntry.Impl()->GetFullEntryL()));
+ }
+
+void CCalEntryImpl::CopyFromL(CCalEntryImpl& aOther, CCalEntry::TCopyType aCopyType)
+ {
+ TCalCollectionId collectionId = 0;
+ if (iLiteEntry)
+ {
+ TUint8 collectionId = aOther.SimpleEntry()->CollectionId();
+ }
+ aOther.LoadFullEntryL();
+ // Delete old state.
+ ClearSimpleEntry();
+
+ if(iCalAttendeeList)
+ {
+ iCalAttendeeList->ResetAndDestroy();
+ delete iCalAttendeeList;
+ iCalAttendeeList = NULL;
+ }
+
+ if(iCalCategoryList)
+ {
+ iCalCategoryList->ResetAndDestroy();
+ delete iCalCategoryList;
+ iCalCategoryList = NULL;
+ }
+
+ delete iCalOrganizer;
+ iCalOrganizer = NULL;
+
+ if(iSessionImpl)
+ {
+ // Use this entry's existing uid.
+ iSessionImpl->DecrementReferenceCount();
+ }
+ iSessionImpl = aOther.iSessionImpl;
+ if (iSessionImpl)
+ {
+ iSessionImpl->IncrementReferenceCount();
+ }
+
+ // ensure other entry has a full CAgnEntry
+ aOther.LoadFullEntryL();
+
+ // ensure other entry has summary, description and alarm action properties loaded - these
+ // are stored in separate streams
+ aOther.SummaryL();
+ aOther.DescriptionL();
+ delete aOther.AlarmL();
+
+ iFullEntry->CopyFromL(*aOther.iFullEntry, aCopyType);
+ iFullEntry->SetLastModifiedDate();
+ iFullEntry->SetCollectionId(collectionId);
+ }
+
+void CCalEntryImpl::SetAlarmL(CCalAlarm* aAlarm)
+ {
+ LoadFullEntryL();
+
+ if ( aAlarm == NULL )
+ {
+ // if aAlarm is NULL, clear the alarm data
+ iFullEntry->ClearAlarm();
+ }
+ else
+ {
+ // This method does not take ownership of aAlarm, so need to copy the alarm details
+ // before adding to the entry.
+
+ // the alarm must be on the same day in local time as the event
+ TDateTime dt = iFullEntry->EntryTime().LocalL().DateTime();
+ TInt minutes = dt.Hour()*60 + dt.Minute();
+ __ASSERT_ALWAYS(minutes - aAlarm->TimeOffset().Int() <= KAgnMinutesInADay, User::Leave(KErrNotSupported));
+
+ iFullEntry->SetAlarmOffset(aAlarm->TimeOffset());
+ iFullEntry->SetAlarmSoundNameL(aAlarm->AlarmSoundNameL());
+
+ CCalContent* alarmAction = aAlarm->AlarmAction(); // doesn't take ownership
+
+ if ( alarmAction )
+ {
+ CAgnContent* agnAlarmAction = static_cast<CAgnContent*>(alarmAction->Impl());
+
+ if ( agnAlarmAction )
+ {
+ CAgnContent* alarmActionCopy = agnAlarmAction->CloneL();
+ iFullEntry->SetAlarmAction(alarmActionCopy); // entry takes ownership of alarmActionCopy
+ }
+ }
+ else
+ {
+ iFullEntry->SetAlarmAction(NULL);
+ }
+ }
+ }
+
+CCalAlarm* CCalEntryImpl::AlarmL()
+ {
+ LoadFullEntryL();
+
+ if (!iFullEntry->HasAlarm())
+ {
+ return NULL;
+ }
+
+ TTime time = iFullEntry->EntryTime().LocalL();
+
+ // Invalid or non-existant entries are set on import to NULL time
+ // That being the case, we return NULL for the Alarm.
+ TDateTime timeOfEvent;
+ if(time == Time::NullTTime())
+ {
+ return NULL;
+ }
+ else
+ {
+ timeOfEvent = time.DateTime();
+ }
+
+ CCalAlarm* alarm = CCalAlarm::NewL();
+ CleanupStack::PushL(alarm);
+
+ alarm->SetTimeOffset(iFullEntry->AlarmOffset().Int());
+ alarm->SetAlarmSoundNameL(iFullEntry->AlarmSoundName());
+
+ if(!iFullEntry->AlarmActionIsLoaded())
+ {
+ CAgnContent* agnAlarmaction = iSessionImpl->Server().RestoreAlarmActionL(iFullEntry->AlarmActionStreamId(), iSessionImpl->FileId());
+ // Restore should always return something, even if it's only a Null Descriptor
+ iFullEntry->SetAlarmAction(agnAlarmaction);
+ }
+
+ if (iFullEntry->AlarmAction())
+ {
+ CCalContent* alarmAction = CCalContent::NewL();
+ CleanupStack::PushL(alarmAction);
+ CAgnContent* agnAlarmActionCopy = iFullEntry->AlarmAction()->CloneL();
+ alarmAction->SetImpl(agnAlarmActionCopy); // Takes ownership of agnAlarmAction.
+ alarm->SetAlarmAction(alarmAction); // Takes ownership of alarmAction.
+ CleanupStack::Pop(alarmAction);
+ }
+
+ CleanupStack::Pop(alarm);
+ return alarm;
+ }
+
+void CCalEntryImpl::SetCommonRptDataL(const TCalRRule& aRpt, CAgnRptDef& aRptRule)
+ {
+ // set repeat rule data which is not specific to the rule type
+ // Both repeating count and until time could be set. If so, the one come earlist will be set as repeating until time.
+ // Note that the repeating until time will be adjusted in TAgnRpt::UntilTimeL() when the entry is stored (CCalEntryViewImpl::DoStore and
+ // CAgnSimpleEntry::AdjustStartUntilTimeForRepEntryL)By then, the TZ rule has been set to a repeating entry.
+ aRptRule.SetInterval(aRpt.Interval());
+ const_cast<TAgnRpt*> (aRptRule.RRule())->SetCount(aRpt.Count());
+
+ TTime untilTime = aRpt.Until().TimeLocalL();
+ if (untilTime != Time::NullTTime())
+ {
+ TAgnCalendarTime untilTimeTAgn = CalUtils::TCalTimeToTAgnCalendarTimeL(aRpt.Until());
+ aRptRule.SetUntilTime(untilTimeTAgn);
+ }
+ }
+
+void CCalEntryImpl::SetRRuleL(const TCalRRule& aRpt)
+ {
+ if (aRpt.Until().TimeLocalL() != Time::NullTTime() && aRpt.DtStart().TimeLocalL() >= aRpt.Until().TimeLocalL())
+ {
+ // if Until time is set to earlier than the start time and is non-NULL, leave
+ User::Leave(KErrArgument);
+ }
+ LoadFullEntryL();
+
+ //Leaves if this is a todo entry and its end date has not been set or this is a non-todo entry and its start date has not been set
+ //since repeating pattern is based on those time attributes.
+ if ( ! iFullEntry->EntryTime().IsSet())
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TBool createdNewRptDef = EFalse;
+ CAgnRptDef* rptDef = iFullEntry->RptDef();
+ if(rptDef == NULL)
+ {
+ rptDef = CAgnRptDef::NewL(*iFullEntry);
+ CleanupStack::PushL(rptDef);
+ createdNewRptDef = ETrue;
+ }
+
+ switch (aRpt.Type())
+ {
+ case TCalRRule::EDaily:
+ {
+ TAgnDailyRpt daily(*rptDef);
+ rptDef->SetRRuleL(daily);
+ }
+ break;
+ case TCalRRule::EWeekly:
+ {
+ TAgnWeeklyRpt weekly(*rptDef);
+ weekly.SetFirstDayOfWeek(aRpt.WkSt());
+ RArray<TDay> array;
+ CleanupClosePushL(array);
+ aRpt.GetByDayL(array);
+ const TInt KWeeklyDayCount = array.Count();
+ for (TInt i = 0; i < KWeeklyDayCount; ++i)
+ {
+ weekly.SetDay(array[i]);
+ }
+ CleanupStack::PopAndDestroy(&array);
+
+ rptDef->SetRRuleL(weekly);
+ }
+ break;
+ case TCalRRule::EMonthly:
+ {
+ RArray<TInt> array;
+ CleanupClosePushL(array);
+ aRpt.GetByMonthDayL(array);
+ if (array.Count() <= 0)
+ {
+ // may be monthly by week
+ RArray<TCalRRule::TDayOfMonth> dayArray;
+ CleanupClosePushL(dayArray);
+ aRpt.GetByDayL(dayArray);
+ const TInt KMonthlyDayCount = dayArray.Count();
+ if (KMonthlyDayCount > 0)
+ {
+ TAgnMonthlyByDaysRpt monthlyByDayAndWeek(*rptDef);
+ for (TInt i = 0; i < KMonthlyDayCount; ++i)
+ {
+ TCalRRule::TDayOfMonth dayOfMonth = dayArray[i];
+ TAgnRpt::TWeekInMonth weekNum = CalUtils::WeekNumberToAgnWeekInMonthL(dayOfMonth.WeekInMonth());
+ monthlyByDayAndWeek.SetDay(dayOfMonth.Day(), weekNum);
+ }
+
+ rptDef->SetRRuleL(monthlyByDayAndWeek);
+ }
+ CleanupStack::PopAndDestroy(&dayArray); // dayArray.Close()
+ }
+ else
+ {
+ TAgnMonthlyByDatesRpt monthlyByDate(*rptDef);
+ const TInt KMonthlyDateCount = array.Count();
+ for (TInt i = 0; i < KMonthlyDateCount; ++i)
+ {
+ monthlyByDate.SetDate(array[i]);
+ }
+
+ rptDef->SetRRuleL(monthlyByDate);
+ }
+ CleanupStack::PopAndDestroy(&array); // array.Reset();
+ }
+ break;
+ case TCalRRule::EYearly:
+ {
+ RArray<TCalRRule::TDayOfMonth> dayArray;
+ CleanupClosePushL(dayArray);
+ aRpt.GetByDayL(dayArray);
+ if (dayArray.Count() > 0)
+ {
+ RArray<TMonth> monthArray;
+ CleanupClosePushL(monthArray);
+ aRpt.GetByMonthL(monthArray);
+ if (monthArray.Count() > 0)
+ {
+ TDay day = dayArray[0].Day();
+ TAgnRpt::TWeekInMonth week = CalUtils::WeekNumberToAgnWeekInMonthL(dayArray[0].WeekInMonth());
+ TMonth month = monthArray[0];
+
+ TAgnYearlyByDayRpt yearlyByDay(*rptDef);
+
+ // Check that the first month to repeat on is earlier than the repeat dtstart date...
+ TDateTime rptStartTime = aRpt.DtStart().TimeUtcL().DateTime();
+ TInt year = rptStartTime.Year();
+ if (month < rptStartTime.Month())
+ {
+ // ...if not, start the following year
+ year++;
+ }
+
+ TTime newStartDay = yearlyByDay.FindStartDayL(day, week, month, year);
+ TCalTime newStartDaycal;
+ newStartDaycal.SetTimeLocalL(newStartDay);
+ const_cast<TCalRRule&>(aRpt).SetDtStart(newStartDaycal);
+ TTime untilTimeLocal = yearlyByDay.UntilTimeL().LocalL();
+ TDateTime rptUntilTime = untilTimeLocal.DateTime();
+ if (aRpt.Count() != 0 || year < rptUntilTime.Year() ||
+ (year == rptUntilTime.Year() && month < rptUntilTime.Month())
+ )
+ {
+ // The count has been set
+ // or the first month to repeat on is not later than the repeat until date
+ rptDef->SetRRuleL(yearlyByDay);
+ }
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ CleanupStack::PopAndDestroy(&monthArray);
+ }
+ else
+ {
+ TAgnYearlyByDateRpt yearlyByDate(*rptDef);
+ rptDef->SetRRuleL(yearlyByDate);
+ }
+ CleanupStack::PopAndDestroy(&dayArray);
+ }
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ if (rptDef->RRule())
+ {
+ SetCommonRptDataL(aRpt, *rptDef);
+ }
+
+ if (createdNewRptDef)
+ {
+ if (rptDef->RRule())
+ {
+ iFullEntry->SetRptDefL(*rptDef);
+ }
+ CleanupStack::PopAndDestroy(rptDef);
+ }
+
+ //Move the entry start date is same as repeating date
+
+ TDateTime newEntryDateTime;
+ if(EntryTypeL() == CCalEntry::ETodo)
+ {
+ newEntryDateTime = EndTimeL().TimeLocalL().DateTime();
+ }
+ else
+ {
+ newEntryDateTime = StartTimeL().TimeLocalL().DateTime();
+ }
+
+ newEntryDateTime.SetYear(aRpt.DtStart().TimeLocalL().DateTime().Year());
+ newEntryDateTime.SetMonth(aRpt.DtStart().TimeLocalL().DateTime().Month());
+ newEntryDateTime.SetDay(aRpt.DtStart().TimeLocalL().DateTime().Day());
+
+ //adjust the entrytime (it the entry start time for non-todos and end time for todos)
+ iFullEntry->MoveStartTimeLocalL(newEntryDateTime);
+ }
+
+void CCalEntryImpl::ClearRepeatingPropertiesL()
+ {
+ SimpleEntry()->ClearRepeat();
+ }
+
+TCalTime CCalEntryImpl::NextInstanceForLocalUIDL(const TCalTime& aTime)
+ {
+ const TTime KTimeUtc = aTime.TimeUtcL() + TTimeIntervalMicroSeconds(1);
+ TTime nextTimeUtc = Time::NullTTime();
+
+ const CAgnRptDef* KRptDef = SimpleEntry()->RptDef();
+ if (KRptDef)
+ {
+ if (KRptDef->NudgeNextInstanceUtcL(KTimeUtc, nextTimeUtc) == EFalse)
+ {
+ nextTimeUtc = Time::NullTTime();
+ }
+ }
+ else
+ {
+ TTime entryTimeUtc = SimpleEntry()->EntryTime().UtcL();
+ if (KTimeUtc < entryTimeUtc)
+ {
+ nextTimeUtc = entryTimeUtc;
+ }
+ }
+
+ TCalTime calTime;
+ calTime.SetTimeUtcL(nextTimeUtc);
+ return calTime;
+ }
+
+TCalTime CCalEntryImpl::PreviousInstanceForLocalUIDL(const TCalTime& aTime)
+ {
+ const TTime KTimeUtc = aTime.TimeUtcL() - TTimeIntervalMicroSeconds(1);
+ TTime prevTimeUtc = Time::NullTTime();
+
+ const CAgnRptDef* KRptDef = SimpleEntry()->RptDef();
+ if (KRptDef)
+ {
+ if (KRptDef->NudgePreviousInstanceUtcL(KTimeUtc, prevTimeUtc) == EFalse)
+ {
+ prevTimeUtc = Time::NullTTime();
+ }
+ }
+ else
+ {
+ TTime entryTimeUtc = SimpleEntry()->EntryTime().UtcL();
+ if (KTimeUtc > entryTimeUtc)
+ {
+ prevTimeUtc = entryTimeUtc;
+ }
+ }
+
+ TCalTime calTime;
+ calTime.SetTimeUtcL(prevTimeUtc);
+ return calTime;
+ }
+
+TCalTime CCalEntryImpl::LastModifiedDateL()
+ {
+ TTime lastModifiedEntry = SimpleEntry()->LastModifiedDateUtc();
+ if(iSessionImpl && SimpleEntry()->RptDef() && SimpleEntry()->TimeMode()!= MAgnCalendarTimeMode::EFloating)
+ {
+ TTime lastModifiedTzChange = iSessionImpl->TzRulesLastModifiedDateL();
+ if(lastModifiedTzChange>lastModifiedEntry)
+ {
+ lastModifiedEntry = lastModifiedTzChange;
+ }
+ }
+ TCalTime lastModifiedTime;
+ lastModifiedTime.SetTimeUtcL(lastModifiedEntry);
+ return lastModifiedTime;
+ }
+
+TCalTime CCalEntryImpl::DTStampL()
+ {
+ LoadFullEntryL();
+ TCalTime dTStampTime;
+ dTStampTime.SetTimeUtcL(iFullEntry->DTStampUtcL());
+ return dTStampTime;
+ }
+
+void CCalEntryImpl::SetLocationL(const TDesC& aLocation)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetLocationL(aLocation);
+ }
+
+const TDesC& CCalEntryImpl::LocationL()
+ {
+ LoadFullEntryL();
+ return iFullEntry->Location();
+ }
+
+void CCalEntryImpl::SetPriorityL(TUint aPriority)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetPriority(aPriority);
+ }
+
+TUint CCalEntryImpl::PriorityL()
+ {
+ return SimpleEntry()->Priority();
+ }
+
+TCalTime CCalEntryImpl::StartTimeL()
+ {
+ return CalUtils::TAgnCalendarTimeToTCalTimeL(SimpleEntry()->StartTime());
+ }
+
+TCalTime CCalEntryImpl::EndTimeL()
+ {
+ TCalTime calEndTime; // initialised to Null time on construction
+ if (SimpleEntry()->Type() != CCalEntry::EReminder)
+ {
+ calEndTime = CalUtils::TAgnCalendarTimeToTCalTimeL(SimpleEntry()->EndTime());
+ }
+ return calEndTime;
+ }
+
+void CCalEntryImpl::SetStartAndEndTimeL(const TCalTime& aStartTime, const TCalTime& aEndTime)
+ {
+ LoadFullEntryL();
+ TCalTime::TTimeMode mode = aStartTime.TimeMode();
+ if (aEndTime.TimeUtcL() != Time::NullTTime())
+ {
+ if (aStartTime.TimeUtcL() != Time::NullTTime())
+ {
+ // both times are non-null so check the modes
+ __ASSERT_ALWAYS(aStartTime.TimeMode() == aEndTime.TimeMode(), User::Leave(KErrArgument));
+
+ // both times are non-null so check that end time is not earlier than start time
+ __ASSERT_ALWAYS(aStartTime.TimeUtcL() <= aEndTime.TimeUtcL(), User::Leave(KErrArgument));
+ }
+ else
+ {
+ // start time non-null so fetch mode from end time
+ mode = aEndTime.TimeMode();
+ }
+ }
+ __ASSERT_ALWAYS(mode == TCalTime::EFixedUtc || mode == TCalTime::EFloating, User::Leave(KErrArgument));
+
+ // either this is a parent entry, or time mode should match recurrence ID
+ __ASSERT_ALWAYS(RecurrenceIdL().TimeUtcL() == Time::NullTTime() ||
+ mode == RecurrenceIdL().TimeMode(),
+ User::Leave(KErrArgument));
+
+ TAgnCalendarTime agnStartTime = CalUtils::TCalTimeToTAgnCalendarTimeL(aStartTime);
+ TAgnCalendarTime agnEndTime = CalUtils::TCalTimeToTAgnCalendarTimeL(aEndTime);
+
+ const CCalEntry::TType KType = SimpleEntry()->Type();
+
+ switch (KType)
+ {
+ case CCalEntry::ETodo:
+ // for todos, if end time is not set, set start time to null as well - this is an undated entry
+ if ( ! agnEndTime.IsSet())
+ {
+ agnStartTime = agnEndTime;
+ }
+ break;
+ case CCalEntry::EReminder:
+ // for reminders, end time is the same as start time
+ agnEndTime = agnStartTime;
+ break;
+ case CCalEntry::EAppt:
+ case CCalEntry::EAnniv:
+ case CCalEntry::EEvent:
+ // for other entries, if end time is not set, make it the same as the start time
+ if ( ! agnEndTime.IsSet())
+ {
+ agnEndTime = agnStartTime;
+ }
+ break;
+ default:
+ // bad entry type
+ User::Leave(KErrArgument);
+ break;
+ }
+
+ iFullEntry->SetStartAndEndTimeL(agnStartTime, agnEndTime);
+ }
+
+MAgnCalendarTimeMode::TTimeMode CCalEntryImpl::TimeMode() const
+ {
+ return SimpleEntry()->TimeMode();
+ }
+
+TCalTime CCalEntryImpl::CompletedTimeL()
+ {
+ TTime completedDateUtc(Time::NullTTime());
+ if (SimpleEntry()->Type() == CCalEntry::ETodo)
+ {
+ completedDateUtc = SimpleEntry()->CompletedDateUtc();
+ }
+ TCalTime calCompletedDate;
+ calCompletedDate.SetTimeUtcL(completedDateUtc);
+ return calCompletedDate;
+ }
+
+void CCalEntryImpl::SetCompletedL(TBool aCompleted, const TCalTime& aDate)
+ {
+ LoadFullEntryL();
+ if (SimpleEntry()->Type() == CCalEntry::ETodo)
+ {
+ if (aCompleted)
+ {
+ SimpleEntry()->SetCompletedDateUtcL(aDate.TimeUtcL());
+ SetStatusL(CCalEntry::ETodoCompleted);
+ }
+ else
+ {
+ SimpleEntry()->SetIncomplete(); // resets completed date to null time
+ SetStatusL(CCalEntry::ETodoNeedsAction);
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+void CCalEntryImpl::SetSummaryL(const TDesC& aSummary)
+ {
+ LoadFullEntryL();
+ HBufC* summ = aSummary.AllocL();
+ iFullEntry->SetSummary(summ); // takes ownership of aSummary
+ }
+
+const TDesC& CCalEntryImpl::SummaryL()
+ {
+ LoadFullEntryL();
+
+ if(!iFullEntry->SummaryIsLoaded())
+ {
+ __ASSERT_DEBUG(iFullEntry->SummaryStreamId() != KNullStreamId, Panic(EAgmNoNotesStreamId));
+ HBufC* summary = iSessionImpl->Server().RestoreTextL(iFullEntry->SummaryStreamId(), iSessionImpl->FileId());
+ // Restore should always return something, even if it's only a Null Descriptor
+ iFullEntry->SetSummary(summary);
+ }
+
+ return iFullEntry->Summary();
+ }
+
+void CCalEntryImpl::SetDescriptionL(const TDesC& aDescription)
+ {
+ LoadFullEntryL();
+ HBufC* desc = aDescription.AllocL();
+ iFullEntry->SetDescription(desc); // takes ownership of aDescription
+ }
+
+const TDesC& CCalEntryImpl::DescriptionL()
+ {
+ LoadFullEntryL();
+
+ if(!iFullEntry->DescriptionIsLoaded())
+ {
+ __ASSERT_DEBUG(iFullEntry->DescriptionStreamId() != KNullStreamId, Panic(EAgmNoNotesStreamId));
+ HBufC* description = iSessionImpl->Server().RestoreTextL(iFullEntry->DescriptionStreamId(), iSessionImpl->FileId());
+ // Restore should always return something, even if it's only a Null Descriptor
+ iFullEntry->SetDescription(description);
+ }
+
+ return iFullEntry->Description();
+ }
+
+CCalEntry::TType CCalEntryImpl::EntryTypeL()
+ {
+ return SimpleEntry()->Type();
+ }
+
+void CCalEntryImpl::SetStatusL(CCalEntry::TStatus aStatus)
+ {
+ LoadFullEntryL();
+ switch (aStatus)
+ {
+ case CCalEntry::ETentative:
+ case CCalEntry::EConfirmed:
+ __ASSERT_ALWAYS(EntryTypeL() != CCalEntry::ETodo, User::Leave(KErrNotSupported));
+ break;
+ case CCalEntry::ECancelled:
+ SimpleEntry()->SetIncomplete();
+ break;
+
+ case CCalEntry::ETodoCompleted:
+ case CCalEntry::ETodoNeedsAction:
+ case CCalEntry::ETodoInProcess:
+ __ASSERT_ALWAYS(EntryTypeL() == CCalEntry::ETodo, User::Leave(KErrNotSupported));
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ if (aStatus == CCalEntry::ETodoCompleted)
+ {
+ if (iFullEntry->CompletedDateUtc() == Time::NullTTime())
+ {
+ TTime time;
+ time.UniversalTime();
+ iFullEntry->SetCompletedDateUtcL(time);
+ }
+ }
+
+ iFullEntry->SetStatus(aStatus);
+ }
+
+void CCalEntryImpl::SetReplicationStatusL(CCalEntry::TReplicationStatus aReplicationStatus)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetReplicationStatusL(aReplicationStatus);
+ }
+
+CCalEntry::TReplicationStatus CCalEntryImpl::ReplicationStatusL()
+ {
+ LoadFullEntryL();
+ return iFullEntry->ReplicationStatus();
+ }
+
+CCalEntry::TStatus CCalEntryImpl::StatusL()
+ {
+ return SimpleEntry()->Status();
+ }
+
+void CCalEntryImpl::SetSequenceNumberL(TInt aSeqNum)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetSequenceNumber(aSeqNum);
+ }
+
+void CCalEntryImpl::SetLastModifiedDateL()
+ {
+ LoadFullEntryL();
+ iFullEntry->SetLastModifiedDate();
+ }
+
+void CCalEntryImpl::SetLastModifiedDateL(const TCalTime& aModifiedTime)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetLastModifiedDateUtc(aModifiedTime.TimeUtcL());
+ }
+
+void CCalEntryImpl::SetDTStampL(const TCalTime& aDTStampTime)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetDTStampUtcL(aDTStampTime.TimeUtcL());
+ }
+
+TAgnEntryId CCalEntryImpl::AgnEntryIdL()
+ {
+ return SimpleEntry()->EntryId();
+ }
+
+void CCalEntryImpl::SetLocalUidL(TCalLocalUid aLocalId)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetLocalUid(aLocalId);
+ }
+
+TCalLocalUid CCalEntryImpl::LocalUidL()
+ {
+ if(iLiteEntry)
+ {
+ return iLiteEntry->LiteEntry().LocalUid();
+ }
+ else
+ {
+ return iFullEntry->LocalUid();
+ }
+ }
+
+TUint8 CCalEntryImpl::ShortFileIdL()
+ {
+ if(iLiteEntry)
+ {
+ return iLiteEntry->LiteEntry().CollectionId();
+ }
+ else
+ {
+ return iFullEntry->CollectionId();
+ }
+ }
+
+CCalEntry::TTransp CCalEntryImpl::BusyStatusL()
+ {
+ LoadFullEntryL();
+ return iFullEntry->BusyStatus();
+ }
+
+void CCalEntryImpl::SetBusyStatusL(CCalEntry::TTransp aBusyStatus)
+ {
+ LoadFullEntryL();
+ iFullEntry->SetBusyStatusL(aBusyStatus);
+ }
+
+CCalGeoValue* CCalEntryImpl::GeoValueL()
+ {
+ LoadFullEntryL();
+ TReal geoLatitude;
+ TReal geoLongitude;
+ iFullEntry->GeoValue(geoLatitude,geoLongitude);
+ if(geoLatitude != KGEODefaultValue && geoLongitude != KGEODefaultValue)
+ {
+ CCalGeoValue* geoValue = CCalGeoValue::NewL();
+ CleanupStack::PushL(geoValue);
+ geoValue->SetLatLongL(geoLatitude,geoLongitude);
+ CleanupStack::Pop(geoValue);
+ return geoValue;
+ }
+ return NULL;
+ }
+
+void CCalEntryImpl::SetGeoValueL(const CCalGeoValue& aGeoValue)
+ {
+ LoadFullEntryL();
+ TReal geoLatitude;
+ TReal geoLongitude;
+ aGeoValue.GetLatLong(geoLatitude,geoLongitude);
+ iFullEntry->SetGeoValueL(geoLatitude,geoLongitude);
+ }
+
+void CCalEntryImpl::ClearGeoValueL()
+ {
+ LoadFullEntryL();
+ iFullEntry->SetGeoValueL(KGEODefaultValue,KGEODefaultValue);
+ }
+
+TCalTime CCalEntryImpl::FindRptUntilTimeL(TInt aCount)
+ {
+ const CAgnRptDef* KRptDef = SimpleEntry()->RptDef();
+
+ TTime untilTime = Time::NullTTime();
+
+ if (KRptDef)
+ {
+ untilTime = KRptDef->RRule()->FindRptUntilTimeLocalL(aCount);
+ }
+
+ TCalTime calUntilTime;
+ calUntilTime.SetTimeLocalL(untilTime);
+
+ return calUntilTime;
+ }
+
+
+ void CCalEntryImpl::AddAttachmentL(CCalAttachment* aAttachment)
+ {
+ __ASSERT_ALWAYS(aAttachment, User::Leave(KErrArgument));
+
+ PopulateAttachmentListL();
+ iCalAttachmentList->AppendL(aAttachment);
+
+ TRAPD(err , iFullEntry->AddAttachmentL(&aAttachment->Impl()));
+
+ if (err != KErrNone)
+ {
+ TInt count = iCalAttachmentList->Count();
+ iCalAttachmentList->Remove(count - 1);
+ User::Leave(err);
+ }
+
+ aAttachment->Impl().ClearFlag(CAgnAttachment::EOwnedByCalAttachment);
+
+ }
+
+void CCalEntryImpl::PopulateAttachmentListL()
+ {
+ if (!iCalAttachmentList)
+ {
+
+ LoadFullEntryL();
+ iCalAttachmentList = new (ELeave) RPointerArray<CCalAttachment>(KAttachmentGranularity);
+
+ const TInt KAttachmentCount = iFullEntry->AttachmentCount();
+ for (TInt i = 0; i < KAttachmentCount; ++i)
+ {
+ CAgnAttachment& agnAttachment = iFullEntry->Attachment(i);
+ CCalAttachment* calAttachment = CCalAttachment::NewL(agnAttachment, *iSessionImpl);
+ CleanupStack::PushL(calAttachment);
+ agnAttachment.ClearFlag(CAgnAttachment::EOwnedByCalAttachment);
+ iCalAttachmentList->AppendL(calAttachment);
+ CleanupStack::Pop(calAttachment);
+ }
+ }
+
+ }
+
+void CCalEntryImpl::DeleteAttachmentL(const CCalAttachment& aAttachment)
+ {
+ LoadFullEntryL();
+ TInt index = iFullEntry->DeleteAttachmentL(aAttachment.Impl());
+ if(iCalAttachmentList && index >= 0 && index < iCalAttachmentList->Count())
+ {
+ delete (*iCalAttachmentList)[index];
+ iCalAttachmentList->Remove(index);
+ __ASSERT_DEBUG(iCalAttachmentList->Count() == iFullEntry->AttachmentCount(), Panic(EAgmErrAttachmentCountCorrupt));
+ }
+ }
+
+CCalAttachment* CCalEntryImpl::AttachmentL(TInt aIndex)
+ {
+ PopulateAttachmentListL();
+
+ if (aIndex < 0 || aIndex >= iCalAttachmentList->Count() )
+ {
+ return NULL;
+ }
+
+ return (*iCalAttachmentList)[aIndex];
+ }
+
+TInt CCalEntryImpl::AttachmentCountL()
+ {
+ LoadFullEntryL();
+ return iFullEntry->AttachmentCount();
+ }
+
+CAgnSimpleEntry* CCalEntryImpl::SimpleEntry()
+ {
+ if (!iFullEntry)
+ {
+ return &iLiteEntry->LiteEntry();
+ }
+ return iFullEntry;
+ }
+
+const CAgnSimpleEntry* CCalEntryImpl::SimpleEntry() const
+ {
+ if (!iFullEntry)
+ {
+ return &iLiteEntry->LiteEntry();
+ }
+ return iFullEntry;
+ }
+
+void CCalEntryImpl::SetUserIntL( TUint32 aUserInt )
+ {
+ SimpleEntry()->SetUserInt(aUserInt);
+ }
+
+TUint32 CCalEntryImpl::UserIntL()
+ {
+ return SimpleEntry()->UserInt();
+ }
+
+
+// CCalEntryIdImpl //
+
+CCalEntryIdImpl* CCalEntryIdImpl::NewL(TDesC8* aFlatData)
+ {
+ CCalEntryIdImpl* self = new(ELeave) CCalEntryIdImpl();
+ CleanupStack::PushL(self);
+ self->ConstructL(aFlatData);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CCalEntryIdImpl::CCalEntryIdImpl()
+ {
+ }
+
+CCalEntryIdImpl::~CCalEntryIdImpl()
+ {
+ delete iFlatData;
+ }
+
+void CCalEntryIdImpl::ConstructL(TDesC8* aFlatData)
+ {
+ __ASSERT_ALWAYS(aFlatData != NULL, User::Leave(KErrArgument));
+
+ iFlatData = aFlatData;
+ iUniqueId = reinterpret_cast<const TAgnAlarmInfo*>(aFlatData->Ptr());
+ }
+
+TPtrC8 CCalEntryIdImpl::IdL()
+ {
+ return iUniqueId->iGlobalIdentifier;
+ }
+
+TPtrC CCalEntryIdImpl::StoreFileNameL()
+ {
+ return iUniqueId->iFileName;
+ }
+
+TCalTime CCalEntryIdImpl::RecurrenceIdL()
+ {
+ TCalTime time;
+
+ if(iUniqueId->iTimeMode ==MAgnCalendarTimeMode::EFloating)
+ {
+ time.SetTimeLocalFloatingL(iUniqueId->iRecurrenceId);
+ }
+ else
+ {
+ time.SetTimeUtcL(iUniqueId->iRecurrenceId);
+ }
+
+ return time;
+ }
+
+TCalTime CCalEntryIdImpl::InstanceTimeL()
+ {
+ TCalTime time;
+
+ if(iUniqueId->iTimeMode == MAgnCalendarTimeMode::EFloating)
+ {
+ time.SetTimeLocalL(iUniqueId->iInstanceTime);
+ }
+ else
+ {
+ time.SetTimeUtcL(iUniqueId->iInstanceTime);
+ }
+
+ return time;
+ }
+
+TCalLocalUid CCalEntryIdImpl::LocalUidL()
+ {
+ return iUniqueId->iAgnUniqueId;
+ }
+
+
+/** Construct a new CCalLiteEntry
+
+@param aLiteEntry The TAgnLiteEntry to be shared between CCalEntry objects.
+@param aSession A reference to the CCalSession
+@internalComponent
+*/
+CCalLiteEntry* CCalLiteEntry::NewL(CAgnSimpleEntry& aSimpleEntry, RAgendaServ& aAgendaServ)
+ {
+ CCalLiteEntry* self = new(ELeave) CCalLiteEntry(aSimpleEntry, aAgendaServ);
+ return self;
+ }
+
+/** Constructor
+
+@param aLiteEntry The TAgnLiteEntry to be shared between CCalEntry objects.
+@param aSession A reference to the CCalSession
+@internalComponent
+*/
+CCalLiteEntry::CCalLiteEntry(CAgnSimpleEntry& aLiteEntry, RAgendaServ& aAgendaServ)
+ : iAgendaServ(aAgendaServ), iLiteEntry(aLiteEntry)
+ {
+ iAgendaServ.IncreaseRef();
+ }
+
+/** Deletes the TAgnLiteEntry that is contained
+
+@internalComponent
+*/
+CCalLiteEntry::~CCalLiteEntry()
+ {
+ iAgendaServ.DeleteSimpleEntry(&iLiteEntry);
+ iAgendaServ.DecreaseRef();
+ }
+
+/** Get a reference to the TAgnLiteEntry
+
+@return A reference to the TAgnLiteEntry
+@internalComponent
+*/
+CAgnSimpleEntry& CCalLiteEntry::LiteEntry() const
+ {
+ return iLiteEntry;
+ }
+
+/** Increments the reference count
+
+This should only be called by a CCalEntry object that is being created from a CCalLiteEntry
+@internalComponent
+*/
+void CCalLiteEntry::IncrementRefCount()
+ {
+ ++iRefCount;
+ }
+
+/** Decrements the reference count and deletes this CCalLiteEntry if there are no more entries refering to it
+
+This should only be called by a CCalEntry object
+@internalComponent
+*/
+void CCalLiteEntry::DecrementRefCount()
+ {
+ __ASSERT_ALWAYS(iRefCount > 0, User::Invariant());
+ if (--iRefCount == 0)
+ {
+ delete this;
+ }
+ }