diff -r 000000000000 -r f979ecb2b13e pimappservices/calendar/shared/src/agmentry.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappservices/calendar/shared/src/agmentry.cpp Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,2088 @@ +// Copyright (c) 1997-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 "agmentry.h" + +#include "agmattendee.h" +#include "agmcategory.h" +#include +#include "agmcontent.h" +#include "agmattachment.h" +#include "agmdate.h" +#include "agmrptdef.h" +#include "agmutil.h" + +#include +//#include "calentryimpl.h" +#include + +#include + + +//---------------------------------- CAgnEntry ------------------------------------------ + +EXPORT_C CAgnEntry* CAgnEntry::NewL(CCalEntry::TType aType) + { + __ASSERT_ALWAYS(aType>=CCalEntry::EAppt && aType<=CCalEntry::EAnniv, Panic(EAgmErrBadTypeEntry)); + // allocate a CAgnEntry object, which invokes the CAgnSimpleEntry new operator, but passing no allocator + // this makes the CAgnSimpleEntry new operator use the default new operator + + return new (ELeave, NULL) CAgnEntry(aType);; + } + +EXPORT_C CAgnEntry* CAgnEntry::NewL(RReadStream& aStream) +//Creates an entry and restores it from aStream + { + // type must be read first because NewL requires it + TUint8 typeData = aStream.ReadUint8L(); + + CCalEntry::TType type=CCalEntry::TType(typeData); + + __ASSERT_ALWAYS(type==CCalEntry::EAppt || type==CCalEntry::EEvent || + type==CCalEntry::EAnniv || type==CCalEntry::ETodo || + type==CCalEntry::EReminder, User::Leave(KErrCorrupt)); + + CAgnEntry* entry = CAgnEntry::NewL(type); + CleanupStack::PushL(entry); + entry->InternalizeL(aStream); + CleanupStack::Pop(); + return entry; + } + + +CAgnEntry::CAgnEntry(CCalEntry::TType aType) : CAgnSimpleEntry(aType) + { + iSummary = NULL; + iSummaryStreamId = KNullStreamId; + iDescription = NULL; + iDescriptionStreamId = KNullStreamId; + SetFlagOff(EAgnAlarmActionDeleted); + iDTStampUtc = Time::NullTTime(); + iLatitude=KGEODefaultValue; + iLongitude=KGEODefaultValue; + } + +void CAgnEntry::ConstructL(HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum) + { + iGsData = CGsParentData::NewL(aUid, aSeqNum, aMethod); // takes ownership of aUid + } + +void CAgnEntry::ConstructL(HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum, const TAgnCalendarTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange) + { + iGsData = CGsChildData::NewL(aUid, aSeqNum, aMethod, aRecurrenceId, aRange); // takes ownership of aUid + } + +EXPORT_C CAgnEntry* CAgnEntry::NewL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum, const TAgnCalendarTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange) + { + CAgnEntry* entry = new (ELeave, NULL) CAgnEntry(aType); + + CleanupStack::PushL(entry); + entry->ConstructL(aUid, aMethod, aSeqNum, aRecurrenceId, aRange); + CleanupStack::Pop(entry); + + return entry; + } + +EXPORT_C CAgnEntry* CAgnEntry::NewL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum) + { + CAgnEntry* entry = new (ELeave, NULL) CAgnEntry(aType); + + CleanupStack::PushL(entry); + entry->ConstructL(aUid, aMethod, aSeqNum); + CleanupStack::Pop(entry); + + return entry; + } + +EXPORT_C CAgnEntry::~CAgnEntry() +/** The destructor frees all resources owned by the entry, prior to its destruction. +@internalComponent +*/ + { + if ( iAttendeeList ) + { + iAttendeeList->ResetAndDestroy(); + delete iAttendeeList; + } + delete iMeetingOrganizer; + + delete iLocation; + + if ( iCategoryList ) + { + iCategoryList->ResetAndDestroy(); + delete iCategoryList; + } + + if (iAttachments) + { + iAttachments->ResetAndDestroy(); + delete iAttachments; + } + + delete iDescription; + delete iSummary; + delete iAlarmSoundName; + delete iAlarmAction; + + delete iGsData; + } + + +EXPORT_C const TDesC& CAgnEntry::Summary() const +/** Gets a pointer to the rich text object owned by the entry. + +@internalComponent +@return Pointer to the rich text object. The caller does not take ownership. */ + { + if ( iSummary ) + { + return *iSummary; + } + + return KNullDesC; + } + + +EXPORT_C TBool CAgnEntry::CompareL(const CAgnEntry& aEntry) const +/** Compares another entry for equality with this one. + +The entries' instance IDs and unique IDs are also compared. + +@internalComponent +@param aEntry Pointer to an entry. +@param aCompareId This argument is used internally, for test purposes only. +As it has a default value, it can be ignored by developers. +@return ETrue if aEntry is the same as this entry, EFalse if not. Note. Replication +data is not included in the comparison, except for the replication status. +*/ + { + if ( ! (*this == aEntry) ) + { + return EFalse; + } + + if ( ReplicationStatus() != aEntry.ReplicationStatus() ) + { + return EFalse; + } + + if ( HasAlarm() ) + { + if ( AlarmSoundName() != aEntry.AlarmSoundName() ) + { + return EFalse; + } + + CAgnContent* content1 = AlarmAction(); + CAgnContent* content2 = aEntry.AlarmAction(); + if ( content1 == NULL ) + { + if ( content2 != NULL ) + { + return EFalse; + } + } + else + { + if ( content2 == NULL ) + { + return EFalse; + } + + if ( content1->Type() != content2->Type() ) + { + return EFalse; + } + + if ( content1->Content() != content2->Content() ) + { + return EFalse; + } + + if ( content1->MimeType() != content2->MimeType() ) + { + return EFalse; + } + } + } + + if ( BusyStatus() != aEntry.BusyStatus() ) + { + return EFalse; + } + + // Compare GEO values + TReal entryLatitude; + TReal entryLongitude; + + aEntry.GeoValue(entryLatitude,entryLongitude); + + if ( iLatitude != entryLatitude || entryLongitude != iLongitude ) + { + return EFalse; + } + + // Compare the user integer. + if (UserInt() != aEntry.UserInt()) + { + return EFalse; + } + + if ( DTStampUtcL() != aEntry.DTStampUtcL() ) + { + return EFalse; + } + + if ( Method() != aEntry.Method() ) + { + return EFalse; + } + + if ( SequenceNumber() != aEntry.SequenceNumber() ) + { + return EFalse; + } + + if ( RecurrenceId() != aEntry.RecurrenceId() ) + { + return EFalse; + } + + const TInt KNumOfCategories = CategoryCount(); + + if ( aEntry.CategoryCount() != KNumOfCategories ) + { + return EFalse; + } + + const RPointerArray* categoryList1 = iCategoryList; + const RPointerArray* categoryList2 = aEntry.iCategoryList; + + if (categoryList1 && categoryList2) + { + TBool categoryFound = EFalse; + + for ( TInt i = 0 ; i < KNumOfCategories; ++i ) + { + categoryFound = EFalse; + + for ( TInt j = 0; ! categoryFound && j < KNumOfCategories; ++j ) + { + if ( (*categoryList1)[i]->Category() == (*categoryList2)[j]->Category() ) + { + if ( (*categoryList1)[i]->Category() == CCalCategory::ECalExtended ) + { + if ( (*categoryList1)[i]->ExtendedCategoryName() == (*categoryList2)[j]->ExtendedCategoryName() ) + { + categoryFound = ETrue; + } + } + else + { + categoryFound = ETrue; + } + } + } + + if ( !categoryFound ) + { + return EFalse; + } + } + } + + const TInt KNumOfAttendees = AttendeeCount(); + + if ( KNumOfAttendees != aEntry.AttendeeCount() ) + { + return EFalse; + } + + if ( KNumOfAttendees > 0 && KNumOfAttendees == aEntry.AttendeeCount() ) + { + const RPointerArray& KAttendeeList1 = *iAttendeeList; + const RPointerArray& KAttendeeList2 = *aEntry.iAttendeeList; + + for ( TInt i = 0; i < KNumOfAttendees; ++i ) + { + const TPtrC& KAttendee1 = KAttendeeList1[i]->Address(); + + TBool attendeeFound = EFalse; + + for ( TInt j = 0; !attendeeFound && j < KNumOfAttendees; ++j ) + { + const TPtrC& KAttendee2 = KAttendeeList2[j]->Address(); + + if ( KAttendee1.CompareF(KAttendee2) == 0 ) + { + attendeeFound = ETrue; + } + } + + if ( !attendeeFound ) + { + return EFalse; + } + } + } + + const TInt KNumAttachments = AttachmentCount(); + if (KNumAttachments != aEntry.AttachmentCount()) + { + return EFalse; + } + if (KNumAttachments > 0) + { + RArray foundAttachmentAlready; + CleanupClosePushL(foundAttachmentAlready); + + for (TInt i = 0; i < KNumAttachments; ++i) + { + foundAttachmentAlready.AppendL(EFalse); + } + + for (TInt i = 0; i < KNumAttachments; ++i) + { + TBool attachmentFound = EFalse; + for (TInt j = 0; j < KNumAttachments; ++j) + { + if (!foundAttachmentAlready[j] && Attachment(i).CompareL(aEntry.Attachment(j))) + { + foundAttachmentAlready[j] = ETrue; + attachmentFound = ETrue; + break; + } + } + if (!attachmentFound) + { + CleanupStack::PopAndDestroy(); // foundAttachmentAlready.Close() + return EFalse; + } + } + + CleanupStack::PopAndDestroy(); // foundAttachmentAlready.Close() + } + + if ( PhoneOwner() == NULL ) + { + if ( aEntry.PhoneOwner() != NULL ) + { + return EFalse; + } + } + else + { + // PhoneOwner() != NULL + if ( aEntry.PhoneOwner() == NULL ) + { + return EFalse; + } + else if ( PhoneOwner()->Address() != aEntry.PhoneOwner()->Address() ) + { + return EFalse; + } + } + + if ( Summary() != aEntry.Summary() ) + { + return EFalse; + } + + if ( Description() != aEntry.Description() ) + { + return EFalse; + } + + if ( Location() != aEntry.Location() ) + { + return EFalse; + } + + return ETrue; + } + + +EXPORT_C const TDesC& CAgnEntry::AlarmSoundName() const +/** Gets the name of the alarm sound as set by SetAlarmSoundName(). + +Returns NULL if the entry isn't alarmed. + +@internalComponent +@return The name of the alarm sound. +*/ + { + + if ( HasAlarm() && iAlarmSoundName ) + { + return *iAlarmSoundName; + } + + return KNullDesC(); + } + + +EXPORT_C void CAgnEntry::SetAlarmSoundNameL(const TDesC& aAlarmSoundName) +/** Sets the name of the alarm sound. + +Note: if the length of the new alarm sound name is greater than KMaxAlarmSoundName +characters, it will be ignored. + +@internalComponent +@param aAlarmSoundName The name of the alarm sound. +*/ + { + const TInt KLen = aAlarmSoundName.Length(); + + if ( KLen > 0 && KLen <= KMaxAlarmSoundNameLength ) + { + // delete and set always to NULL before AllocL because + // that call could leave and the pointer be not NULL + + delete iAlarmSoundName; + iAlarmSoundName = NULL; + + iAlarmSoundName = aAlarmSoundName.AllocL(); + } + } + + +EXPORT_C void CAgnEntry::ClearAlarm() +/** Clear associated alarm + +@internalComponent +*/ + { + delete iAlarmSoundName; + iAlarmSoundName = NULL; + + if ( iAlarmActionStreamId != KNullStreamId) + { + SetFlagOn(EAgnAlarmActionDeleted); + } + + delete iAlarmAction; + iAlarmAction = NULL; + + SetAlarmOffset(KAlarmNotSet); + } + + void CAgnEntry::ExternalizeGsDataL(RWriteStream& aStream, TBool aToBuffer) const + { + aStream.WriteInt8L(GsDataType()); + + if(aToBuffer) + { + iGsData->ExternalizeToBufferL(aStream); + } + else + { + iGsData->ExternalizeL(aStream); + } + } + +EXPORT_C void CAgnEntry::PruneRDatesL(const TAgnCalendarTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange) +/** +Used when adding a repeating child to a parent entry. +Removes all sporadic dates either after or before the specified recurrence ID. +@internalComponent +*/ + { + __ASSERT_DEBUG(iGsData->GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry)); + __ASSERT_DEBUG(RptDef(), Panic(EAgmErrNotParentEntry)); + __ASSERT_DEBUG(aRange == CalCommon::EThisAndFuture || aRange == CalCommon::EThisAndPrior, Panic(EAgmErrInvalidRecurrenceRange)); + + if (RptDef()->HasSporadicDates()) + { + const RArray* KSporadicDates = RptDef()->SporadicDateList(); + + for (TInt i = KSporadicDates->Count() - 1; i >= 0; --i) + { + const TAgnCalendarTime& KSporadicDate = (*KSporadicDates)[i]; + if ( (aRecurrenceId > KSporadicDate && aRange == CalCommon::EThisAndPrior ) || + (aRecurrenceId < KSporadicDate && aRange == CalCommon::EThisAndFuture ) ) + { + RptDef()->RemoveSporadicDate(KSporadicDate); + } + } + } + } + +void CAgnEntry::InternalizeGsDataL(RReadStream& aStream, TBool aFromBuffer) + { + CGsData::TGsDataType dataType = static_cast(aStream.ReadInt8L()); + + if(dataType == CGsData::EParent) + { + iGsData = CGsParentData::NewL(); + } + else + { + iGsData = CGsChildData::NewL(); + } + + if(aFromBuffer) + { + iGsData->InternalizeFromBufferL(aStream); + } + else + { + iGsData->InternalizeL(aStream); + } + } + +EXPORT_C void CAgnEntry::ExternalizeL(RWriteStream& aStream) const +/** Externalises an entry's details and attributes, but not its rich text to a +write stream. + +The presence of this function means that the standard templated operator<<() +(defined in s32strm.h) is available to externalise objects of this class. + +@internalComponent +@param aStream Stream to which the object should be externalised. +*/ + { + ExternalizeEntryL(aStream); + ExternalizeGsDataL(aStream, EFalse); + } + +void CAgnEntry::ExternalizeEntryL(RWriteStream& aStream, TBool aToBuffer) const + { + CAgnSimpleEntry::doExternalizeL(aStream, aToBuffer); + aStream.WriteInt8L(iReplicationStatus); + + if ( HasAlarm() ) + { + if (iAlarmSoundName) + { + aStream << *iAlarmSoundName; + } + else + { + aStream << KNullDesC(); + } + } + + // Make sure there is no server pointer + // - This may have been set up from a previous FetchEntry + __ASSERT_DEBUG(iSummaryStreamId == KNullStreamId || + !(iSummary && iSummary->Length() > 0 && iSummaryStreamId == KNullStreamId), + Panic(EAgmNoNotesStreamId)); + + aStream << iSummaryStreamId; + + TInt size = 0; + if ( iLocation ) + { + size = iLocation->Length(); + aStream.WriteUint32L(size); + aStream.WriteL(iLocation->Des(), size); + } + else + { + size = 0; + aStream.WriteUint32L(size); + } + + TInt phoneOwnerIndex = 0; + + if ( iAttendeeList ) + { + size = iAttendeeList->Count(); + aStream.WriteUint32L(size); + + for ( TInt i = 0; i < size; ++i ) + { + CAgnAttendee*& attendeeI = (*iAttendeeList)[i]; + + attendeeI->ExternalizeL(aStream); + + if ( iPhoneOwner == attendeeI ) + { + phoneOwnerIndex = i + 1; + } + } + } + else + { + size = 0; + aStream.WriteUint32L(size); + } + + // phone owner index. 0 implies no phoneowner + aStream.WriteUint32L(phoneOwnerIndex); + + // meeting organizer if present + if (iMeetingOrganizer) + { + aStream.WriteUint8L(ETrue); + iMeetingOrganizer->ExternalizeL(aStream); + } + else + { + aStream.WriteUint8L(EFalse); + } + + // Write the creation date field + + aStream << iDTStampUtc.Int64(); + + // this does not change the file format + if ( iCategoryList ) + { + size = iCategoryList->Count(); + aStream.WriteUint32L(size); + + for ( TInt ccount = 0; ccount < size; ++ccount ) + { + (*iCategoryList)[ccount]->ExternalizeL(aStream); + } + } + else + { + size = 0; + aStream.WriteUint32L(size); + } + + // Write the Notes Stream Id - Null value indicates no Notes data. + // If the Notes exist, they should have been saved previously, so Stream id != 0 !!! + __ASSERT_DEBUG((iDescriptionStreamId == KNullStreamId) || + !(iDescription && iDescription->Length() > 0 && iDescriptionStreamId == KNullStreamId), + Panic(EAgmNoNotesStreamId)); + aStream << iDescriptionStreamId; + aStream << iAlarmActionStreamId; + + aStream.WriteUint8L(iBusyStatus); + + // GEO properties + aStream.WriteReal64L(iLatitude); + aStream.WriteReal64L(iLongitude); + + const TInt KAttachmentCount = AttachmentCount(); + aStream.WriteUint16L(KAttachmentCount); + for (TInt i = 0; i < KAttachmentCount; ++i) + { + if ( ! Attachment(i).FlagsSet(CAgnAttachment::EDataHasBeenSet)) + { + // attachments with just content IDs should not be stored + User::Leave(KErrArgument); + } + else + { + aStream << Attachment(i); + } + } + + // Set the user integer of the stream. + aStream.WriteInt32L( UserInt() ); + + // future DC proofing + aStream.WriteUint32L(0); // number of bytes until end of entry + } + + +EXPORT_C void CAgnEntry::InternalizeL(RReadStream& aStream) + { + InternalizeEntryL(aStream, EFalse); + InternalizeGsDataL(aStream, EFalse); + } + +void CAgnEntry::InternalizeEntryL(RReadStream& aStream, TBool aFromBuffer) +/** Internalises an entry's details and attributes, but not its rich text from +a read stream. + +The presence of this function means that the standard templated operator>>() +(defined in s32strm.h) is available to internalise objects of this class. + +@internalComponent +@param aStream Stream from which the object should be internalised. +*/ + { + CAgnSimpleEntry::doInternalizeL(aStream, aFromBuffer); + iReplicationStatus = static_cast(aStream.ReadInt8L()); + + delete iAlarmSoundName; + iAlarmSoundName = NULL; + + if ( HasAlarm() ) + { + iAlarmSoundName = HBufC::NewL(aStream, KMaxAlarmSoundNameLength); + if ( iAlarmSoundName->Length() == 0 ) + { + delete iAlarmSoundName; + iAlarmSoundName = NULL; + } + } + + aStream >> iSummaryStreamId; + + // Delete any location that may exist + delete iLocation; + iLocation = NULL; + + TInt size = aStream.ReadUint32L(); + if ( size ) + { + iLocation = HBufC::NewL(size); + TPtr bufPtr = iLocation->Des(); + aStream.ReadL(bufPtr, size); + } + + size = aStream.ReadUint32L(); + if ( iAttendeeList ) + { + iAttendeeList->ResetAndDestroy(); + } + else + { + if ( size ) + { + CreateAttendeeListL(); + } + } + iPhoneOwner = NULL; + iMeetingOrganizer = NULL; + + for ( TInt count = 0; count < size; ++count ) + { + CAgnAttendee* attendee = CAgnAttendee::NewL(aStream); + CleanupStack::PushL(attendee); + iAttendeeList->AppendL(attendee); + CleanupStack::Pop(attendee); + } + + // populate the phoneowner/organizer fields if existing + TInt phoneOwnerIndex = aStream.ReadUint32L(); + if (phoneOwnerIndex > 0) + { + iPhoneOwner = (*iAttendeeList)[phoneOwnerIndex-1]; + } + + // meeting organizer if present + if (aStream.ReadUint8L()) + { + iMeetingOrganizer = CAgnAttendee::NewL(aStream); + } + + TInt64 dtStamp; + aStream >> dtStamp; + iDTStampUtc = dtStamp; + + size = aStream.ReadUint32L(); + + if ( iCategoryList ) + { + iCategoryList->ResetAndDestroy(); + } + else + { + if ( size ) + { + iCategoryList = new (ELeave) RPointerArray; + } + } + + for ( TInt ccount = 0; ccount < size; ++ccount ) + { + CAgnCategory* category = CAgnCategory::NewL(aStream); + CleanupStack::PushL(category); + iCategoryList->AppendL(category); + CleanupStack::Pop(category); + } + + // If it's the new file format read in the Stream Id for the notes text + aStream >> iDescriptionStreamId; + + aStream >> iAlarmActionStreamId; + + iBusyStatus = static_cast(aStream.ReadUint8L()); + + // GEO properties + TReal geoLatitude = aStream.ReadReal64L(); + TReal geoLongitude = aStream.ReadReal64L(); + + SetGeoValueL(geoLatitude, geoLongitude); + + TInt attachmentCount = aStream.ReadUint16L(); + for (TInt i = 0; i < attachmentCount; ++i) + { + + CAgnAttachment* attachment = AttachmentFactory::NewAttachmentL(aStream); + CleanupStack::PushL(attachment); + AddAttachmentL(attachment); + CleanupStack::Pop(attachment); + } + + // Set the user integer of this entry from the stream. + SetUserInt(aStream.ReadInt32L()); + + // future DC proofing + size = aStream.ReadUint32L(); // number of bytes until end of entry + while (size > 0) + { + aStream.ReadUint8L(); // ignore data + size--; + } + } + +EXPORT_C CAgnEntry* CAgnEntry::CloneL() const + { + CAgnEntry* entry = NULL; + HBufC8* guid = (this->Guid()).AllocLC(); + if(this->GsDataType() == CGsData::EParent) + { + entry = CAgnEntry::NewL(this->Type(), guid, this->Method(), this->SequenceNumber()); + } + else + { + entry = CAgnEntry::NewL(this->Type(), guid, this->Method(), this->SequenceNumber(), this->RecurrenceId(), this->RecurrenceRange()); + } + CleanupStack::Pop(guid); + CleanupStack::PushL(entry); + entry->CopyFromL(*this, CCalEntry::ECopyAll); + CleanupStack::Pop(entry); + return entry; + } + +EXPORT_C void CAgnEntry::CopyFromL(const CAgnEntry& aSource, CCalEntry::TCopyType aCopyType) +/** Copy the details common to all entry types from aSource. +If aCopyType is EShallowCopy it indicates that if aSources rich text is stored out of line and its +not loaded then it isn't loaded and copied +*/ + { + CopySimpleEntryL(aSource, aCopyType); + + // NOTE: don't use the internal set methods with pointers because doing a CopyFrom + // we are supposed to carbon copy the original. If the original has a NULL + // pointer in a member, we have to do the same and not keep any old stuff + iReplicationStatus = aSource.iReplicationStatus; + + if( iAttendeeList ) + { + iAttendeeList->ResetAndDestroy(); + } + iPhoneOwner = NULL; + delete iMeetingOrganizer; + iMeetingOrganizer = NULL; + + const TInt KAttendees = aSource.AttendeeCount(); + for ( TInt count = 0; count < KAttendees; ++count ) + { + CAgnAttendee& attendee = aSource.FetchAttendee(count); + + CAgnAttendee* newAttendee = attendee.CloneL(); + AddAttendeeL(newAttendee); + + if ( aSource.PhoneOwner() == &attendee ) + { + SetPhoneOwnerL(newAttendee); + } + } + + if (aSource.Organizer()) + { + iMeetingOrganizer = aSource.Organizer()->CloneL(); + } + + // Copy the Location + delete iLocation; + iLocation = NULL; + + if ( aSource.iLocation ) + { + iLocation = aSource.iLocation->AllocL(); + } + + iDTStampUtc = aSource.iDTStampUtc; + + if( iCategoryList ) + { + iCategoryList->ResetAndDestroy(); + } + + const TInt KCategories = aSource.CategoryCount(); + for ( TInt ccount = 0; ccount < KCategories; ++ccount ) + { + CAgnCategory& category = aSource.FetchCategory(ccount); + + CAgnCategory* newCategory = CAgnCategory::NewL(category); + CleanupStack::PushL(newCategory); + AddCategoryL(newCategory); + CleanupStack::Pop(newCategory); + } + + iBusyStatus = aSource.BusyStatus(); + + // GEO properties + TReal sourceLatitude; + TReal sourceLongitude; + aSource.GeoValue(sourceLatitude,sourceLongitude); + + iLatitude = sourceLatitude; + iLongitude = sourceLongitude; + + // Copy the Notes buffer + + delete iDescription; + iDescription = NULL; + + if ( aSource.iDescription ) + { + iDescription = aSource.iDescription->AllocL(); + } + + iDescriptionStreamId = aSource.iDescriptionStreamId; + + + // Copy the Summary buffer + + delete iSummary; + iSummary = NULL; + + if ( aSource.iSummary ) + { + iSummary = aSource.iSummary->AllocL(); + } + + iSummaryStreamId = aSource.iSummaryStreamId; + + + // Copy the Alarm sound name + + delete iAlarmSoundName; + iAlarmSoundName = NULL; + + if ( aSource.iAlarmSoundName ) + { + iAlarmSoundName = aSource.iAlarmSoundName->AllocL(); + } + + + // Copy the Alarm action + + delete iAlarmAction; + iAlarmAction = NULL; + + if ( aSource.iAlarmAction ) + { + iAlarmAction = aSource.iAlarmAction->CloneL(); + } + + iAlarmActionStreamId = aSource.iAlarmActionStreamId; + iFlags = aSource.iFlags; + + if ( iAttachments ) + { + iAttachments->ResetAndDestroy(); + delete iAttachments; + iAttachments = NULL; + } + + const TInt KAttachments = aSource.AttachmentCount(); + for ( TInt i = 0; i < KAttachments; ++i ) + { + CAgnAttachment& attachment = aSource.Attachment(i); + CAgnAttachment* attachmentCopy = AttachmentFactory::CloneL(attachment); + CleanupStack::PushL(attachmentCopy); + AddAttachmentL(attachmentCopy); + CleanupStack::Pop(attachmentCopy); + } + + iGsData->CopyDataL(*aSource.iGsData); + + if(aCopyType == CCalEntry::ECopyAll) + { + HBufC8* guid = aSource.Guid().AllocL(); + SetGuid(guid); + } + } + +EXPORT_C CCalEntry::TReplicationStatus CAgnEntry::ReplicationStatus() const +/** Get ReplicationStatus + +@internalComponent +*/ + { + return static_cast(iReplicationStatus); + } + + +EXPORT_C void CAgnEntry::SetReplicationStatusL(CCalEntry::TReplicationStatus aReplicationStatus) +/** Set ReplicationStatus + +@internalComponent +@leave KErrArgument if passed parameter exceeds boundaries +*/ + { + if( aReplicationStatus < CCalEntry::EOpen || aReplicationStatus > CCalEntry::ERestricted ) + { + User::Leave(KErrArgument); + } + + iReplicationStatus = aReplicationStatus; + } + + +EXPORT_C TBool CAgnEntry::SummaryIsLoaded() const +/** Check if summary text is loaded from stream + +@internalComponent +*/ + { + if ( ! iSummary && iSummaryStreamId != KNullStreamId ) + { + return EFalse; + } + + return ETrue; + } + + +EXPORT_C void CAgnEntry::SetSummary(HBufC* aSummary) +/** Set summary + +@internalComponent +*/ + { + delete iSummary; + iSummary = aSummary; + } + + +EXPORT_C void CAgnEntry::SetLocationL(const TDesC& aLocation) +/** Sets the contents of the entry's location field. + +Sets the entry's 'has extended' property. + +@internalComponent +@param aLocation Descriptor containing a location, e.g. for a meeting. +*/ + { + delete iLocation; + iLocation = NULL; + iLocation = aLocation.AllocL(); + } + + +EXPORT_C const TDesC& CAgnEntry::Location() const +/** Gets the contents of the entry's location field. + +@internalComponent +@return The location field. NULL if the entry has no location field. +*/ + { + if ( iLocation ) + { + return *iLocation; + } + + return KNullDesC(); + } + + +EXPORT_C TInt CAgnEntry::AttendeeCount() const +/** Gets the number of attendees that have been added to the entry. + +@internalComponent +@return Number of attendees added. +*/ + { + if ( ! iAttendeeList ) + { + return 0; + } + + return iAttendeeList->Count(); + } + +EXPORT_C CAgnAttendee& CAgnEntry::FetchAttendee(TInt aIndex) const +/** Gets the attendee at the specified index within the entry's list of +attendees. + +The index specified must be valid (between zero and AttendeeCount() +- 1), otherwise a panic occurs. + +@internalComponent +@param aIndex Index to identify the specified attendee. +@return The attendee details. */ + { + return *(*iAttendeeList)[aIndex]; + } + + +EXPORT_C void CAgnEntry::AddAttendeeL(CAgnAttendee* aAttendee) +/** Appends an attendee to the entry's list of attendees. + +@internalComponent +@param aAttendee Pointer to the attendee details. +*/ + { + CleanupStack::PushL(aAttendee); + CreateAttendeeListL(); + + // Add an attendee for this entry + iAttendeeList->AppendL(aAttendee); + CleanupStack::Pop(aAttendee); + } + +void CAgnEntry::CreateAttendeeListL() + { + if ( !iAttendeeList ) + { + iAttendeeList = new (ELeave) RPointerArray; + } + } + +EXPORT_C void CAgnEntry::SetOrganizerL(CAgnAttendee* aAttendee) +/** Set attendee as organiser + +@internalComponent +*/ + { + if (iMeetingOrganizer == iPhoneOwner) + { + iPhoneOwner = NULL; + } + delete iMeetingOrganizer; + iMeetingOrganizer = aAttendee; + } + +EXPORT_C CAgnAttendee* CAgnEntry::Organizer() const +/** Get Organizer as attendee object + +@internalComponent +*/ + { + return iMeetingOrganizer; + } + +EXPORT_C void CAgnEntry::DeleteAttendee(TInt aIndex) +/** Deletes the attendee at the index specified from the entry's list of attendees. + +If there is no attendee at the index specified, a panic occurs. + +@internalComponent +@param aIndex Index of the attendee to delete. +*/ + { + CAgnAttendee* attendee = (*iAttendeeList)[aIndex]; + + if (iPhoneOwner == attendee) + { + iPhoneOwner = NULL; + } + + if (iMeetingOrganizer == attendee) + { + iMeetingOrganizer = NULL; + } + + iAttendeeList->Remove(aIndex); + delete attendee; + } + + +EXPORT_C CAgnAttendee* CAgnEntry::PhoneOwner() const +/** Get Phone owner as attendee object + +@internalComponent +*/ + { + return iPhoneOwner; + } + + +EXPORT_C void CAgnEntry::SetPhoneOwnerL(CAgnAttendee* aAttendee) +/** Set Phone owner as attendee, this must be an existing attendee + +@internalComponent +@leave KErrNotFound if the passed attendee is not matching anyone in the current list +*/ + { + TInt ownerExists = KErrNotFound; + + if (iAttendeeList) + { + const TInt KCount = iAttendeeList->Count(); + + for (TInt i = 0; i < KCount; ++i) + { + if (aAttendee == (*iAttendeeList)[i]) + { + ownerExists = i; + } + } + } + + if (ownerExists == KErrNotFound && aAttendee != iMeetingOrganizer) + { + User::Leave(KErrNotFound); + } + + iPhoneOwner = aAttendee; + } + + +EXPORT_C void CAgnEntry::SetDTStampUtcL(const TTime& aDTStampUtc) +/** +@internalComponent +*/ + { + iDTStampUtc = aDTStampUtc; + } + + +EXPORT_C const TTime& CAgnEntry::DTStampUtcL() const +/** +@internalComponent +@return TTime +*/ + { + return iDTStampUtc; + } + +EXPORT_C TInt CAgnEntry::CategoryCount() const +/** Gets the number of categories owned by the entry. + +@internalComponent +@return The number of categories. +*/ + { + if ( !iCategoryList ) + { + return 0; + } + + return iCategoryList->Count(); + } + + +EXPORT_C void CAgnEntry::AddCategoryL(CAgnCategory* aCategory) +/** Appends a category to the entry's list of categories. + +The entry takes ownership of the category specified. + +@internalComponent +@param aCategory The category to be added +@leave KErrAlreadyExists if category already present +*/ + { + // Add an category for this entry + if ( !iCategoryList ) + { + iCategoryList = new (ELeave) RPointerArray; + } + + // Need to check that the category isn't already in the list + if ( ! CategoryExist(*aCategory) ) + { + iCategoryList->AppendL(aCategory); + } + else + { + User::Leave(KErrAlreadyExists); + } + } + +TBool CAgnEntry::CategoryExist(CAgnCategory& aSearchCategory) const +/** Check if category is already present + +@internalComponent +*/ + { + if (!iCategoryList) + { + return EFalse; + } + + //return ETrue if aSearchCategory belongs to this object, otherwise return EFalse + const TInt KNumCatList = iCategoryList->Count(); + + for ( TInt i = 0; i < KNumCatList; ++i ) + { + CAgnCategory& category = FetchCategory(i); + + CCalCategory::TCalCategoryType categoryType = category.Category(); + + if ( categoryType == aSearchCategory.Category()) + { + if ( categoryType == CCalCategory::ECalExtended ) // Need to compare names + { + if ( category.ExtendedCategoryName().CompareF(aSearchCategory.ExtendedCategoryName()) == 0 ) + { + return ETrue; + } + } + else + { + return ETrue; + } + } + } + + return EFalse; + } + + +EXPORT_C CAgnCategory& CAgnEntry::FetchCategory(TInt aIndex) const +/** Gets the indexed category. + +@internalComponent +@param aIndex Index into the entry's list of categories. Must be valid +or a panic occurs. +@return Pointer to the category located at the index specified. +*/ + { + __ASSERT_DEBUG(iCategoryList != NULL, Panic(EAgmErrCategoryListNotInitialised)); + __ASSERT_DEBUG(aIndex < iCategoryList->Count(), Panic(EAgmErrCategoryOutOfRange)); + + return *(*iCategoryList)[aIndex]; + } + + +EXPORT_C void CAgnEntry::DeleteCategory(TInt aIndex) +/** Deletes the indexed category. + +@internalComponent +@param aIndex Index into the entry's list of categories. Must be valid +or a panic occurs. +*/ + { + __ASSERT_DEBUG(iCategoryList != NULL, Panic(EAgmErrCategoryListNotInitialised)); + CAgnCategory* category = (*iCategoryList)[aIndex]; + delete category; + iCategoryList->Remove(aIndex); + + if ( iCategoryList->Count() == 0 ) + { + iCategoryList->ResetAndDestroy(); + delete iCategoryList; + iCategoryList=NULL; + } + } + + +EXPORT_C const TDesC& CAgnEntry::Description() const +/** Gets the notes text. + +If no notes text has been set, a empty descriptor (KNullDesC) is returned. + +@internalComponent +@capability ReadUserData +@return The notes text. +*/ + { + if ( iDescription ) + { + return *iDescription; + } + return KNullDesC; + } + + +EXPORT_C TBool CAgnEntry::DescriptionIsLoaded() const +/** Check notes is loaded + +@internalComponent +@capability ReadUserData +@return Boolean to indicate if loaded or not +*/ + { + if ( !iDescription && iDescriptionStreamId != KNullStreamId ) + { + return EFalse; + } + + return ETrue; + } + + +EXPORT_C void CAgnEntry::SetDescription(HBufC* aDescription) +/** Sets the notes text. + +This object takes ownership of aNotes. + +@internalComponent +@param aNotes Notes text. +*/ + { + delete iDescription; + iDescription = aDescription; + } + + +EXPORT_C CAgnEntry::TAgnDataChange CAgnEntry::DescriptionChange() const +/** Check if the notes changed + + 1. If iDescription is NULL, The description has never been added or never been loaded - No Change + 2. If iDescriptionStreamId is not KNullStreamId and iDecription is KNullDesC, The descrioption has been deleted (CAgnEntry::SetDescrioprion() can be used to delete description) + 3. If iDescriptionStreamId is not KNullStreamId and iDecription is not KNullDesC, The descrioption could be updated + 4. If iDescriptionStreamId is KNullStreamId and iDescription is not KNullDesC, The description has been added + +@internalComponent +@return TAgnDescriptionChange value indicating the type of change +*/ + { + TAgnDataChange change = EAgnDataNoChange; + if ( iDescription ) + { + if ( iDescriptionStreamId != KNullStreamId ) + { + if ( *iDescription == KNullDesC ) + { + change = EAgnDataDeleted; + } + else + { + change = EAgnDataUpdated; + } + } + else if ( *iDescription != KNullDesC ) + { + change = EAgnDataAdded; + } + } + + return change; + } + + +EXPORT_C CAgnEntry::TAgnDataChange CAgnEntry::SummaryChange() const +/** Check if the summary changed + + 1. If iSummary is NULL, The Summary has never been added or laoded- No Change + 2. If iSummaryStreamId is not KNullStreamId and iSummary is KNullDesC, The Summary has been deleted (CAgnEntry::SetSummary() can be used to delete description) + 3. If iSummaryStreamId is not KNullStreamId and iSummary is not KNullDesC, The Summary could be updated + 4. If iSummaryStreamId is KNullStreamId and iSummary is not KNullDesC, The Summary has been added + +@internalComponent +@return TAgnSummaryChange value indicating the type of change +*/ + { + TAgnDataChange change = EAgnDataNoChange; + + if ( iSummary ) + { + if ( iSummaryStreamId != KNullStreamId ) + { + if ( *iSummary == KNullDesC ) + { + change = EAgnDataDeleted; + } + else + { + change = EAgnDataUpdated; + } + } + else if ( *iSummary != KNullDesC ) + { + change = EAgnDataAdded; + } + } + + return change; + } + + +EXPORT_C CAgnEntry::TAgnDataChange CAgnEntry::AlarmActionChange() const +/** Check if the alarm action changed + + 1. If iAlarmActionDeleted is true, alarm has been deleted + 2. If iAlarmActionStreamId is KNullStreamId and iAlarmAction is not NULL, alarm has been added + 3. If iAlarmActionStreamId is not KNullStreamId and iAlarmAction is not KNullDesC, The AlarmAction could be updated + +@internalComponent +@return TAgnAlarmActionChange value indicating the type of change +*/ + { + TAgnDataChange change = EAgnDataNoChange; + + if ( IsFlagSet(EAgnAlarmActionDeleted) ) + { + change = EAgnDataDeleted; + } + else if ( iAlarmAction ) + { + if ( iAlarmActionStreamId == KNullStreamId ) + { + change = EAgnDataAdded; + } + else + { + change = EAgnDataUpdated; + } + } + + return change; + } + + +EXPORT_C const TStreamId& CAgnEntry::DescriptionStreamId() const +/** Gets the ID of the embedded stream store in which the description has been stored. + +@internalComponent +@return The ID for the stream store in which the description has been stored. +*/ + { + return iDescriptionStreamId; + } + + +EXPORT_C void CAgnEntry::SetDescriptionStreamId(const TStreamId& aStreamId) +/** Sets the ID of the embedded stream store in which the description has been stored. + +@internalComponent +@param The ID for the stream store in which the description has been stored. +*/ + { + iDescriptionStreamId = aStreamId; + } + + +EXPORT_C void CAgnEntry::SetSummaryStreamId(const TStreamId& aStreamId) +/** Sets the ID of the embedded stream store in which the summary has been stored. + +@internalComponent +@param The ID for the stream store in which the summary has been stored. +*/ + { + iSummaryStreamId = aStreamId; + } + +EXPORT_C const TStreamId& CAgnEntry::SummaryStreamId() const +/** Gets the ID of the embedded stream store in which the summary has been stored. + +@internalComponent +@return The ID for the stream store in which the summary has been stored. +*/ + { + return iSummaryStreamId; + } + +/** +@internalComponent +@capability None +@return TPtrC8 +*/ +EXPORT_C const TDesC8& CAgnEntry::Guid() const + { + return iGsData->Guid(); + } + +EXPORT_C void CAgnEntry::SetMethod(CCalEntry::TMethod aMethod) + { + iGsData->SetMethod(aMethod); + } + +EXPORT_C void CAgnEntry::SetGuid(HBufC8* aGuid) +/** +@internalComponent +*/ + { + iGsData->SetGuid(aGuid); + } + +EXPORT_C CGsData::TGsDataType CAgnEntry::GsDataType() const +/** +@internalComponent +*/ + { + return iGsData->GsDataType(); + } + +EXPORT_C CCalEntry::TMethod CAgnEntry::Method() const +/** +@internalComponent +*/ + { + return iGsData->Method(); + } + +EXPORT_C TInt CAgnEntry::SequenceNumber() const +/** +@internalComponent +*/ + { + return iGsData->SequenceNumber(); + } + + +EXPORT_C void CAgnEntry::SetSequenceNumber(TInt aSeqNum) + { + iGsData->SetSequenceNumber(aSeqNum); + } +/** +@internalComponent +@capability None +@return TTime +*/ +EXPORT_C TAgnCalendarTime CAgnEntry::RecurrenceId() const + { + return iGsData->RecurrenceId(); + } + +/** +@internalComponent +*/ +EXPORT_C CalCommon::TRecurrenceRange CAgnEntry::RecurrenceRange() const + { + return iGsData->RecurrenceRange(); + } + +EXPORT_C TCalLocalUid CAgnEntry::ParentId() const + { + __ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry)); + + return (static_cast(iGsData)->ParentId()); + } + +EXPORT_C void CAgnEntry::SetParentId(TCalLocalUid aParentId) + { + __ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry)); + + static_cast(iGsData)->SetParentId(aParentId); + } + +EXPORT_C void CAgnEntry::UpdateRecurrenceIdL(const TAgnCalendarTime& aRecId) + { + __ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry)); + + CGsChildData* childData = static_cast(iGsData); + TTimeIntervalHours hoursChange; + aRecId.UtcL().HoursFrom(RecurrenceId().UtcL(), hoursChange); + childData->SetRecurrenceId(aRecId); + } + +EXPORT_C void CAgnEntry::SetRecurrenceRangeL(CalCommon::TRecurrenceRange aRange) + { + if (RptDef()) + { + __ASSERT_DEBUG(aRange == CalCommon::EThisAndFuture || aRange == CalCommon::EThisAndPrior, User::Leave(KErrCorrupt)); + } + else + { + __ASSERT_DEBUG(aRange == CalCommon::EThisOnly, User::Leave(KErrCorrupt)); + } + + CGsChildData* childData = static_cast(iGsData); + childData->SetRecurrenceRange(aRange); + } + +EXPORT_C TBool CAgnEntry::HasChildren() const + { + if (GsDataType() == CGsData::EParent && ChildIds().Count() > 0) + { + return ETrue; + } + return EFalse; + } + +EXPORT_C const RArray& CAgnEntry::ChildIds() const + { + __ASSERT_DEBUG(GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry)); + + return (static_cast(iGsData)->ChildIds()); + } + +EXPORT_C void CAgnEntry::AddChildIdL(const TGsChildRefData& aChildRefData) + { + __ASSERT_DEBUG(GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry)); + + static_cast(iGsData)->AddChildIdL(aChildRefData); + } + +EXPORT_C void CAgnEntry::RemoveChildId(TCalLocalUid aId) + { + __ASSERT_DEBUG(GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry)); + + static_cast(iGsData)->RemoveChildId(aId); + } + +EXPORT_C void CAgnEntry::SetRecurrenceIdFromParentL(const CAgnEntry& aParentEntry) + {//Set the recurrence id and range by its parent data. + __ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry)); + TAgnCalendarTime recurid = RecurrenceId(); + + CGsChildData* childGsData = static_cast(iGsData); + if ( ! recurid.IsSet()) + { + recurid = aParentEntry.GetChildRecurrenceId(LocalUid()); + childGsData->SetRecurrenceId(recurid); + } + } + + TAgnCalendarTime CAgnEntry::GetChildRecurrenceId(TCalLocalUid aChildId) const + {//Get the recurrence id for one of its children + const RArray& KChildIds = ChildIds(); + + const TInt KCount((KChildIds.Count())); + TAgnCalendarTime recurId; + + for (TInt i = 0; i < KCount; ++i) + { + if (KChildIds[i].ChildId() == aChildId) + { + recurId = KChildIds[i].RecurrenceId(); + break; + } + } + return recurId; + } + + +EXPORT_C void CAgnEntry::SetAlarmAction(CAgnContent* aAlarmAction) +/** Set an alarm action object to the Agenda entry. +The Agenda Entry takes ownership of the passed object. +@internalComponent +*/ + { + if(iAlarmAction && !aAlarmAction && iAlarmActionStreamId != KNullStreamId) + { + SetFlagOn(EAgnAlarmActionDeleted); + } + + delete iAlarmAction; + + // Take ownership of the content. + iAlarmAction = aAlarmAction; + } + + +EXPORT_C TBool CAgnEntry::AlarmActionIsLoaded() const +/** Check if Alarm action object is loaded from the stream +@internalComponent +*/ + { + if ( !iAlarmAction && iAlarmActionStreamId != KNullStreamId && ! IsFlagSet(EAgnAlarmActionDeleted) ) + { + return EFalse; + } + + return ETrue; + } + + +EXPORT_C CAgnContent* CAgnEntry::AlarmAction() const +/** Get the Alarm action object +@internalComponent +*/ + { + return iAlarmAction; + } + + +EXPORT_C void CAgnEntry::SetAlarmActionStreamId(const TStreamId& aStreamId) +/** Set the Alarm action stream id +@internalComponent +*/ + { + iAlarmActionStreamId = aStreamId; + } + + +EXPORT_C const TStreamId& CAgnEntry::AlarmActionStreamId() const +/** Get the Alarm action stream id +@internalComponent +*/ + { + return iAlarmActionStreamId; + } + +EXPORT_C void CAgnEntry::AddAttachmentL(CAgnAttachment* aAttachment) + { + if (!iAttachments) + { + iAttachments = new (ELeave) RPointerArray; + } + if (aAttachment) + { + iAttachments->AppendL(aAttachment); + } + } + +EXPORT_C TInt CAgnEntry::DeleteAttachmentL(const CAgnAttachment& aAttachment) + { + TInt ret = -1; + if (iAttachments) + { + const TInt KAttachmentCount = iAttachments->Count(); + for (TInt i = 0; i < KAttachmentCount; ++i) + { + CAgnAttachment* attachToCompare = (*iAttachments)[i]; + if (attachToCompare->CompareL(aAttachment)) + { + ret = i; + delete attachToCompare; + iAttachments->Remove(i); + break; + } + } + } + return ret; + } + +EXPORT_C CAgnAttachment& CAgnEntry::Attachment(TInt aIndex) const + { + return *(*iAttachments)[aIndex]; + } + +EXPORT_C TInt CAgnEntry::AttachmentCount() const + { + if (iAttachments) + { + return iAttachments->Count(); + } + return 0; + } + +/** +Sets the user integer for this entry. + +@param aUserInt The new value of the user integer. +@internalComponent +*/ +EXPORT_C void CAgnEntry::SetUserInt( TUint32 aUserInt ) + { + CAgnSimpleEntry::SetUserInt(aUserInt); + } + +/** +Gets the user integer of this entry. + +@return The user integer. +@internalComponent +*/ +EXPORT_C TUint32 CAgnEntry::UserInt() const + { + return CAgnSimpleEntry::UserInt(); + } + +EXPORT_C void CAgnEntry::ExternalizeToBufferL(RWriteStream& aWriteStream) const +/** Used for passing the data to the between client and server +@internalComponent +*/ + { + ExternalizeEntryL(aWriteStream, ETrue); + ExternalizeGsDataL(aWriteStream, ETrue); + + if ( iDescription ) + { + aWriteStream.WriteUint8L(ETrue); + aWriteStream << *iDescription; + } + else + { + aWriteStream.WriteUint8L(EFalse); + } + + if ( iSummary ) + { + aWriteStream.WriteUint8L(ETrue); + aWriteStream << *iSummary; + } + else + { + aWriteStream.WriteUint8L(EFalse); + } + + TBool hasAlarmContent = iAlarmAction?ETrue:EFalse; + aWriteStream.WriteUint8L(hasAlarmContent); + if ( hasAlarmContent ) + { + aWriteStream << *iAlarmAction; + } + + aWriteStream.WriteUint8L(IsFlagSet(EAgnAlarmActionDeleted)); + } + + +EXPORT_C void CAgnEntry::InternalizeFromBufferL(RReadStream& aReadStream) +/** Used for passing the data to the between client and server +@internalComponent +*/ + { + InternalizeEntryL(aReadStream, ETrue); + InternalizeGsDataL(aReadStream, ETrue); + + delete iDescription; + iDescription = NULL; + if(aReadStream.ReadUint8L())//iDescription is not NULL + {//The following does not allocate KMaxTInt cells on heap + iDescription = HBufC::NewL(aReadStream, KMaxTInt); + } + + delete iSummary; + iSummary = NULL; + + if(aReadStream.ReadUint8L())//iSummary is not NULL + {//The following does not allocate KMaxTInt cells on heap + iSummary = HBufC::NewL(aReadStream, KMaxTInt); + } + + delete iAlarmAction; + iAlarmAction = NULL; + TBool hasAlarmContent = aReadStream.ReadUint8L(); + if ( hasAlarmContent ) + { + iAlarmAction = new (ELeave) CAgnContent; + aReadStream >> *iAlarmAction; + } + + if (aReadStream.ReadUint8L()) + { + SetFlagOn(EAgnAlarmActionDeleted); + } + else + { + SetFlagOff(EAgnAlarmActionDeleted); + } + // Externalize the entry details to the buffer + // Any rich text components will be stored in the textStream buffer + } + + +EXPORT_C CCalEntry::TTransp CAgnEntry::BusyStatus() const +/** Get transparency value +@internalComponent +*/ + { + return static_cast(iBusyStatus); + } + + +EXPORT_C void CAgnEntry::SetBusyStatusL(CCalEntry::TTransp aBusyStatus) +/** Set transparency value +@internalComponent +@leave KErrArgument if passed parameter is negative +*/ + { + if ( aBusyStatus < 0 ) + { + User::Leave( KErrArgument ); + } + + iBusyStatus = aBusyStatus; + } + +EXPORT_C void CAgnEntry::GeoValue(TReal& aLatitude, TReal& aLongitude) const + { + aLatitude=iLatitude; + aLongitude=iLongitude; + } + +/** Set GEO - Latitude and Longitude values for the entry +Latitude is bound between +-0-90 degrees +Longitude is bound between +-0-180 degrees +@internalComponent +@leave KErrArgument if passed parameter is out of bounds. +*/ +EXPORT_C void CAgnEntry::SetGeoValueL(const TReal& aLatitude, const TReal& aLongitude) + { + // Bounds checking + __ASSERT_ALWAYS( + ((aLatitude >= KCalGEOMinLatitude && aLatitude <= KCalGEOMaxLatitude) || aLatitude == KGEODefaultValue) + && ((aLongitude >= KCalGEOMinLongitude && aLongitude <= KCalGEOMaxLongitude) || aLongitude == KGEODefaultValue), + User::Leave(KErrArgument)); + + // Truncate to KGEOMaxDecimals decimal places + TReal truncatedLatitude; + TReal truncatedLongitude; + Math::Round(truncatedLatitude,aLatitude,KCalGEOMaxDecimalPlaces); + Math::Round(truncatedLongitude,aLongitude,KCalGEOMaxDecimalPlaces); + + iLatitude = truncatedLatitude; + iLongitude = truncatedLongitude; + } + +// verify entry is valid before storing it +EXPORT_C void CAgnEntry::VerifyBeforeStoreL() + { + //Check entry time + if ( Type() != CCalEntry::ETodo ) + { + __ASSERT_ALWAYS(StartTime().IsSet(), Panic(EAgmErrTimeNotSet)); + if ( Type() != CCalEntry::EReminder ) + { + __ASSERT_ALWAYS(EndTime().IsSet(), Panic(EAgmErrTimeNotSet)); + } + } + //Check repeating rule + if ( RptDef() ) + { + // check entry's repeat rule valid + if ( RptDef()->InvariantL() != KErrNone ) + { + const TAgnRpt* rptRule = RptDef()->RRule(); + __ASSERT_ALWAYS(rptRule, User::Leave(KErrCorrupt)); // this can never be NULL if Invariant returns an error + + // if entry has only one instance, clear the repeat rule + if ( rptRule->InstanceCountL() == 1 ) + { + RptDef()->ClearRRule(); + } + else + { + User::Leave(KErrArgument); + } + } + + else if (RptDef()->Exceptions()) + { + RptDef()->PruneExceptionsL(); + } + + //check the RDates here + TInt i = 0; + while (RptDef()->SporadicDateList() && i < RptDef()->SporadicDateList()->Count()) + { + const TAgnCalendarTime& KSporadicDate = (*RptDef()->SporadicDateList())[i]; + if (RptDef()->IsARepeatRuleDateInstanceL(KSporadicDate.LocalL())) + { + RptDef()->RemoveSporadicDate(KSporadicDate); + } + else if (EntryTime() == KSporadicDate) + { + // the DTSTART may not be checked in IsARepeatRuleDateInstance, so check it explicitly + RptDef()->RemoveSporadicDate(KSporadicDate); + } + else + { + // this sporadic date is ok + ++i; + } + } + + const TAgnRpt* rptRule = RptDef()->RRule(); + if(!rptRule && !(RptDef()->HasSporadicDates())) + { + ClearRepeat(); + } + } + } + +void CAgnEntry::SetFlagOn(TFlags aFlag) + { + iFlags |= aFlag; + } + +void CAgnEntry::SetFlagOff(TFlags aFlag) + { + iFlags &= ~aFlag; + } + +TBool CAgnEntry::IsFlagSet(TFlags aFlag) const + { + return (iFlags & aFlag); + }