--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarui/editors/src/CalenEntryUpdater.cpp Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,525 @@
+/*
+* Copyright (c) 2002-2004 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: ?Description
+*
+*/
+
+// user includes
+#include "CalenEntryUpdater.h"
+#include "CleanupResetAndDestroy.h"
+#include "calenglobaldata.h" // CCalenGlobalData
+//debug
+#include "calendarui_debug.h"
+
+// system includes
+#include <calcommon.h>
+#include <CalenInterimUtils2.h>
+#include <calenagendautils.h>
+#include <calendateutils.h>
+#include <calentry.h>
+#include <calentryview.h>
+#include <calinstance.h>
+#include <calinstanceview.h>
+#include <calrrule.h>
+#include <vwsdef.h>
+#include <calencommands.hrh> // Calendar commands
+#include <calencontext.h>
+#include <caleninstanceid.h> // TCalenInstanceId
+#include <calenservices.h>
+#include <calenactionuiutils.h>
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::NewL()
+// Two-phased constructor.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCalenEntryUpdater* CCalenEntryUpdater::NewL( MCalenServices& aServices ,RArray<TInt>& aCollectionIds )
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalenEntryUpdater* self = new (ELeave) CCalenEntryUpdater( aServices, aCollectionIds );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ TRACE_EXIT_POINT;
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::~CCalenEntryUpdater()
+// Destructor
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCalenEntryUpdater::~CCalenEntryUpdater()
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::CCalenEntryUpdater()
+// Constructor.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCalenEntryUpdater::CCalenEntryUpdater( MCalenServices& aServices , RArray<TInt>& aCollectionIds)
+: iServices( aServices ) , iCollectionIds(aCollectionIds)
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::ConstructL()
+// Leaving construction.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::ConstructL()
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::DeleteEntryL()
+// Delete the given entry from agenda.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::DeleteEntryL( CCalEntry& aEntry, TCalenInstanceId aInstanceId )
+ {
+ TRACE_ENTRY_POINT;
+
+ EntryViewL(aInstanceId.iColId).DeleteL( aEntry );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::TryDeleteInstanceWithUiL()
+// Attempt to delete the entry, using CCalenCommonUI. Only delete the entry
+// using the repeat type defined in aRepeatType.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::TryDeleteInstanceWithUiL( CCalEntry& aEntry,
+ const TCalTime& aInstanceDate,
+ CalCommon::TRecurrenceRange aRepeatType,
+ MCalenServices& aServices )
+ {
+ TRACE_ENTRY_POINT;
+ DoTryDeleteInstanceWithUiL( aEntry, aInstanceDate, ETrue, aRepeatType, aServices );
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::TryDeleteInstanceWithUiL()
+// Attempt to delete the entry, using CCalenCommonUI to prompt the user whether to
+// delete the entire series or just the instance.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::TryDeleteInstanceWithUiL( CCalEntry& aEntry,
+ const TCalTime& aInstanceDate,
+ MCalenServices& aServices )
+ {
+ TRACE_ENTRY_POINT;
+
+ DoTryDeleteInstanceWithUiL( aEntry,
+ aInstanceDate,
+ EFalse,
+ CalCommon::EThisAndAll,
+ aServices );
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::DoTryDeleteInstanceWithUiL()
+// If aHasRepeatType is ETrue, use aRepeatType to determine whether to delete the
+// entire series or just the instance. If aHasRepeatType is EFalse, aRepeatType is
+// ignored and the user is prompted to choose.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::DoTryDeleteInstanceWithUiL( CCalEntry& /*aEntry*/,
+ const TCalTime& /*aInstanceDate*/,
+ TBool aHasRepeatType,
+ CalCommon::TRecurrenceRange aRepeatType,
+ MCalenServices& aServices )
+ {
+ TRACE_ENTRY_POINT;
+
+ if( aHasRepeatType )
+ {
+ switch( aRepeatType )
+ {
+ case CalCommon::EThisOnly:
+ aServices.IssueCommandL( ECalenDeleteCurrentOccurrence );
+ break;
+ case CalCommon::EThisAndAll:
+ aServices.IssueCommandL( ECalenDeleteSeries );
+ break;
+ default:
+ ASSERT( 0 );
+ }
+ }
+ else
+ {
+ aServices.IssueCommandL( ECalenDeleteCurrentEntry );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::UpdateRDatesL()
+// Updates the RDates and Exception dates of the given entry.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::UpdateRDatesL( CCalEntry& aEditedEntry,
+ CCalEntry& aOrigEntry,
+ const TCalTime& aOrigInstanceDate )
+ {
+ TRACE_ENTRY_POINT;
+
+ RArray<TCalTime> rdates;
+ CleanupClosePushL( rdates );
+ aEditedEntry.GetRDatesL( rdates );
+
+ TBool hasRdates = rdates.Count() > 0;
+
+ // If we've changed the RRule but we already have RDates, get rid of the RDates.
+ if( hasRdates )
+ {
+ TCalRRule editedRule;
+ TBool editedHasRule = aEditedEntry.GetRRuleL( editedRule )
+ && editedRule.Type() != TCalRRule::EInvalid;
+
+ TCalRRule origRule;
+ TBool origHasRule = aOrigEntry.GetRRuleL( origRule )
+ && origRule.Type() != TCalRRule::EInvalid;
+
+ TBool repeatRuleHasChanged = EFalse;
+ if ( editedHasRule && origHasRule )
+ {
+ repeatRuleHasChanged = TypeOrIntervalChangedL( editedRule, origRule );
+ }
+ else
+ {
+ repeatRuleHasChanged = editedHasRule || origHasRule;
+ }
+
+ if( repeatRuleHasChanged && ! hasRdates )
+ {
+ // Clear any RDates, Exception dates etc.
+ aEditedEntry.ClearRepeatingPropertiesL();
+ aEditedEntry.SetRRuleL( editedRule );
+ }
+ else
+ {
+ // If the start time of the entry has been modified,
+ // and we have RDates, update the RDates to the new time.
+ if( aEditedEntry.StartTimeL().TimeLocalL() != aOrigEntry.StartTimeL().TimeLocalL() )
+ {
+ // The original time is that of the RDate which the user opened up,
+ // not the start time of the entry. First iteration through the rates
+ // is to get the time of day of the rdate on the instance day.
+
+ TTimeIntervalMinutes origTime = -1;
+ TTimeIntervalMinutes newTime = CalenDateUtils::TimeOfDay( aEditedEntry.StartTimeL().TimeLocalL() );
+
+ for( TInt i=0; i<rdates.Count(); ++i )
+ {
+ if( CalenDateUtils::OnSameDay( aOrigInstanceDate.TimeLocalL(), rdates[i].TimeLocalL() ) )
+ {
+ origTime = CalenDateUtils::TimeOfDay( rdates[i].TimeLocalL() );
+ }
+ }
+
+ // Alternatively, the entry opened up could have been the main parent entry.
+ if( origTime.Int() == -1 )
+ {
+ if( CalenDateUtils::OnSameDay( aOrigInstanceDate.TimeLocalL(), aOrigEntry.StartTimeL().TimeLocalL() ) )
+ {
+ origTime = CalenDateUtils::TimeOfDay( aOrigEntry.StartTimeL().TimeLocalL() );
+ }
+ }
+
+ ASSERT( origTime.Int() != -1 );
+
+ RArray<TCalTime> exdates;
+ CleanupClosePushL( exdates );
+ aOrigEntry.GetExceptionDatesL( exdates );
+
+ for( TInt i=0; i<rdates.Count(); ++i )
+ {
+ TBool ignore = EFalse;
+
+ for( TInt j=0; j<exdates.Count(); ++j )
+ {
+ if( rdates[i].TimeUtcL() == exdates[j].TimeLocalL() )
+ {
+ ignore = ETrue;
+ break;
+ }
+ }
+
+ if( !ignore && CalenDateUtils::TimeOfDay( rdates[ i ].TimeLocalL() ) == origTime )
+ {
+ TTime beginningOfDay = CalenDateUtils::BeginningOfDay( rdates[ i ].TimeLocalL() );
+
+
+ // Use floating time for non-timed entries
+ if ( !CalenAgendaUtils::IsTimedEntryL(aEditedEntry.EntryTypeL()))
+ {
+ rdates[ i ].SetTimeLocalFloatingL( beginningOfDay + newTime );
+ }
+ else
+ {
+ rdates[ i ].SetTimeLocalL( beginningOfDay + newTime );
+ }
+ }
+ }
+
+ aEditedEntry.SetRDatesL( rdates );
+ // SetExceptionDatesL doesn't remove any existing exception dates.
+ // As as result we have to clear the repeating properties then repopulate
+ // the entry's repeating properties by restoring the RRule, each child
+ // entry, the RDates, and any unduplicated exception dates.
+ aEditedEntry.SetExceptionDatesL( exdates );
+ CleanupStack::PopAndDestroy( &exdates );
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&rdates);
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::TypeOrIntervalChangedL
+// Compares two rrules for differences
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CCalenEntryUpdater::TypeOrIntervalChangedL( const TCalRRule& aEditedRule,
+ const TCalRRule& aOrigRule ) const
+ {
+ TRACE_ENTRY_POINT;
+
+ TBool repeatTypeChanged = aEditedRule.Type() != aOrigRule.Type();
+ TBool intervalChanged = aEditedRule.Interval() != aOrigRule.Interval();
+
+ TRACE_EXIT_POINT;
+ return ( repeatTypeChanged || intervalChanged );
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::UpdateInstanceL()
+// Stores the given entry using CCalenInterimUtils2.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::UpdateInstanceL( CCalEntry& aEditedEntry,
+ CCalEntry& aOrigEntry,
+ const TCalTime& aOrigInstanceDate,
+ CalCommon::TRecurrenceRange aWhichInstances,
+ const TCalTime& aNewInstanceStartDate,
+ const TCalTime& aNewInstanceEndDate,
+ const TDesC& aFileName )
+ {
+ TRACE_ENTRY_POINT;
+
+ TInt colId = iServices.SessionL(aFileName).CollectionIdL();
+
+ //Set the collection id here for temp instanceId and set it to context
+ TCalenInstanceId instanceIdTemp = iServices.Context().InstanceId();
+ instanceIdTemp.iColId = colId;
+ instanceIdTemp.iType = aEditedEntry.EntryTypeL();
+ if( aNewInstanceStartDate.TimeLocalL() != aOrigInstanceDate.TimeLocalL() )
+ {
+ instanceIdTemp.iInstanceTime = aNewInstanceStartDate.TimeLocalL();
+ }
+ iServices.Context().SetInstanceIdL(instanceIdTemp,iServices.Context().ViewId());
+ TBool isChild( aOrigEntry.RecurrenceIdL().TimeUtcL() != Time::NullTTime() );
+
+ if(isChild)
+ {
+ CCalenInterimUtils2::StoreL( EntryViewL(colId), aEditedEntry, ETrue );
+ }
+ else if( aWhichInstances == CalCommon::EThisAndAll )
+ {
+ UpdateRDatesL( aEditedEntry, aOrigEntry, aOrigInstanceDate );
+ CCalenInterimUtils2::StoreL( EntryViewL(colId), aEditedEntry, ETrue );
+ }
+ else if( aWhichInstances == CalCommon::EThisOnly )
+ {
+ // copy global UID from the original entry
+ HBufC8* guid = aOrigEntry.UidL().AllocLC();
+
+ // create new (child) entry
+ // Use original instance time for recurrenceID as this entry hasn't got one.
+ CCalEntry* newEntry = CCalEntry::NewL( aOrigEntry.EntryTypeL(),
+ guid,
+ aOrigEntry.MethodL(),
+ aOrigEntry.SequenceNumberL(),
+ aOrigInstanceDate,
+ aWhichInstances );
+
+ CleanupStack::Pop( guid ); // ownership transferred
+ CleanupStack::PushL( newEntry );
+
+ // copy all the data from edited entry
+ newEntry->CopyFromL( aEditedEntry );
+
+ // Workround for Symbian "features":
+ // The summary is not automatically copied when it is very large.
+ newEntry->SetSummaryL( aEditedEntry.SummaryL() );
+ // Calling SetStartAndEndTimeL on an entry with an RRule with TDays
+ // completely ignores the date you pass in.
+ if( ! CalenDateUtils::OnSameDay( aNewInstanceStartDate.TimeUtcL(), newEntry->StartTimeL().TimeUtcL() ) )
+ {
+ TCalTime newStart, newEnd;
+ TTime beginningOfDay = CalenDateUtils::BeginningOfDay( aNewInstanceStartDate.TimeUtcL() );
+ TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( newEntry->StartTimeL().TimeUtcL() );
+ newStart.SetTimeUtcL( beginningOfDay + timeOfDay );
+ beginningOfDay = CalenDateUtils::BeginningOfDay( aNewInstanceEndDate.TimeUtcL() );
+ timeOfDay = CalenDateUtils::TimeOfDay( newEntry->EndTimeL().TimeUtcL() );
+ newEnd.SetTimeUtcL( beginningOfDay + timeOfDay );
+ newEntry->SetStartAndEndTimeL( newStart, newEnd );
+ }
+
+ // reset local UID
+ newEntry->SetLocalUidL( TCalLocalUid( 0 ) );
+
+ // clear repeat rule properties
+ newEntry->ClearRepeatingPropertiesL();
+
+ // Set the geocoordinates
+ CCalGeoValue* geoValue = aEditedEntry.GeoValueL();
+ if( geoValue )
+ {
+ newEntry->SetGeoValueL( *geoValue );
+ delete geoValue;
+ }
+
+ CCalenInterimUtils2::StoreL( EntryViewL(colId), *newEntry, ETrue );
+
+ MCalenContext &context = iServices.Context();
+ TCalenInstanceId id = TCalenInstanceId::CreateL( *newEntry, aNewInstanceStartDate , colId );
+ context.SetFocusDateAndTimeAndInstanceL( aNewInstanceStartDate, id, context.ViewId() );
+
+ aEditedEntry.SetLocalUidL( newEntry->LocalUidL() );
+
+ CleanupStack::PopAndDestroy( newEntry );
+ }
+ else
+ {
+ // not supported in UI level
+ __ASSERT_ALWAYS( EFalse, User::Invariant() );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::FindInstanceL()
+// Returns the index into aInstances of the instance with the same UID as
+// aEntry, at the same date/time as aInstanceDate, or return KErrNotFound if
+// no match found.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CCalenEntryUpdater::FindInstanceL( CCalEntry& aEntry,
+ const TCalTime& aInstanceDate,
+ RPointerArray<CCalInstance>& aInstances)
+ {
+ TRACE_ENTRY_POINT;
+
+ InstanceViewL().FindInstanceL( aInstances,
+ CalCommon::EIncludeAll,
+ CalCommon::TCalTimeRange(aInstanceDate, aInstanceDate) );
+
+ for( TInt i( 0 ); i < aInstances.Count(); i++ )
+ {
+ if( aInstances[i]->Entry().UidL() == aEntry.UidL() )
+ {
+ TRACE_EXIT_POINT;
+ return i;
+ }
+ }
+
+ TRACE_EXIT_POINT;
+ return -1;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::EntryViewL()
+// Get CalEntryView from services
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCalEntryView& CCalenEntryUpdater::EntryViewL(TInt ColId)
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalEntryView* entryView = iServices.EntryViewL(ColId);
+
+ TRACE_EXIT_POINT;
+ return *entryView;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::InstanceViewL()
+// Get CalInstanceView from services
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCalInstanceView& CCalenEntryUpdater::InstanceViewL()
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalInstanceView* instanceView = iServices.InstanceViewL(iCollectionIds);
+
+ TRACE_EXIT_POINT;
+ return *instanceView;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenEntryUpdater::DeleteInstanceL()
+// Delete the given instance from agenda.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenEntryUpdater::DeleteInstanceL( CCalEntry& /*aEntry*/, TCalenInstanceId aInstanceId )
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalInstance* instance = CalenActionUiUtils::FindPossibleInstanceL( aInstanceId, InstanceViewL() );
+ if( instance )
+ {
+ CleanupStack::PushL( instance );
+ InstanceViewL().DeleteL(instance , CalCommon::EThisOnly);
+ CleanupStack::Pop( instance );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+// End of File