calendarui/editors/src/CalenEntryUpdater.cpp
changeset 0 f979ecb2b13e
child 13 0f07cd1b5772
--- /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