calendarui/editors/src/CalenEditorDataHandler.cpp
changeset 0 f979ecb2b13e
child 16 55d60436f00b
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  CalenEditorDataHandler implements all logic of checking and
       
    15 *                validating editor data
       
    16 *
       
    17 */
       
    18 
       
    19 // System includes
       
    20 #include <calendateutils.h>
       
    21 #include <calenagendautils.h>
       
    22 #include <calinstance.h>
       
    23 #include <calalarm.h>
       
    24 #include <calentry.h>
       
    25 #include <calrrule.h>
       
    26 #include <centralrepository.h>
       
    27 #include <calattachment.h>
       
    28 #include <eikenv.h>
       
    29 #include <CalenInterimUtils2.h>
       
    30 #include <calencontext.h>
       
    31 #include <caleninstanceid.h>            // TCalenInstanceId
       
    32 #include <calenservices.h>
       
    33 
       
    34 // User includes
       
    35 #include "CalenEditorDataHandler.h"
       
    36 #include "CalendarPrivateCRKeys.h"
       
    37 #include "CalenDefaultEditors.hrh"
       
    38 #include "calenentryutil.h"
       
    39 #include "CleanupResetAndDestroy.h"
       
    40 #include "calenattachmentutils.h"
       
    41 #include "calenattachmentinfo.h"
       
    42 #include "calenattachmentmodel.h"
       
    43 #include "calenunifiededitor.h"
       
    44 #include "calendarui_debug.h"
       
    45 
       
    46 // Constants
       
    47 #define KNoOfDaysInWeek  7
       
    48 
       
    49 // ======== LOCAL FUNCTIONS ========
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // IsTimed
       
    53 // Returns ETrue if the entry is timed (i.e. an appointment or a
       
    54 // reminder), EFalse otherwise.
       
    55 // (other items were commented in a header).
       
    56 // -----------------------------------------------------------------------------
       
    57 //
       
    58 static TBool IsTimed( CCalEntry::TType aEntryType )
       
    59     {
       
    60     TRACE_ENTRY_POINT;
       
    61 
       
    62     TRACE_EXIT_POINT;
       
    63     return aEntryType == CCalEntry::EAppt || aEntryType == CCalEntry::EReminder;  
       
    64     }
       
    65        
       
    66 // -----------------------------------------------------------------------------
       
    67 // ForeverDate
       
    68 // Returns the date which Calendar presumes to be infinitely far in the future.
       
    69 // Used, for example, when setting a repeating meeting to repeat forever.
       
    70 // (other items were commented in a header).
       
    71 // -----------------------------------------------------------------------------
       
    72 //
       
    73 static TTime ForeverDate()
       
    74     {
       
    75     TRACE_ENTRY_POINT;
       
    76 
       
    77     TTime forever = TTime( TDateTime( ECalenForeverYear, static_cast<TMonth>( ECalenForeverMonth ), 
       
    78                            ECalenForeverDay, 0, 0, 0, 0) );
       
    79 
       
    80     TRACE_EXIT_POINT;
       
    81     return forever;
       
    82     }
       
    83 
       
    84 // -----------------------------------------------------------------------------
       
    85 // IsForeverDate
       
    86 // Returns ETrue if the given date is considered by Calendar to be infinitely
       
    87 // far in the future.
       
    88 // (other items were commented in a header).
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 static TBool IsForeverDate( const TTime& aDate )
       
    92     {
       
    93     TRACE_ENTRY_POINT;
       
    94 
       
    95     TRACE_EXIT_POINT;
       
    96     return CalenDateUtils::OnSameDay( aDate, ForeverDate() );
       
    97     }
       
    98 
       
    99 // ======== MEMBER FUNCTIONS ========
       
   100 
       
   101 // ---------------------------------------------------------------------------
       
   102 // CCalenEditorDataHandler::CCalenEditorDataHandler
       
   103 // Constructor.
       
   104 // (other items were commented in a header).
       
   105 // ---------------------------------------------------------------------------
       
   106 //
       
   107 CCalenEditorDataHandler::CCalenEditorDataHandler(
       
   108                                             CCalEntry& aEntry,
       
   109                                             const TCalTime& aInstanceDateTime,
       
   110                                             TBool aIsCreatingNew,
       
   111                                             TInt aMaxTextEditorLength,
       
   112                                             MCalenServices& aServices,
       
   113                                             RArray<TInt>& aCollectionIds)
       
   114     : iEntry( aEntry ),
       
   115       iInstanceDateTime( aInstanceDateTime ),
       
   116       iIsCreatingNew( aIsCreatingNew ),
       
   117       iMaxTextEditorLength( aMaxTextEditorLength ),
       
   118       iServices( aServices ) , iCalendarFieldEdited(EFalse) , iCollectionIds(aCollectionIds)
       
   119     {
       
   120     TRACE_ENTRY_POINT;
       
   121     TRACE_EXIT_POINT;
       
   122     }
       
   123 
       
   124 // ---------------------------------------------------------------------------
       
   125 // CCalenEditorDataHandler::ConstructL
       
   126 // Two phase construction.
       
   127 // (other items were commented in a header).
       
   128 // ---------------------------------------------------------------------------
       
   129 //
       
   130 void CCalenEditorDataHandler::ConstructL()
       
   131     {
       
   132     TRACE_ENTRY_POINT;
       
   133 
       
   134     iEntryType = iEntry.EntryTypeL();
       
   135     iRecurrenceId = iEntry.RecurrenceIdL();
       
   136 
       
   137     iOriginal = CCalenEntryUtil::NewL( iEntry, iInstanceDateTime );
       
   138     iEdited = CCalenEntryUtil::NewL( iEntry, iInstanceDateTime );
       
   139     if ( IsCreatingNew() )
       
   140         {
       
   141         SetDefaultNewValuesL( *iOriginal ); // modify iOriginal also
       
   142         SetDefaultNewValuesL( *iEdited );
       
   143         }
       
   144     else
       
   145         {
       
   146         iInstanceId = iServices.Context().InstanceId();
       
   147         }
       
   148     
       
   149 
       
   150     TRACE_EXIT_POINT;
       
   151     }
       
   152 
       
   153 // ---------------------------------------------------------------------------
       
   154 // CCalenEditorDataHandler::NewL
       
   155 // Two-phased constructor.
       
   156 // (other items were commented in a header).
       
   157 // ---------------------------------------------------------------------------
       
   158 //
       
   159 CCalenEditorDataHandler* CCalenEditorDataHandler::NewL(
       
   160                                             CCalEntry& aEntry,
       
   161                                             const TCalTime& aInstanceDateTime,
       
   162                                             TBool aIsCreatingNew,
       
   163                                             TInt aMaxTextEditorLength,
       
   164                                             MCalenServices& aServices,
       
   165                                             RArray<TInt>& aCollectionIds)
       
   166     {
       
   167     TRACE_ENTRY_POINT;
       
   168 
       
   169     CCalenEditorDataHandler* self = new( ELeave ) CCalenEditorDataHandler(
       
   170         aEntry, aInstanceDateTime, aIsCreatingNew, aMaxTextEditorLength, aServices,aCollectionIds );
       
   171     CleanupStack::PushL( self );
       
   172     self->ConstructL();
       
   173     CleanupStack::Pop( self );
       
   174 
       
   175     TRACE_EXIT_POINT;
       
   176     return self;
       
   177     }
       
   178 
       
   179 // ---------------------------------------------------------------------------
       
   180 // CCalenEditorDataHandler::~CCalenEditorDataHandler
       
   181 // Destructor.
       
   182 // (other items were commented in a header).
       
   183 // ---------------------------------------------------------------------------
       
   184 //
       
   185 CCalenEditorDataHandler::~CCalenEditorDataHandler()
       
   186     {
       
   187     TRACE_ENTRY_POINT;
       
   188 
       
   189     delete iOriginal;
       
   190     delete iEdited;
       
   191 
       
   192     TRACE_EXIT_POINT;
       
   193     }
       
   194 
       
   195 // ---------------------------------------------------------------------------
       
   196 // CCalenEditorDataHandler::Edited
       
   197 // Returns the CCalenEditorDataHandler used to represent the entry the
       
   198 // user is currently editing.
       
   199 // (other items were commented in a header).
       
   200 // ---------------------------------------------------------------------------
       
   201 //
       
   202 CCalenEntryUtil& CCalenEditorDataHandler::Edited()
       
   203     {
       
   204     TRACE_ENTRY_POINT;
       
   205 
       
   206     TRACE_EXIT_POINT;
       
   207     return *iEdited;
       
   208     }
       
   209 
       
   210 // ---------------------------------------------------------------------------
       
   211 // CCalenEditorDataHandler::Original
       
   212 // Returns the CCalenEditorDataHandler used to represent the entry the
       
   213 // user originally opened.
       
   214 // (other items were commented in a header).
       
   215 // ---------------------------------------------------------------------------
       
   216 //
       
   217 const CCalenEntryUtil& CCalenEditorDataHandler::Original() const
       
   218     {
       
   219     TRACE_ENTRY_POINT;
       
   220 
       
   221     TRACE_EXIT_POINT;
       
   222     return *iOriginal;
       
   223     }
       
   224 
       
   225 // ---------------------------------------------------------------------------
       
   226 // CCalenEditorDataHandler::Entry
       
   227 // Returns the entry this object is wrapping round.
       
   228 // (other items were commented in a header).
       
   229 // ---------------------------------------------------------------------------
       
   230 //
       
   231 CCalEntry& CCalenEditorDataHandler::Entry()
       
   232     {
       
   233     TRACE_ENTRY_POINT;
       
   234 
       
   235     TRACE_EXIT_POINT;
       
   236     return iEntry;
       
   237     }
       
   238 
       
   239 // ---------------------------------------------------------------------------
       
   240 // CCalenEditorDataHandler::InstanceDateTime
       
   241 // Returns the instance date/time.
       
   242 // (other items were commented in a header).
       
   243 // ---------------------------------------------------------------------------
       
   244 //
       
   245 const TCalTime& CCalenEditorDataHandler::InstanceDateTime() const
       
   246     {
       
   247     TRACE_ENTRY_POINT;
       
   248 
       
   249     TRACE_EXIT_POINT;
       
   250     return iInstanceDateTime;
       
   251     }
       
   252 
       
   253 
       
   254 // ---------------------------------------------------------------------------
       
   255 // CCalenEditorDataHandler::ShouldSaveOrDeleteOrDoNothingL
       
   256 // Works out whether the entry should be deleted, saved, 
       
   257 // or whether no action should be taken.
       
   258 // (other items were commented in a header).
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 CCalenEditorDataHandler::TAction CCalenEditorDataHandler::ShouldSaveOrDeleteOrDoNothingL()
       
   262     {
       
   263     TRACE_ENTRY_POINT;
       
   264 
       
   265     if ( !IsEditedL() )
       
   266         {
       
   267         // Not edited at all OR
       
   268         // Only added space characters to text fields but not
       
   269         // edited the non-text fields
       
   270         // no need to save the note
       
   271         TRACE_EXIT_POINT;
       
   272         return CCalenEditorDataHandler::EActionNothing;        
       
   273         }
       
   274 
       
   275     // *************** THE NOTE IS EDITED ********************
       
   276     if(IsCreatingNew())
       
   277         {
       
   278         // ************* EDITED NEW NOTE *********   
       
   279           
       
   280         // Subject && Location && Description are text fields                   
       
   281         // If text fields as a whole is not empty, we can save the note
       
   282         // If text fields as a whole IS empty, we can STILL save the note
       
   283         // since we edited "non-text" fields
       
   284         if ( !NonTextFieldsEditedL() && AreTextFieldsEmptyL() )
       
   285             {
       
   286             TRACE_EXIT_POINT;
       
   287             return CCalenEditorDataHandler::EActionNothing;
       
   288             }
       
   289         else
       
   290             {
       
   291             TRACE_EXIT_POINT;
       
   292             return CCalenEditorDataHandler::EActionSave;
       
   293             }
       
   294         }
       
   295 
       
   296      // **************** EDITED OLD NOTE **********    
       
   297 
       
   298      if(AreTextFieldsClearedL() && !NonTextFieldsEditedL()) // subject && location && description
       
   299         {
       
   300         // ***** OLD NOTE + TEXT FIELDS EMPTIED + NON-TEXT FIELDS NOT EDITED
       
   301         // Even if user may have edited non-text fields, 
       
   302         // delete the note 
       
   303         TRACE_EXIT_POINT;
       
   304         return CCalenEditorDataHandler::EActionDelete;        
       
   305         }
       
   306 
       
   307     // ****** OLD NOTE WITH TEXT FIELDS **********
       
   308     // Save the note, since the text fields contain something
       
   309     TRACE_EXIT_POINT;
       
   310     return CCalenEditorDataHandler::EActionSave;
       
   311     }
       
   312 
       
   313 // ---------------------------------------------------------------------------
       
   314 // CCalenEditorDataHandler::NonTextFieldsEdited
       
   315 // Returns ETrue if any of the non-text fields (e.g. time fields) of the entry
       
   316 // have been edited, EFalse otherwise.
       
   317 // (other items were commented in a header).
       
   318 // ---------------------------------------------------------------------------
       
   319 //
       
   320 TBool CCalenEditorDataHandler::NonTextFieldsEditedL()
       
   321     {
       
   322     TRACE_ENTRY_POINT;
       
   323 
       
   324     TRACE_EXIT_POINT;
       
   325     
       
   326     return ( IsStartDateTimeEdited() ||
       
   327              IsEndDateTimeEdited()   ||
       
   328              IsAlarmEditedL()        ||
       
   329              IsRepeatRuleEdited()    ||
       
   330              IsPriorityEdited()      ||
       
   331              IsCalendarEditedL()     ||
       
   332              IsAttachmentExists()    ||
       
   333              IsEventTypeEdited()     ||
       
   334              AllDayFieldEdited() );
       
   335     }
       
   336 
       
   337 // ---------------------------------------------------------------------------
       
   338 // CCalenEditorDataHandler::TextFieldsEdited
       
   339 // Returns ETrue if any of the text fields (e.g. summary) of the entry
       
   340 // have been edited, EFalse otherwise.
       
   341 // (other items were commented in a header).
       
   342 // ---------------------------------------------------------------------------
       
   343 //
       
   344 TBool CCalenEditorDataHandler::TextFieldsEdited()
       
   345     {
       
   346     TRACE_ENTRY_POINT;
       
   347 
       
   348     TRACE_EXIT_POINT;
       
   349 
       
   350     return ( IsSummaryEdited()  || IsLocationEdited() || IsDescriptionEdited()
       
   351             || IsAttachmentExists() );
       
   352     }
       
   353 
       
   354 // ---------------------------------------------------------------------------
       
   355 // CCalenEditorDataHandler::IsEditedL
       
   356 // Returns ETrue if the entry has been modified, EFalse otherwise.
       
   357 // (other items were commented in a header).
       
   358 // ---------------------------------------------------------------------------
       
   359 //
       
   360 TBool CCalenEditorDataHandler::IsEditedL()
       
   361     {
       
   362     TRACE_ENTRY_POINT;
       
   363 
       
   364     TRACE_EXIT_POINT;
       
   365 
       
   366     return ( TextFieldsEdited() || NonTextFieldsEditedL() );
       
   367     }
       
   368 
       
   369 // ---------------------------------------------------------------------------
       
   370 // CCalenEditorDataHandler::WriteChangesToEntryL
       
   371 // Read the data from the form and set it to the entry.
       
   372 // (other items were commented in a header).
       
   373 // ---------------------------------------------------------------------------
       
   374 //
       
   375 void CCalenEditorDataHandler::WriteChangesToEntryL( CalCommon::TRecurrenceRange aRepeatTarget )
       
   376     {
       
   377     TRACE_ENTRY_POINT;
       
   378 
       
   379     // This is only place where we can read data from CCalEntry.
       
   380     // E.g. when we calculate alarm offset, we need to read start time from
       
   381     // entry, not anymore from CCalenEntryUtil.
       
   382     TBool isNew = IsCreatingNew();
       
   383 
       
   384     WriteStartAndEndTimesToEntryL( aRepeatTarget );
       
   385 
       
   386     if ( isNew || IsSummaryEdited() )
       
   387         {
       
   388         TPtrC summary = Edited().Summary();
       
   389         // If text is considered empty, always store as KNullDesC
       
   390         if ( CalenAgendaUtils::IsEmptyText( summary ) )
       
   391             {
       
   392             summary.Set( KNullDesC );
       
   393             }
       
   394         iEntry.SetSummaryL( summary );
       
   395         }
       
   396 
       
   397     if ( isNew || IsLocationEdited() )
       
   398         {
       
   399         TPtrC location = Edited().Location();
       
   400         // If text is considered empty, always store as KNullDesC
       
   401         if ( CalenAgendaUtils::IsEmptyText( location ) )
       
   402             {
       
   403             location.Set(KNullDesC);
       
   404             }
       
   405         iEntry.SetLocationL( location );
       
   406         }
       
   407 
       
   408     if ( isNew || IsDescriptionEdited() )
       
   409         {
       
   410         iEntry.SetDescriptionL( Edited().Description() );
       
   411         }
       
   412 
       
   413     // Repeat rule has to be modified in both cases
       
   414     if ( isNew || IsStartDateTimeEdited() || IsRepeatRuleEdited() )
       
   415         {
       
   416 
       
   417         if ( aRepeatTarget == CalCommon::EThisOnly)
       
   418             {
       
   419             iEntry.ClearRepeatingPropertiesL();
       
   420             }
       
   421         else if ( Edited().IsRepeating() )
       
   422             {
       
   423             // If we're an RDate (with repeat type ERepeatOther), don't try to set an RRule,
       
   424             // but don't clear the repeat properties either.
       
   425             if( Edited().RepeatType() != ERepeatOther )
       
   426                 {
       
   427                 TCalRRule rrule;
       
   428 
       
   429                 CalculateRepeatRuleL( Edited().StartDateTime(),
       
   430                                       Edited().RepeatType(),
       
   431                                       Edited().RepeatUntilDateTime(),
       
   432                                       rrule );
       
   433 
       
   434                 iEntry.SetRRuleL( rrule );
       
   435                 
       
   436                 // As there should not be any rdates, remove any that are
       
   437                 // still present
       
   438                 RArray<TCalTime> emptyList;
       
   439                 CleanupClosePushL( emptyList );
       
   440                 iEntry.SetRDatesL( emptyList );
       
   441                 CleanupStack::PopAndDestroy(); // emptyList
       
   442                 }
       
   443             else
       
   444                 {
       
   445                 // The repeat type is ERepeatOther, therefore as 
       
   446                 // it is impossible to create an entry of type
       
   447                 // ERepeat other using the editor either the repeat until
       
   448                 // date or the start date must have been changed
       
   449 
       
   450                 // The start date/time has changed, in order for the
       
   451                 // series to maintain its pattern, any rDates and if
       
   452                 // present rRule are moved by the same offset
       
   453                 // The repeat type is ERepeatOther, so check if we have any rdates
       
   454                 RArray<TCalTime> rDateList;
       
   455                 CleanupClosePushL( rDateList );
       
   456                 iEntry.GetRDatesL( rDateList );
       
   457                 TInt count = rDateList.Count();
       
   458 
       
   459                 if ( count == 0 )
       
   460                     {
       
   461                     // There are no rdates so the new until and start date can be applied
       
   462                     // directly.
       
   463                     TCalRRule rrule;
       
   464 
       
   465                     CalculateRepeatRuleL( Edited().StartDateTime(),
       
   466                                       Edited().RepeatType(),
       
   467                                       Edited().RepeatUntilDateTime(),
       
   468                                       rrule );
       
   469 
       
   470                     iEntry.SetRRuleL( rrule );
       
   471                     }
       
   472                 else
       
   473                     {
       
   474                     // There are rDates which need to be checked.
       
   475                     if ( IsStartDateTimeEdited() )
       
   476                         {
       
   477                         // Need to shift any rdates
       
   478                         TTime editedStart = iEdited->StartDateTime();
       
   479                         TTime origStart = iOriginal->StartDateTime();
       
   480                         TTimeIntervalMicroSeconds offSet = editedStart.MicroSecondsFrom( origStart );
       
   481                         for ( TInt index = 0; index < count; index++ )
       
   482                             {
       
   483                             TCalTime& rDateTime = rDateList[ index ];
       
   484                             TTime shiftedTime = rDateTime.TimeUtcL();
       
   485                             TDateTime before = shiftedTime.DateTime();
       
   486                             shiftedTime += offSet;
       
   487                             TDateTime after = shiftedTime.DateTime();
       
   488                             rDateTime.SetTimeUtcL( shiftedTime ); 
       
   489                             }
       
   490                         }
       
   491 
       
   492                     //  Check and fix the rDates and rRules match the 
       
   493                     //  repeat until date and time.
       
   494                     TTime untilTime = Edited().RepeatUntilDateTime();
       
   495                     
       
   496                     // Remove any rdates that are after the the repeat until date
       
   497                     TInt count = rDateList.Count();
       
   498                     if ( count > 0 )
       
   499                         {
       
   500                         TInt index = count - 1;
       
   501                         do 
       
   502                             {
       
   503                             TTime lastRDate = CalenDateUtils::BeginningOfDay( rDateList[ index ].TimeLocalL() );
       
   504                             TDateTime before = lastRDate.DateTime();
       
   505                             if ( lastRDate > untilTime )
       
   506                                 {
       
   507                                 rDateList.Remove( index-- );
       
   508                                 }
       
   509                             else
       
   510                                 {
       
   511                                 index = KErrNotFound;
       
   512                                 }
       
   513                             } while ( index != KErrNotFound );
       
   514                         }
       
   515                     
       
   516                     // Need to check if the end date of the
       
   517                     // rrule needs adjusting if it exists.
       
   518                     TCalRRule rRule;
       
   519                     if ( iEntry.GetRRuleL( rRule ) )
       
   520                         {
       
   521                         count = rDateList.Count();
       
   522                         if ( count > 0 )
       
   523                             {
       
   524                             // There still exists some rdates, so only need to trim 
       
   525                             // the rrule if it exists
       
   526                             TTime lastRDate = CalenDateUtils::BeginningOfDay( rDateList[ count - 1 ].TimeLocalL() );
       
   527                             const TTime& origUntilDate = Original().RepeatUntilDateTime();
       
   528                             TTime startDT = rRule.DtStart().TimeLocalL();
       
   529                             
       
   530                             if ( lastRDate <= origUntilDate && startDT > lastRDate )
       
   531                                 { 
       
   532                                 if ( startDT < untilTime)
       
   533                                     {
       
   534                                     if( origUntilDate != untilTime)
       
   535                                     	{
       
   536 										ApplyUntilDateToRRuleL( rRule, untilTime);
       
   537                                     	iEntry.SetRRuleL( rRule );
       
   538                                     	}
       
   539                                     }
       
   540                                  else
       
   541                                     {
       
   542                                     // The repeat start is after the until date
       
   543                                     // so remove any repeat information.
       
   544                                     iEntry.ClearRepeatingPropertiesL();
       
   545 
       
   546                                     // If the entry date has been moved past the until
       
   547                                     // date, need to swap the an rDate for the entry.
       
   548                                     TTime startTime = iEntry.StartTimeL().TimeLocalL();
       
   549 
       
   550                                     if ( startTime > untilTime )
       
   551                                         {
       
   552                                         // Find the duration of the entry
       
   553                                         TTime endTime = iEntry.EndTimeL().TimeLocalL();
       
   554                                         TTimeIntervalMinutes duration;
       
   555                                         //startTime.MinutesFrom( endTime, duration );// for bug: CMCA-745CZ4
       
   556                                         endTime.MinutesFrom( startTime, duration );
       
   557                                         
       
   558                                         // Choose the first rDate as the new start time
       
   559                                         TCalTime newStartTime = rDateList[ 0 ];
       
   560                                         endTime = newStartTime.TimeLocalL() + duration;
       
   561 
       
   562                                         // FIXME.
       
   563                                         // If there is only one rDate left, the agenda model
       
   564                                         // will crash if it is deleted.
       
   565                                         if ( count != 0 )
       
   566                                             {
       
   567                                             rDateList.Remove( 0 );
       
   568                                             }
       
   569 
       
   570                                         TCalTime newEndTime;
       
   571                                         if ( UseFloatingTimeL() )
       
   572                                             {
       
   573                                             newEndTime.SetTimeLocalFloatingL( endTime );
       
   574                                             }
       
   575                                         else
       
   576                                             {
       
   577                                             newEndTime.SetTimeLocalL( endTime );
       
   578                                             }
       
   579 
       
   580                                         iEntry.SetStartAndEndTimeL( newStartTime, newEndTime );
       
   581                                         }    
       
   582                                     }
       
   583                                 }
       
   584                             }
       
   585                         }
       
   586 
       
   587                     iEntry.SetRDatesL( rDateList );
       
   588                     }
       
   589 
       
   590                 CleanupStack::PopAndDestroy(); // rDateList
       
   591                 }
       
   592             }
       
   593         else
       
   594             {
       
   595             iEntry.ClearRepeatingPropertiesL();
       
   596 
       
   597             // FIXME  As the entry is supposedly not repeating
       
   598             // any rDates should be removed. Unforunately this
       
   599             // is not possible at the moment because removing the 
       
   600             // rdates will cause the agenda model to panic
       
   601             //
       
   602             // RArray<TCalTime> emptyList;
       
   603             // CleanupClosePushL( emptyList );
       
   604             // iEntry.SetRDatesL( emptyList );
       
   605             // CleanupStack::PopAndDestroy(); // emptyList
       
   606             }
       
   607         }
       
   608 
       
   609     if ( isNew || IsAlarmEditedL() && ( iEntry.StatusL() != CCalEntry::ETodoCompleted ) )
       
   610         {
       
   611         if ( Edited().IsAlarmActivated() )
       
   612             {
       
   613             CCalAlarm* alarm  = iEntry.AlarmL();
       
   614             if ( ! alarm )
       
   615                 {
       
   616                 alarm = CCalAlarm::NewL();
       
   617                 }
       
   618             CleanupStack::PushL( alarm );
       
   619 
       
   620             TTime startTime;
       
   621             //  ToDos don't have start time! 
       
   622             // If we have undated todo with alarm that was taken care earlier
       
   623             if (iEntry.EntryTypeL()==CCalEntry::ETodo)
       
   624                 {
       
   625                 startTime = iEntry.EndTimeL().TimeLocalL();
       
   626                 }
       
   627 
       
   628             // if this is not todo we use starttime normal way
       
   629              else
       
   630                 {
       
   631                 startTime = iEntry.StartTimeL().TimeLocalL();
       
   632                 }
       
   633             TCalRRule ignore;
       
   634             TBool isRepeating = iEntry.GetRRuleL( ignore );
       
   635 
       
   636             // If edit alarm of repeating entry, we have to nudge start
       
   637             // time to instance date
       
   638             if ( isRepeating &&  aRepeatTarget == CalCommon::EThisAndAll )
       
   639                 {
       
   640                 // nudge to instance date;
       
   641                 TTime instanceDate = iInstanceDateTime.TimeLocalL();
       
   642                 if ( IsStartDateTimeEdited() )
       
   643                     {
       
   644                     instanceDate = Edited().EventDateTime();
       
   645                     }
       
   646 
       
   647                 TDateTime insDt = instanceDate.DateTime();
       
   648                 TDateTime startDt = startTime.DateTime();
       
   649                 // Don't use individual setters (SetMonth, SetDay ...), because
       
   650                 // they break if month doesn't contain old  date
       
   651                 // or date to be set.
       
   652                 startDt.Set( insDt.Year(), insDt.Month(), insDt.Day(),
       
   653                              startDt.Hour(), startDt.Minute(),
       
   654                              startDt.Second(), startDt.MicroSecond() );
       
   655                 startTime = TTime( startDt );
       
   656                 }
       
   657 
       
   658             TTime alarmTime = Edited().AlarmDateTime();
       
   659 
       
   660             TTimeIntervalMinutes offset;
       
   661             startTime.MinutesFrom( alarmTime, offset );
       
   662             alarm->SetTimeOffset( offset );
       
   663 
       
   664             iEntry.SetAlarmL( alarm );
       
   665             CleanupStack::PopAndDestroy( alarm );
       
   666             }
       
   667         else
       
   668             {
       
   669             iEntry.SetAlarmL( NULL );
       
   670             }
       
   671         }
       
   672 
       
   673     if ( isNew || IsPriorityEdited() )
       
   674         {
       
   675         // map priority here
       
   676         TUint priority = 0;
       
   677         switch ( Edited().Priority() )
       
   678             {
       
   679             case CCalenEntryUtil::ETodoPriorityHigh:
       
   680                 priority = 1;
       
   681                 break;
       
   682             case CCalenEntryUtil::ETodoPriorityNormal:
       
   683                 priority = 2;
       
   684                 break;
       
   685             case CCalenEntryUtil::ETodoPriorityLow:
       
   686                 priority = 3;
       
   687                 break;
       
   688             default:
       
   689                 ASSERT( EFalse );
       
   690                 break;
       
   691             }
       
   692         iEntry.SetPriorityL( priority );
       
   693         }
       
   694 
       
   695     if ( isNew )
       
   696         {
       
   697         CCalEntry::TReplicationStatus status = CCalEntry::EOpen;
       
   698         switch ( Edited().SynchType() )
       
   699             {
       
   700             case CCalenEntryUtil::ESynchPrivate:
       
   701                 status = CCalEntry::EPrivate;
       
   702                 break;
       
   703             case CCalenEntryUtil::ESynchPublic:
       
   704                 status = CCalEntry::EOpen;
       
   705                 break;
       
   706             case CCalenEntryUtil::ESynchNoSync:
       
   707                 status = CCalEntry::ERestricted;
       
   708                 break;
       
   709             default:
       
   710                 ASSERT( EFalse );
       
   711                 break;
       
   712             }
       
   713         iEntry.SetReplicationStatusL( status );
       
   714         }
       
   715     
       
   716     /**
       
   717      * S60 settings for new entries
       
   718      */
       
   719     if ( IsCreatingNew() )
       
   720         {
       
   721         if ( Edited().EntryType() == CCalEntry::EAnniv )
       
   722             {
       
   723             TCalRRule rrule( TCalRRule::EYearly );
       
   724             rrule.SetDtStart( iEntry.StartTimeL() );
       
   725             rrule.SetInterval( 1 );
       
   726             rrule.SetCount( 0 );
       
   727             iEntry.SetRRuleL( rrule );
       
   728             }
       
   729         }
       
   730     
       
   731     // check for attachments
       
   732     if( isNew || IsAttachmentExists() )
       
   733         {
       
   734         // TODO: Uncomment this when enabling attachment support
       
   735         AddAttachementsToEntryL();
       
   736         }
       
   737     TRACE_EXIT_POINT;
       
   738     }
       
   739 
       
   740 // -----------------------------------------------------------------------------
       
   741 // CCalenEditorDataHandler::ApplyUntilDateToRRuleL
       
   742 // Applies an new until date to a rrule
       
   743 // (other items were commented in a header).
       
   744 // -----------------------------------------------------------------------------
       
   745 //
       
   746 void CCalenEditorDataHandler::ApplyUntilDateToRRuleL( TCalRRule& aRRule, const TTime& aRepeatUntil ) const
       
   747     {
       
   748     TRACE_ENTRY_POINT;
       
   749      // note repeat is set to forever.
       
   750     if ( ! CalenDateUtils::IsValidDay( aRepeatUntil ) || IsForeverDate( aRepeatUntil ) )
       
   751         {
       
   752         // Set repeat to forever:
       
   753         aRRule.SetCount( 0 );
       
   754         }
       
   755     else
       
   756         {
       
   757         // Change repeatuntil so that hours, minutes, ... are same as in start date
       
   758         TDateTime dtUntil = aRepeatUntil.DateTime();
       
   759         TDateTime dtStart= iEntry.StartTimeL().TimeLocalL().DateTime();
       
   760 
       
   761         dtUntil.Set( dtUntil.Year(), dtUntil.Month(), dtUntil.Day(),
       
   762                      dtStart.Hour(), dtStart.Minute(), dtStart.Second(), dtStart.MicroSecond() );
       
   763 
       
   764         TCalTime calRepeatUntil;
       
   765         if ( UseFloatingTimeL() )
       
   766             {
       
   767             calRepeatUntil.SetTimeLocalFloatingL( TTime( dtUntil ) );
       
   768             }
       
   769         else
       
   770             {
       
   771             calRepeatUntil.SetTimeLocalL( TTime( dtUntil ) );
       
   772             }
       
   773         aRRule.SetUntil( calRepeatUntil );
       
   774         }
       
   775     TRACE_EXIT_POINT;
       
   776     }
       
   777 // -----------------------------------------------------------------------------
       
   778 // CCalenEditorDataHandler::DurationGreaterThanRepeatIntervalError
       
   779 // Returns ETrue if the duration of instances of the meeting is greater than
       
   780 // the repeat period of the series, EFalse otherwise.
       
   781 // (other items were commented in a header).
       
   782 // -----------------------------------------------------------------------------
       
   783 //
       
   784 TBool CCalenEditorDataHandler::DurationGreaterThanRepeatIntervalError()
       
   785     {
       
   786     TRACE_ENTRY_POINT;
       
   787     TBool isError = EFalse;
       
   788     switch( Edited().RepeatType() )
       
   789         {
       
   790         case ERepeatDaily:
       
   791         case ERepeatWorkdays:
       
   792             {
       
   793             TTimeIntervalDays durDays = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() );
       
   794             isError = durDays >= TTimeIntervalDays(1);
       
   795             break;
       
   796             }
       
   797         case ERepeatWeekly:
       
   798             {
       
   799             TTimeIntervalDays durDays = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() );
       
   800             isError = durDays >= TTimeIntervalDays(7);
       
   801             break;
       
   802             }
       
   803         case ERepeatBiWeekly:
       
   804             {
       
   805             TTimeIntervalDays durDays = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() );
       
   806             isError = durDays >= TTimeIntervalDays(14);
       
   807             break;
       
   808             }
       
   809         case ERepeatMonthly:
       
   810             {
       
   811             TTimeIntervalMonths durMonths = Edited().EndDateTime().MonthsFrom( Edited().StartDateTime() );
       
   812             isError = durMonths >= TTimeIntervalMonths(1);
       
   813             break;
       
   814             }
       
   815         case ERepeatYearly:
       
   816             {
       
   817             TTimeIntervalYears durYears = Edited().EndDateTime().YearsFrom( Edited().StartDateTime() );
       
   818             isError = durYears >= TTimeIntervalYears(1);
       
   819             break;
       
   820             }
       
   821         case ERepeatOther:
       
   822 		    {
       
   823             isError = EFalse;
       
   824             break;
       
   825 			}
       
   826         default:
       
   827             // Not repeating, no error
       
   828             isError = EFalse;
       
   829             break;
       
   830         }
       
   831     TRACE_EXIT_POINT;
       
   832     return isError;
       
   833     }
       
   834 
       
   835 // -----------------------------------------------------------------------------
       
   836 // CCalenEditorDataHandler::CheckErrorsForThisAndAllL
       
   837 // Check for errors in the form. This function should only be called when the
       
   838 // user has decided they want to edit "This and all" from a prompt, or when the
       
   839 // entry is not repeating.
       
   840 // (other items were commented in a header).
       
   841 // -----------------------------------------------------------------------------
       
   842 //
       
   843 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckErrorsForThisAndAllL()
       
   844     {
       
   845     TRACE_ENTRY_POINT;
       
   846 
       
   847     // From UI spec:
       
   848     //   5 checks is specified, only one not needed in this phase is 2.1
       
   849 
       
   850     const TTime start = Edited().StartDateTime();
       
   851     const TTime end = Edited().EndDateTime();
       
   852 
       
   853     // 1) Check that entry doesn't end earlier than it starts
       
   854     if ( end < start )
       
   855         {
       
   856         TRACE_EXIT_POINT;
       
   857         return CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime;
       
   858         }
       
   859 
       
   860     // 2) Repeating entry checks:
       
   861     if ( Edited().IsRepeating() )
       
   862         {
       
   863         //    2.1) Check that repeat until date is a) later than start date (for new notes)
       
   864         //                                         b) not before start date (for existing notes)
       
   865         TTime repeatUntilDay = CalenDateUtils::BeginningOfDay(
       
   866             Edited().RepeatUntilDateTime() );
       
   867 
       
   868         TTime repeatStartDay;
       
   869 
       
   870         // if new note or old note isnt repeating
       
   871         //   edited.repeatUntil date must be greater than edited.start date
       
   872         // else
       
   873         //   if IsRepeatRuleEdited or IsStartDateTimeEdited 
       
   874         //     //(either one above will make a new rule in which edited.startdate is the start date)
       
   875         //     edited.repeatUntil must be greater than edited.start date
       
   876         //   else
       
   877         //     edited.repeatUntil must be greater than start date on disk
       
   878 
       
   879         TCalRRule rrule;
       
   880         if( IsCreatingNew() || 
       
   881             !Entry().GetRRuleL(rrule) ||
       
   882             IsRepeatRuleEdited() || 
       
   883             IsStartDateTimeEdited() )
       
   884             {
       
   885             // We don't have an rrule so we can't get the rrule start date,
       
   886             // or user has edited a field that will cause new start date to be used in the new rule.
       
   887             // Use the edited entry's start date.
       
   888             repeatStartDay = CalenDateUtils::BeginningOfDay( start );
       
   889             }
       
   890         else
       
   891             {
       
   892             // original rrule is valid and new rule will not be created
       
   893             repeatStartDay = CalenDateUtils::BeginningOfDay( rrule.DtStart().TimeLocalL() );
       
   894             }
       
   895 
       
   896         if ( repeatUntilDay <= repeatStartDay )
       
   897             {
       
   898             TRACE_EXIT_POINT;
       
   899             return CCalenEditorDataHandler::EFormErrRepeatUntilEarlierThanNote;
       
   900             }
       
   901 
       
   902         if( DurationGreaterThanRepeatIntervalError() )
       
   903             {
       
   904             TRACE_EXIT_POINT;
       
   905             return CCalenEditorDataHandler::EFormErrDurationGreaterThanRepeatInterval;
       
   906             }
       
   907         // 3) Alarm field checks:
       
   908         TRACE_EXIT_POINT;
       
   909         return CheckAlarmFieldsForErrorsL(ETrue); // user editing the series
       
   910         }
       
   911 
       
   912     // 3) Alarm field checks:
       
   913     TRACE_EXIT_POINT;
       
   914     return CheckAlarmFieldsForErrorsL(); // user editing the series
       
   915     }
       
   916 
       
   917 // -----------------------------------------------------------------------------
       
   918 // CCalenEditorDataHandler::CheckErrorsForThisOnlyL
       
   919 // Check for errors in the form. This function should only be called when the
       
   920 // user has decided they want to edit "This only" from a prompt, or when the
       
   921 // entry is an exception.
       
   922 // (other items were commented in a header).
       
   923 // -----------------------------------------------------------------------------
       
   924 //
       
   925 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckErrorsForThisOnlyL( CCalEntry& /*aParentEntry*/,
       
   926                                                                                   CCalInstanceView& /*aInstanceView*/ )
       
   927     {
       
   928     TRACE_ENTRY_POINT;
       
   929 
       
   930     const TTime start = Edited().StartDateTime();
       
   931     const TTime end = Edited().EndDateTime();
       
   932 
       
   933     // Check that entry doesn't end earlier than it starts
       
   934     if ( end < start )
       
   935         {
       
   936         TRACE_EXIT_POINT;
       
   937         return CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime;
       
   938         }
       
   939 
       
   940     TError error = CheckForOutOfSequenceL();
       
   941 
       
   942     if( error != EFormErrNone )
       
   943         {
       
   944         return error;
       
   945         }
       
   946 
       
   947     // Alarm field checks:
       
   948     TRACE_EXIT_POINT;
       
   949     return CheckAlarmFieldsForErrorsL(); // user creating/editing an exception
       
   950     }
       
   951 
       
   952 // -----------------------------------------------------------------------------
       
   953 // CCalenEditorDataHandler::CheckForOutOfSequenceL
       
   954 // Checks to see if the instance is being moved out of sequence, relative to
       
   955 // the rest of the series.
       
   956 // (other items were commented in a header).
       
   957 // -----------------------------------------------------------------------------
       
   958 //
       
   959 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckForOutOfSequenceL()
       
   960     {
       
   961     TRACE_ENTRY_POINT;
       
   962     // Only perform the checks when we change the start or end time of the meeting.
       
   963     if( !IsStartDateTimeEdited() && !IsEndDateTimeEdited() )
       
   964         {
       
   965         TRACE_EXIT_POINT;
       
   966         return EFormErrNone;
       
   967         }
       
   968 
       
   969     TCalTime prevStart, prevEnd;
       
   970 
       
   971     GetPreviousInstanceTimeL( prevStart, prevEnd );
       
   972 
       
   973     if( prevStart.TimeLocalL() != Time::NullTTime() )
       
   974         {
       
   975         // Does the exception end on/after prevEnd?
       
   976         if( Edited().StartDateTime() < prevEnd.TimeLocalL() )
       
   977             {
       
   978             // Does the exception start after prevStart?
       
   979             if( Edited().StartDateTime() > prevStart.TimeLocalL() )
       
   980                 {
       
   981                 TRACE_EXIT_POINT;
       
   982                 return EFormErrOverlapsExistingInstance;
       
   983                 }
       
   984             else
       
   985                 {
       
   986                 // Does the exception finish after prevStart?
       
   987                 if( Edited().EndDateTime() > prevStart.TimeLocalL() )
       
   988                     {
       
   989                     TRACE_EXIT_POINT;
       
   990                     return EFormErrOverlapsExistingInstance;
       
   991                     }
       
   992                 else
       
   993                     {
       
   994                     TRACE_EXIT_POINT;
       
   995                     return EFormErrOutOfSequence;
       
   996                     }
       
   997                 }
       
   998             }
       
   999 
       
  1000         // Does the exception start on the same day as prevStart?
       
  1001         if( CalenDateUtils::OnSameDay( Edited().StartDateTime(), prevStart.TimeLocalL() ) )
       
  1002             {
       
  1003             TRACE_EXIT_POINT;
       
  1004             return EFormErrInstanceAlreadyExistsOnThisDay;
       
  1005             }
       
  1006         }
       
  1007 
       
  1008     TCalTime nextStart, nextEnd;
       
  1009 
       
  1010     GetNextInstanceTimeL( nextStart, nextEnd );
       
  1011 
       
  1012     if( nextStart.TimeLocalL() != Time::NullTTime() )
       
  1013         {
       
  1014         // Does the exception finish on/before nextStart?
       
  1015         if( Edited().EndDateTime() > nextStart.TimeLocalL() )
       
  1016             {
       
  1017             // Does the exception finish before nextFinish?
       
  1018             if( Edited().EndDateTime() < nextEnd.TimeLocalL() )
       
  1019                 {
       
  1020                 TRACE_EXIT_POINT;
       
  1021                 return EFormErrOverlapsExistingInstance;
       
  1022                 }
       
  1023             else
       
  1024                 {
       
  1025                 // Does the exception start before nextFinish?
       
  1026                 if( Edited().StartDateTime() < nextEnd.TimeLocalL() )
       
  1027                     {
       
  1028                     TRACE_EXIT_POINT;
       
  1029                     return EFormErrOverlapsExistingInstance;
       
  1030                     }
       
  1031                 else
       
  1032                     {
       
  1033                     TRACE_EXIT_POINT;
       
  1034                     return EFormErrOutOfSequence;
       
  1035                     }
       
  1036                 }
       
  1037             }
       
  1038 
       
  1039         // Does the exception start on the same day as nextStart?
       
  1040         if( CalenDateUtils::OnSameDay( Edited().StartDateTime(), nextStart.TimeLocalL() ) )
       
  1041             {
       
  1042             TRACE_EXIT_POINT;
       
  1043             return EFormErrInstanceAlreadyExistsOnThisDay;
       
  1044             }
       
  1045         }
       
  1046 
       
  1047     // Does the series have any rdates
       
  1048     RArray<TCalTime> rDateArray;
       
  1049     CleanupClosePushL( rDateArray );
       
  1050     Entry().GetRDatesL( rDateArray );
       
  1051     TInt rDateCount = rDateArray.Count();
       
  1052 
       
  1053     if ( rDateCount > 0 )
       
  1054         {
       
  1055         // If the series has rdates, check that the exception
       
  1056         // does not overlap or start on the same day
       
  1057         const TTime& startDateTime = Edited().StartDateTime();
       
  1058         const TTime& endDateTime = Edited().EndDateTime();
       
  1059         TTimeIntervalMinutes duration;
       
  1060         startDateTime.MinutesFrom( endDateTime, duration );
       
  1061 
       
  1062         for ( TInt index = 0; index < rDateCount; index++ )
       
  1063             {
       
  1064             const TTime& rDate = rDateArray[ index ].TimeLocalL();
       
  1065 
       
  1066             if ( !CalenDateUtils::OnSameDay( Original().StartDateTime(), rDate ) )
       
  1067                 {
       
  1068                 // Does the exception start or end on the same day as a rdate.
       
  1069                 if ( CalenDateUtils::OnSameDay( startDateTime, rDate ) )
       
  1070                     {
       
  1071                     CleanupStack::PopAndDestroy(); // rDateArray
       
  1072                     TRACE_EXIT_POINT;
       
  1073                     return EFormErrInstanceAlreadyExistsOnThisDay;
       
  1074                     }
       
  1075 
       
  1076                 // Does the exception overlap an rdate?
       
  1077                 TTime rDateEnd = rDate + duration;
       
  1078                 if ( endDateTime > rDateEnd && startDateTime < rDate )
       
  1079                     {
       
  1080                     CleanupStack::PopAndDestroy(); // rDateArray
       
  1081                     TRACE_EXIT_POINT;
       
  1082                     return EFormErrOverlapsExistingInstance;
       
  1083                     }
       
  1084                 }
       
  1085             }
       
  1086         }
       
  1087 
       
  1088     CleanupStack::PopAndDestroy(); // rDateArray
       
  1089     TRACE_EXIT_POINT;
       
  1090     return EFormErrNone;
       
  1091     }
       
  1092 
       
  1093 // -----------------------------------------------------------------------------
       
  1094 // CCalenEditorDataHandler::GetPreviousInstanceTimeL
       
  1095 // Gets the start and end times of the previous instance. Sets both to a null
       
  1096 // time if there is no instance before the current one
       
  1097 // (other items were commented in a header).
       
  1098 // -----------------------------------------------------------------------------
       
  1099 //
       
  1100 void CCalenEditorDataHandler::GetPreviousInstanceTimeL( TCalTime& aPreviousStartTime,
       
  1101                                                         TCalTime& aPreviousEndTime )
       
  1102     {
       
  1103     TRACE_ENTRY_POINT;
       
  1104 
       
  1105     aPreviousStartTime.SetTimeLocalL( Time::NullTTime() );
       
  1106     aPreviousEndTime.SetTimeLocalL( Time::NullTTime() );
       
  1107 
       
  1108     RPointerArray<CCalEntry> entries;
       
  1109     CleanupResetAndDestroyPushL(entries);
       
  1110 
       
  1111     EntryViewL().FetchL( Entry().UidL(), entries );
       
  1112 
       
  1113     TCalTime currentInstanceDate = Entry().RecurrenceIdL();
       
  1114     if( currentInstanceDate.TimeUtcL() == Time::NullTTime() )
       
  1115         {
       
  1116         // We must be creating a new exception. Calculate the recurrence id.
       
  1117         TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( entries[0]->StartTimeL().TimeLocalL() );
       
  1118         TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1119         currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1120         }
       
  1121 
       
  1122     TCalRRule rrule;
       
  1123     if( entries[0]->GetRRuleL(rrule) )
       
  1124         {
       
  1125         TCalenRepeatIndex repeatIndex = CalenNoteDataUtil::RepeatIndexL( *entries[0] );
       
  1126         TBool keepLooking = ETrue;
       
  1127         RArray<TCalTime> exdates;
       
  1128         CleanupClosePushL( exdates );
       
  1129         entries[0]->GetExceptionDatesL(exdates);
       
  1130         
       
  1131         // Needed for case ERepeatOther
       
  1132         TCalRRule::TType type( rrule.Type() );
       
  1133         TInt repeatInterval( rrule.Interval() );
       
  1134         TCalTime start, end;
       
  1135         TTime previousInstanceTime = Time::NullTTime(); 
       
  1136         
       
  1137         while( keepLooking )
       
  1138             {
       
  1139             // Subtract the repeat interval of the parent.
       
  1140             switch( repeatIndex )
       
  1141                 {
       
  1142                 case ERepeatDaily:
       
  1143                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(1) );
       
  1144                     break;
       
  1145                 case ERepeatWeekly:
       
  1146                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7) );
       
  1147                     break;
       
  1148                 case ERepeatBiWeekly:
       
  1149                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(14) );
       
  1150                     break;
       
  1151                 case ERepeatMonthly:
       
  1152                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalMonths(1) );
       
  1153                     break;
       
  1154                 case ERepeatYearly:
       
  1155                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalYears(1) );
       
  1156                     break;
       
  1157                 case ERepeatWorkdays:
       
  1158                     currentInstanceDate.SetTimeLocalL(currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7) );
       
  1159                 case ERepeatOther:
       
  1160                 	/* This case includes repeating events like: 3 days every week, 3rd weekday of everymonth
       
  1161                 	   that does not fall in any cases above but still have repeating rule*/
       
  1162                 	   
       
  1163                 	 // Check if the current entry being edited is child entry
       
  1164           			 // If yes, then put back the child entry time to currentInstanceDate  
       
  1165 				     if(Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime() )
       
  1166                 	 	{
       
  1167                 	 	 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( Entry().StartTimeL().TimeLocalL() );
       
  1168         				 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1169         				 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1170                 	 	}
       
  1171              
       
  1172                 	 switch( type )
       
  1173                 	 {
       
  1174                 	 	case TCalRRule::EDaily:
       
  1175                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(1 * repeatInterval));
       
  1176                 	 		break;
       
  1177                 	 	case TCalRRule::EWeekly:
       
  1178                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7 * repeatInterval));
       
  1179                 	 		break;
       
  1180                 	 	case TCalRRule::EMonthly: 
       
  1181                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1182                 	 		// can go beuong 30 days. Ex: Every third wednesday of every month 
       
  1183                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalMonths(repeatInterval)-TTimeIntervalDays(7 * repeatInterval));
       
  1184                 	 		break;
       
  1185                 	 	case TCalRRule::EYearly:  
       
  1186                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1187                 	 		// can go beuong 365 days. Ex: Every third wednesday of September of every year
       
  1188                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalYears(repeatInterval)-TTimeIntervalDays(7 * repeatInterval));
       
  1189                 	 		break;
       
  1190                 	 }
       
  1191                 	 
       
  1192                 	 end.SetTimeLocalL(CalenDateUtils::BeginningOfDay(currentInstanceDate.TimeLocalL()));
       
  1193                      previousInstanceTime = GetPreviousInstanceForRepeatOtherL(*entries[0], CalCommon::TCalTimeRange( start, end));
       
  1194                      currentInstanceDate.SetTimeLocalL( previousInstanceTime);
       
  1195                      break;
       
  1196                 default:
       
  1197                 case ERepeatNotRepeated:
       
  1198                     keepLooking = EFalse;
       
  1199                     break;
       
  1200                 }
       
  1201 
       
  1202             // Is currentInstanceDate before parent dt start?
       
  1203             if( currentInstanceDate.TimeLocalL() < entries[0]->StartTimeL().TimeLocalL() )
       
  1204                 {
       
  1205                 // There are no instances before the exception
       
  1206                 keepLooking = EFalse;
       
  1207                 }
       
  1208             else
       
  1209                 {
       
  1210                 // Is there an exdate on currentInstanceDate?
       
  1211                 TBool isExdateOnDay = EFalse;
       
  1212                 for(TInt i=0; i<exdates.Count(); ++i)
       
  1213                     {
       
  1214                     if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1215                         {
       
  1216                         isExdateOnDay = ETrue;
       
  1217                         // There is an exdate - is there a child associated with the exdate?
       
  1218                         for(TInt j=1; j<entries.Count(); ++j)
       
  1219                             {
       
  1220                             if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1221                                 {
       
  1222                                 // This child is the previous instance.
       
  1223                                 aPreviousStartTime = entries[j]->StartTimeL();
       
  1224                                 aPreviousEndTime = entries[j]->EndTimeL();
       
  1225                                 keepLooking = EFalse;
       
  1226                                 }
       
  1227                             }
       
  1228                         break;
       
  1229                         }
       
  1230                     }
       
  1231 
       
  1232                 if( !isExdateOnDay )
       
  1233                     {
       
  1234                     // The instance exists and hasn't been deleted or made into an exception.
       
  1235                     // Use information from the parent to set the start/end times.
       
  1236                     aPreviousStartTime = currentInstanceDate;
       
  1237 
       
  1238                     TTimeIntervalMinutes duration;
       
  1239                     TTime start = entries[0]->StartTimeL().TimeLocalL();
       
  1240                     TTime end = entries[0]->EndTimeL().TimeLocalL(); 
       
  1241                     end.MinutesFrom( start, duration );
       
  1242                     aPreviousEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration );
       
  1243                     keepLooking = EFalse;
       
  1244                     }
       
  1245                 }
       
  1246             }
       
  1247         CleanupStack::PopAndDestroy( &exdates );
       
  1248         }
       
  1249 
       
  1250     CleanupStack::PopAndDestroy(&entries);
       
  1251 
       
  1252     TRACE_EXIT_POINT;
       
  1253     }
       
  1254 
       
  1255 // -----------------------------------------------------------------------------
       
  1256 // CCalenEditorDataHandler::GetNextInstanceTimeL
       
  1257 // Gets the start and end times of the next instance. Sets both to a null
       
  1258 // time if there is no instance after the current one.
       
  1259 // (other items were commented in a header).
       
  1260 // -----------------------------------------------------------------------------
       
  1261 //
       
  1262 void CCalenEditorDataHandler::GetNextInstanceTimeL( TCalTime& aNextStartTime,
       
  1263                                                     TCalTime& aNextEndTime )
       
  1264     {
       
  1265     TRACE_ENTRY_POINT;
       
  1266 
       
  1267     aNextStartTime.SetTimeLocalL( Time::NullTTime() );
       
  1268     aNextEndTime.SetTimeLocalL( Time::NullTTime() );
       
  1269 
       
  1270     RPointerArray<CCalEntry> entries;
       
  1271     CleanupResetAndDestroyPushL(entries);
       
  1272 
       
  1273     EntryViewL().FetchL( Entry().UidL(), entries );
       
  1274 
       
  1275     TCalTime currentInstanceDate = Entry().RecurrenceIdL();
       
  1276     if( currentInstanceDate.TimeUtcL() == Time::NullTTime() )
       
  1277         {
       
  1278         // We must be creating a new exception. Calculate the recurrence id.
       
  1279         TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( entries[0]->StartTimeL().TimeLocalL() );
       
  1280         TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1281         currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1282         }
       
  1283 
       
  1284     TCalRRule rrule;
       
  1285     if( entries[0]->GetRRuleL(rrule) )
       
  1286         {
       
  1287         TCalenRepeatIndex repeatIndex = CalenNoteDataUtil::RepeatIndexL( *entries[0] );
       
  1288         TBool keepLooking = ETrue;
       
  1289         RArray<TCalTime> exdates;
       
  1290         CleanupClosePushL( exdates );
       
  1291         entries[0]->GetExceptionDatesL(exdates);
       
  1292         
       
  1293         // Needed for case ERepeatOther
       
  1294         TCalRRule::TType type( rrule.Type() );
       
  1295         TInt repeatInterval( rrule.Interval() );
       
  1296         TCalTime start, end;
       
  1297         TTime nextInstanceTime = Time::NullTTime(); 
       
  1298         
       
  1299         while( keepLooking )
       
  1300             {
       
  1301             // Subtract the repeat interval of the parent.
       
  1302             switch( repeatIndex )
       
  1303                 {
       
  1304                 case ERepeatDaily:
       
  1305                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1) );
       
  1306                     break;
       
  1307                 case ERepeatWeekly:
       
  1308                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7) );
       
  1309                     break;
       
  1310                 case ERepeatBiWeekly:
       
  1311                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(14) );
       
  1312                     break;
       
  1313                 case ERepeatMonthly:
       
  1314                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalMonths(1) );
       
  1315                     break;
       
  1316                 case ERepeatYearly:
       
  1317                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalYears(1) );
       
  1318                     break;
       
  1319                 case ERepeatWorkdays:
       
  1320                     currentInstanceDate.SetTimeLocalL(currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7) );
       
  1321                     break;
       
  1322                 case ERepeatOther:
       
  1323                     {
       
  1324                 	/* This case includes repeating events like: 3 days every week, 3rd weekday of everymonth
       
  1325                 	   that does not fall in any cases above but still have repeating rule*/
       
  1326           			 
       
  1327           			 // Check if the current entry being edited is child entry
       
  1328           			 // If yes, then put back the child entry time to currentInstanceDate
       
  1329 				     if(Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime())
       
  1330                 	 	{
       
  1331                 	 	 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( Entry().StartTimeL().TimeLocalL() );
       
  1332         				 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1333         				 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1334                 	 	}
       
  1335                 	 switch( type )
       
  1336                 	     {
       
  1337                 	 	case TCalRRule::EDaily:
       
  1338                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1 * repeatInterval));
       
  1339                 	 		break;
       
  1340                 	 	case TCalRRule::EWeekly:
       
  1341                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7 * repeatInterval));
       
  1342                 	 		break;
       
  1343                 	 	case TCalRRule::EMonthly:  
       
  1344                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1345                 	 		// can go beuong 30 days. Ex: Every third wednesday of every month
       
  1346                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalMonths(repeatInterval)+TTimeIntervalDays(7 * repeatInterval));
       
  1347                 	 		break;
       
  1348                 	 	case TCalRRule::EYearly:  
       
  1349                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1350                 	 		// can go beuong 365 days. Ex: Every third wednesday of September of every year
       
  1351                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalYears(repeatInterval)+TTimeIntervalDays(7 * repeatInterval));
       
  1352                 	 		break;
       
  1353                 	     }
       
  1354                 	 
       
  1355                 	 start.SetTimeLocalL(CalenDateUtils::BeginningOfDay(currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1)));
       
  1356                 	 
       
  1357                      nextInstanceTime = GetNextInstanceForRepeatOtherL(*entries[0], CalCommon::TCalTimeRange( start, end));
       
  1358                      currentInstanceDate.SetTimeLocalL( nextInstanceTime);
       
  1359                      break;
       
  1360                     }
       
  1361                 case ERepeatNotRepeated:
       
  1362                     keepLooking = EFalse;
       
  1363                     break;
       
  1364                 default:
       
  1365                     break;
       
  1366                 }
       
  1367 
       
  1368             // Is currentInstanceDate after parent dt end?
       
  1369             if( currentInstanceDate.TimeLocalL() > rrule.Until().TimeLocalL() )
       
  1370                 {
       
  1371                 // There are no instances before the exception
       
  1372                 keepLooking = EFalse;
       
  1373                 }
       
  1374             else
       
  1375                 {
       
  1376                 // Is there an exdate on currentInstanceDate?
       
  1377                 TBool isExdateOnDay = EFalse;
       
  1378                 for(TInt i=0; i<exdates.Count(); ++i)
       
  1379                     {
       
  1380                     if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1381                         {
       
  1382                         isExdateOnDay = ETrue;
       
  1383                         // There is an exdate - is there a child associated with the exdate?
       
  1384                         for(TInt j=1; j<entries.Count(); ++j)
       
  1385                             {
       
  1386                             if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1387                                 {
       
  1388                                 // This child is the previous instance.
       
  1389                                 aNextStartTime = entries[j]->StartTimeL();
       
  1390                                 aNextEndTime = entries[j]->EndTimeL();
       
  1391                                 keepLooking = EFalse;
       
  1392                                 }
       
  1393                             }
       
  1394                         break;
       
  1395                         }
       
  1396                     }
       
  1397                 
       
  1398                 if( !isExdateOnDay )
       
  1399                     {
       
  1400                     // The instance exists and hasn't been deleted or made into an exception.
       
  1401                     // Use information from the parent to set the start/end times.
       
  1402                     aNextStartTime = currentInstanceDate;
       
  1403 
       
  1404                     TTimeIntervalMinutes duration;
       
  1405                     TTime start = entries[0]->StartTimeL().TimeLocalL();
       
  1406                     TTime end = entries[0]->EndTimeL().TimeLocalL();
       
  1407                     end.MinutesFrom( start, duration );
       
  1408                     aNextEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration );
       
  1409                     keepLooking = EFalse;
       
  1410                     }
       
  1411                 }
       
  1412             }
       
  1413         CleanupStack::PopAndDestroy( &exdates );
       
  1414         }
       
  1415 
       
  1416     CleanupStack::PopAndDestroy(&entries);
       
  1417 
       
  1418     TRACE_EXIT_POINT;
       
  1419     }
       
  1420 
       
  1421 // -----------------------------------------------------------------------------
       
  1422 // CCalenEditorDataHandler::CheckAlarmFieldsForErrorsL
       
  1423 // Check the alarm fields for errors. Returns the error if found, or
       
  1424 // EFormErrNone if no error found.
       
  1425 // (other items were commented in a header).
       
  1426 // -----------------------------------------------------------------------------
       
  1427 //
       
  1428 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckAlarmFieldsForErrorsL(TBool aSeries)
       
  1429     {
       
  1430     TRACE_ENTRY_POINT;
       
  1431 
       
  1432     TError error = EFormErrNone;
       
  1433     // If alarm not active, no check
       
  1434     if ( Edited().IsAlarmActivated() )
       
  1435         {
       
  1436         TTime alarm     = Edited().AlarmDateTime();
       
  1437         TTime startTime = Edited().StartDateTime();
       
  1438         TTime now(Time::NullTTime());
       
  1439         now.HomeTime();
       
  1440 
       
  1441         if(IsAlarmInAcceptablePeriod(error, alarm, startTime))
       
  1442             {
       
  1443             // ask form (not iEntry) if it is repeating
       
  1444             // if we launched an old exception, then form has no repeat field
       
  1445             // if creating a new exception, then form has repeat field
       
  1446             TBool EventIsInFuture = (IsTimedEntry() && (startTime > now)) ||
       
  1447                                     (!IsTimedEntry() && (startTime.DaysFrom(now) >= TTimeIntervalDays(0)));
       
  1448             if( !aSeries && (alarm < now) && ( iEdited->EntryType()!=CCalEntry::EAnniv ) )
       
  1449                 {
       
  1450                 // dont let non-repeating future entries have alarms in past
       
  1451             	error = EFormErrAlarmTimePast;
       
  1452                 }
       
  1453             /*  otherwise, save alarm to past:
       
  1454              *   new/old non-repeating & in past
       
  1455              *  repeating new/old repeating in past/future
       
  1456              */
       
  1457             }
       
  1458         }
       
  1459 
       
  1460     TRACE_EXIT_POINT;
       
  1461     return error;
       
  1462     }
       
  1463 
       
  1464 // -----------------------------------------------------------------------------
       
  1465 // CCalenEditorDataHandler::IsAlarmInAcceptablePeriod
       
  1466 // Check alarm time validity
       
  1467 // (other items were commented in a header).
       
  1468 // -----------------------------------------------------------------------------
       
  1469 //
       
  1470 TBool CCalenEditorDataHandler::IsAlarmInAcceptablePeriod(TError& aError, 
       
  1471 const TTime& aAlarmTime, const TTime& aStartTime) const
       
  1472     {
       
  1473     TRACE_ENTRY_POINT;
       
  1474 
       
  1475     TTime upperLimit = IsTimedEntry() ? 
       
  1476                        aStartTime : 
       
  1477                        CalenDateUtils::BeginningOfDay(aStartTime) + TTimeIntervalDays(1);
       
  1478     TTime lowerLimit = aStartTime - TTimeIntervalDays(31);
       
  1479     TBool acceptable = ETrue;
       
  1480     if(aAlarmTime < lowerLimit)
       
  1481         {
       
  1482         acceptable = EFalse;
       
  1483         aError = EFormErrAlarmDateTooManyDaysBeforeNote;
       
  1484         }
       
  1485     else if(aAlarmTime > upperLimit)
       
  1486         {
       
  1487         acceptable = EFalse;
       
  1488         aError = EFormErrAlarmTimeLaterThanNote;
       
  1489         }
       
  1490 
       
  1491     TRACE_EXIT_POINT;
       
  1492     return acceptable;
       
  1493     }
       
  1494 
       
  1495 // -----------------------------------------------------------------------------
       
  1496 // CCalenEditorDataHandler::ForceValidValuesL
       
  1497 // Force the form to use valid values. This function gets called when the user
       
  1498 // forces the application to exit, for example by pressing the off button.
       
  1499 // We attempt to save as much data as possible from the form.
       
  1500 // (other items were commented in a header).
       
  1501 // -----------------------------------------------------------------------------
       
  1502 //
       
  1503 void CCalenEditorDataHandler::ForceValidValuesL( CalCommon::TRecurrenceRange aRepeatTarget )
       
  1504     {
       
  1505     TRACE_ENTRY_POINT;
       
  1506 
       
  1507     // Checks and valid values are
       
  1508     // from S60 Calendar UI spec, chapter 4.6.4.1 Exiting Note Editor:
       
  1509 
       
  1510     // We modify values as we go, thus we can't pre-read fields.
       
  1511     // E.g. when start time is needed in check, it should be always read
       
  1512     // from model, because previous check might have modified it.
       
  1513 
       
  1514     //  2) if ends earlier than starts
       
  1515     if ( Edited().EndDateTime() < Edited().StartDateTime() )
       
  1516         {
       
  1517         //  a) (for new entry) set end time equal to start time
       
  1518         if ( IsCreatingNew() )
       
  1519             {
       
  1520             Edited().SetEndDateTimeL( Edited().StartDateTime() );
       
  1521             }
       
  1522         //  b) (for existing entries) replace with original end time
       
  1523         else
       
  1524             {
       
  1525             Edited().SetEndDateTimeL( Original().EndDateTime() );
       
  1526             // if still wrong, replace start time also
       
  1527             Edited().SetStartDateTimeL( Original().StartDateTime() );
       
  1528             }
       
  1529         } // END end < start check
       
  1530 
       
  1531     // 1) Alarm validation
       
  1532     if ( Edited().IsAlarmActivated() )
       
  1533         {
       
  1534         TTime now;
       
  1535         now.HomeTime();
       
  1536 
       
  1537         // Note: all three checks are done for each alarm.
       
  1538         // Alarm time is read always again, because modifications are done after each check
       
  1539 
       
  1540         //  1.1) a) if alarm more than 31 days before start, alarm is set 31 days before start
       
  1541         //       b) (for todos) - "" - before due date
       
  1542         TTime maxAlarmBeforeStart = Edited().StartDateTime() - TTimeIntervalDays( 31 );
       
  1543         if ( Edited().AlarmDateTime() < maxAlarmBeforeStart  )
       
  1544             {
       
  1545             Edited().SetAlarmDateTimeL( maxAlarmBeforeStart );
       
  1546             }
       
  1547 
       
  1548         //  1.2) a) (meetings) if alarm later than start, set it to default alarm time
       
  1549         //       b) (for todos & annivs) - "" - later than due date
       
  1550         TTime atLatest = Edited().StartDateTime();
       
  1551         if(!IsTimedEntry())
       
  1552             {
       
  1553             atLatest += TTimeIntervalDays(1); 
       
  1554             atLatest -= TTimeIntervalSeconds(1);
       
  1555             // at Latest for ToDo/Anniv would be DD @ 23:59:59
       
  1556             }
       
  1557         if( Edited().AlarmDateTime() > atLatest )
       
  1558             {            
       
  1559             SetDefaultAlarmDateTimeL();
       
  1560             }
       
  1561 
       
  1562         //  1.3) if alarm is set to passed time,
       
  1563         if ( Edited().AlarmDateTime() < now )
       
  1564             {
       
  1565             // a) it is set off for
       
  1566             //    - new/old NON-REPEATING entries
       
  1567             if (!Edited().IsRepeating() && Edited().EntryType() != CCalEntry::EAnniv )
       
  1568                 {
       
  1569                 Edited().SetAlarmOffL();
       
  1570                 }
       
  1571             // b) (for existing entries) it is saved, unless it has failed 1.1 or 1.2
       
  1572             else
       
  1573                 {
       
  1574                 // keep, if it is repeating entry, since repeating entries 
       
  1575                 // can have alarms in past
       
  1576                 }
       
  1577             }
       
  1578         } // END alarm checks
       
  1579 
       
  1580     //  3) Repeat rule checks
       
  1581     if ( Edited().IsRepeating() )
       
  1582         {
       
  1583         // if repeating note's repeat until date
       
  1584         // a) (for new entries)  isn't one day later than start date
       
  1585         // b) (for existing entries) is before start date
       
  1586         // set it to one year later from start date
       
  1587         TTime repeatUntilDay = CalenDateUtils::BeginningOfDay(
       
  1588             Edited().RepeatUntilDateTime() );
       
  1589         TTime startDay = CalenDateUtils::BeginningOfDay( Edited().StartDateTime() );
       
  1590         if ( (  IsCreatingNew() && repeatUntilDay <= startDay) ||
       
  1591              (! IsCreatingNew() && repeatUntilDay < startDay) )
       
  1592             {
       
  1593             Edited().SetRepeatUntilDateTimeL( startDay + TTimeIntervalYears(1) );
       
  1594             }
       
  1595         }
       
  1596 
       
  1597     //  4) if due date of todo is passed or invalid, save it with entered date
       
  1598     // no operation (this is just clarification in UI spec
       
  1599 
       
  1600 
       
  1601     //  5) Check for out of sequence for exceptions
       
  1602     //  6) Check for duration > rpt interval for series
       
  1603     
       
  1604     if( aRepeatTarget == CalCommon::EThisOnly )
       
  1605         {
       
  1606         TError error = CheckForOutOfSequenceL();
       
  1607 
       
  1608         if( error != EFormErrNone )
       
  1609             {
       
  1610             // Revert start/end times
       
  1611             Edited().SetStartDateTimeL( Original().StartDateTime() );
       
  1612             Edited().SetEndDateTimeL( Original().EndDateTime() );
       
  1613             }
       
  1614         }
       
  1615     else if( aRepeatTarget == CalCommon::EThisAndAll )
       
  1616         {
       
  1617         if( DurationGreaterThanRepeatIntervalError() )
       
  1618             {
       
  1619             // Revert start/end times
       
  1620             Edited().SetStartDateTimeL( Original().StartDateTime() );
       
  1621             Edited().SetEndDateTimeL( Original().EndDateTime() );
       
  1622             }
       
  1623         }
       
  1624 
       
  1625     TRACE_EXIT_POINT;
       
  1626     }
       
  1627 
       
  1628 // -----------------------------------------------------------------------------
       
  1629 // CCalenEditorDataHandler::IsOldEntry
       
  1630 // Returns ETrue if the entry was already created previously so that
       
  1631 // we are now editing it, returns EFalse otherwise.
       
  1632 // (other items were commented in a header).
       
  1633 // -----------------------------------------------------------------------------
       
  1634 //
       
  1635 TBool CCalenEditorDataHandler::IsOldEntry()
       
  1636     {
       
  1637     TRACE_ENTRY_POINT;
       
  1638 
       
  1639     TRACE_EXIT_POINT;
       
  1640     return !IsCreatingNew();
       
  1641     }
       
  1642 
       
  1643 // -----------------------------------------------------------------------------
       
  1644 // CCalenEditorDataHandler::AreTextFieldsEmptyL
       
  1645 // Returns ETrue if summary && location && description text fields are all empty
       
  1646 // Returns EFalse otherwise.
       
  1647 // (other items were commented in a header).
       
  1648 // -----------------------------------------------------------------------------
       
  1649 //
       
  1650 TBool CCalenEditorDataHandler::AreTextFieldsEmptyL()
       
  1651     {
       
  1652     TRACE_ENTRY_POINT;
       
  1653 
       
  1654     // We have to consider texts empty, if only summary is empty, in case
       
  1655     // location is not supported, because location can still exists in database.
       
  1656     TBool summaryAndDescriptionEmpty = CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) && 
       
  1657     CalenAgendaUtils::IsEmptyText( iEdited->Description() );
       
  1658 
       
  1659     if(LocationEnabledInUiL())
       
  1660         {
       
  1661         TRACE_EXIT_POINT;
       
  1662         return summaryAndDescriptionEmpty && CalenAgendaUtils::IsEmptyText( iEdited->Location() );        
       
  1663         }
       
  1664     
       
  1665     TRACE_EXIT_POINT;
       
  1666 
       
  1667     return summaryAndDescriptionEmpty; // and location is empty implicitly
       
  1668     }
       
  1669 
       
  1670 // -----------------------------------------------------------------------------
       
  1671 // CCalenEditorDataHandler::AreTextFieldsClearedL
       
  1672 // Returns ETrue if the user cleared the text in the location and summary fields.
       
  1673 // (other items were commented in a header).
       
  1674 // -----------------------------------------------------------------------------
       
  1675 //
       
  1676 TBool CCalenEditorDataHandler::AreTextFieldsClearedL()
       
  1677     {
       
  1678     TRACE_ENTRY_POINT;
       
  1679 
       
  1680     if ( CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) &&
       
  1681         CalenAgendaUtils::IsEmptyText( iEdited->Description() ) )
       
  1682         {
       
  1683         if ( LocationEnabledInUiL() )
       
  1684             {
       
  1685             if ( CalenAgendaUtils::IsEmptyText( iEdited->Location() ) )
       
  1686                 {
       
  1687                 if ( IsSummaryEmptied() || IsDescriptionEmptied() || IsLocationEmptied() )
       
  1688                     {
       
  1689                     TRACE_EXIT_POINT;
       
  1690                     return ETrue;
       
  1691                     }
       
  1692                 }
       
  1693             }
       
  1694 
       
  1695         else if ( IsSummaryEmptied() || IsDescriptionEmptied() )
       
  1696             {
       
  1697             TRACE_EXIT_POINT;
       
  1698             return ETrue;
       
  1699             }
       
  1700         }
       
  1701 
       
  1702     TRACE_EXIT_POINT;
       
  1703 
       
  1704     return EFalse;
       
  1705     }
       
  1706 
       
  1707 // -----------------------------------------------------------------------------
       
  1708 // CCalenEditorDataHandler::IsDescriptionEmptied
       
  1709 // Returns ETrue, the description was not empty in original && is empty
       
  1710 // in the edited note
       
  1711 // Returns EFalse, otherwise
       
  1712 // (other items were commented in a header).
       
  1713 // -----------------------------------------------------------------------------
       
  1714 TBool CCalenEditorDataHandler::IsDescriptionEmptied()
       
  1715     {
       
  1716     TRACE_ENTRY_POINT;
       
  1717 
       
  1718     if( !CalenAgendaUtils::IsEmptyText( iOriginal->Description() ) &&
       
  1719         CalenAgendaUtils::IsEmptyText( iEdited->Description() ) )
       
  1720         {
       
  1721         TRACE_EXIT_POINT;
       
  1722         return ETrue;
       
  1723         }
       
  1724 
       
  1725     TRACE_EXIT_POINT;
       
  1726 
       
  1727     return EFalse;
       
  1728     }
       
  1729 
       
  1730 // -----------------------------------------------------------------------------
       
  1731 // CCalenEditorDataHandler::IsSummaryEmptied
       
  1732 // Returns ETrue, the summary was not empty in original && is empty
       
  1733 // in the edited note
       
  1734 // Returns EFalse, otherwise
       
  1735 // (other items were commented in a header).
       
  1736 // -----------------------------------------------------------------------------
       
  1737 TBool CCalenEditorDataHandler::IsSummaryEmptied()
       
  1738     {
       
  1739     TRACE_ENTRY_POINT;
       
  1740 
       
  1741     if( !CalenAgendaUtils::IsEmptyText( iOriginal->Summary() ) &&
       
  1742         CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) )
       
  1743         {
       
  1744         TRACE_EXIT_POINT;
       
  1745         return ETrue;
       
  1746         }
       
  1747 
       
  1748     TRACE_EXIT_POINT;
       
  1749     return EFalse;
       
  1750     }
       
  1751 
       
  1752 // -----------------------------------------------------------------------------
       
  1753 // CCalenEditorDataHandler::IsLocationEmptied
       
  1754 // Returns ETrue, the summary was not empty in original && is empty
       
  1755 // in the edited note
       
  1756 // Returns EFalse, otherwise
       
  1757 // (other items were commented in a header).
       
  1758 // -----------------------------------------------------------------------------
       
  1759 TBool CCalenEditorDataHandler::IsLocationEmptied()
       
  1760     {
       
  1761     TRACE_ENTRY_POINT;
       
  1762 
       
  1763     if( !CalenAgendaUtils::IsEmptyText( iOriginal->Location() ) &&
       
  1764         CalenAgendaUtils::IsEmptyText( iEdited->Location() ) )
       
  1765         {
       
  1766         TRACE_EXIT_POINT;
       
  1767         return ETrue;
       
  1768         }
       
  1769 
       
  1770     TRACE_EXIT_POINT;
       
  1771     return EFalse;
       
  1772     }
       
  1773 
       
  1774 // -----------------------------------------------------------------------------
       
  1775 // CCalenEditorDataHandler::IsEntryTypeEdited
       
  1776 // Returns ETrue if the 'Entry Type' is edited, EFalse otherwise.
       
  1777 // (other items were commented in a header).
       
  1778 // -----------------------------------------------------------------------------
       
  1779 //
       
  1780 TBool CCalenEditorDataHandler::IsEntryTypeEdited()
       
  1781     {
       
  1782     TRACE_ENTRY_POINT;
       
  1783 
       
  1784     TRACE_EXIT_POINT;
       
  1785     return iOriginal->EntryType() != iEdited->EntryType();
       
  1786     }
       
  1787 
       
  1788 // -----------------------------------------------------------------------------
       
  1789 // CCalenEditorDataHandler::IsStartDateTimeEdited
       
  1790 // Returns ETrue if the start date/time has been edited, EFalse otherwise.
       
  1791 // (other items were commented in a header).
       
  1792 // -----------------------------------------------------------------------------
       
  1793 //
       
  1794 TBool CCalenEditorDataHandler::IsStartDateTimeEdited()
       
  1795     {
       
  1796     TRACE_ENTRY_POINT;
       
  1797     
       
  1798     TBool isEdited = EFalse;
       
  1799     
       
  1800     TTime orgTTime = iOriginal->StartDateTime();
       
  1801     TTime editedTTime = iEdited->StartDateTime();
       
  1802     
       
  1803     // Get TDateTime of Original & Edited entries.
       
  1804     TDateTime orgDT = orgTTime.DateTime();
       
  1805     TDateTime editedDT = editedTTime.DateTime();
       
  1806     
       
  1807     if( !IsTimedEntry() && IsCreatingNew() )
       
  1808         {
       
  1809         // For non-timed event,on while creating new entry.
       
  1810         // check for only Date field change only.
       
  1811         if( orgDT.Day() != editedDT.Day() ||
       
  1812                 orgDT.Month() != editedDT.Month() ||
       
  1813                 orgDT.Year() != editedDT.Year() )
       
  1814             {
       
  1815             isEdited = ETrue;
       
  1816             }
       
  1817         }
       
  1818     else
       
  1819         {
       
  1820         
       
  1821         // For timed entry, check for Entry Date/Time Changes
       
  1822         if( orgTTime != editedTTime )
       
  1823             {
       
  1824             isEdited = ETrue;
       
  1825             }
       
  1826         }
       
  1827 		
       
  1828     TRACE_EXIT_POINT;
       
  1829     return isEdited;
       
  1830     
       
  1831     //return iOriginal->StartDateTime() != iEdited->StartDateTime();
       
  1832      
       
  1833     }
       
  1834 
       
  1835 // -----------------------------------------------------------------------------
       
  1836 // CCalenEditorDataHandler::IsEndDateTimeEdited
       
  1837 // Returns ETrue if the end date/time has been edited, EFalse otherwise.
       
  1838 // (other items were commented in a header).
       
  1839 // -----------------------------------------------------------------------------
       
  1840 //
       
  1841 TBool CCalenEditorDataHandler::IsEndDateTimeEdited()
       
  1842     {
       
  1843     TRACE_ENTRY_POINT;
       
  1844     TBool isEdited = EFalse;
       
  1845     
       
  1846     TTime orgTTime = iOriginal->EndDateTime();
       
  1847     TTime editedTTime = iEdited->EndDateTime();
       
  1848     
       
  1849     // Get TDateTime of Original & Edited entries.
       
  1850     TDateTime orgDT = orgTTime.DateTime();
       
  1851     TDateTime editedDT = editedTTime.DateTime();
       
  1852     
       
  1853     if( !IsTimedEntry() && IsCreatingNew() )
       
  1854         {
       
  1855         
       
  1856         // For non-timed event, check for only Date field change.
       
  1857         // No need to check for Entry time change.
       
  1858         if( orgDT.Day() != editedDT.Day() ||
       
  1859                 orgDT.Month() != editedDT.Month() ||
       
  1860                 orgDT.Year() != editedDT.Year() )
       
  1861             {
       
  1862             isEdited = ETrue;
       
  1863             }
       
  1864         }
       
  1865     else
       
  1866         {
       
  1867         // For timed entry, check for Entry Date/Time Changes
       
  1868         if( orgTTime != editedTTime )
       
  1869             {
       
  1870             isEdited = ETrue;
       
  1871             }
       
  1872         }
       
  1873     
       
  1874 	TRACE_EXIT_POINT;
       
  1875     return isEdited;
       
  1876 
       
  1877     //return iOriginal->EndDateTime() != iEdited->EndDateTime();
       
  1878     }
       
  1879 
       
  1880 // -----------------------------------------------------------------------------
       
  1881 // CCalenEditorDataHandler::IsDescriptionEdited
       
  1882 // Returns ETrue if the description has been modified, EFalse otherwise.
       
  1883 // (other items were commented in a header).
       
  1884 // -----------------------------------------------------------------------------
       
  1885 //
       
  1886 TBool CCalenEditorDataHandler::IsDescriptionEdited()
       
  1887     {
       
  1888     TRACE_ENTRY_POINT;
       
  1889 
       
  1890     TRACE_EXIT_POINT;
       
  1891     return iOriginal->Description() != iEdited->Description();
       
  1892     }
       
  1893 
       
  1894 // -----------------------------------------------------------------------------
       
  1895 // CCalenEditorDataHandler::IsPriorityEdited
       
  1896 // Returns ETrue if the priotity has been modified, EFalse otherwise.
       
  1897 // (other items were commented in a header).
       
  1898 // -----------------------------------------------------------------------------
       
  1899 //
       
  1900 TBool CCalenEditorDataHandler::IsPriorityEdited()
       
  1901     {
       
  1902     TRACE_ENTRY_POINT;
       
  1903 
       
  1904     TRACE_EXIT_POINT;
       
  1905     return iOriginal->Priority() != iEdited->Priority();
       
  1906     }
       
  1907 
       
  1908 // -----------------------------------------------------------------------------
       
  1909 // CCalenEditorDataHandler::IsCalendarEditedL
       
  1910 // Returns ETrue if the calendar filed has been edited, EFalse otherwise.
       
  1911 // (other items were commented in a header).
       
  1912 // -----------------------------------------------------------------------------
       
  1913 //
       
  1914 TBool CCalenEditorDataHandler::IsCalendarEditedL()
       
  1915     {
       
  1916     TRACE_ENTRY_POINT;
       
  1917       
       
  1918     TRACE_EXIT_POINT;
       
  1919     return iCalendarFieldEdited;
       
  1920     }
       
  1921 
       
  1922 // -----------------------------------------------------------------------------
       
  1923 // CCalenEditorDataHandler::IsSummaryEdited
       
  1924 // Returns ETrue if the summary has been edited, EFalse otherwise.
       
  1925 // (other items were commented in a header).
       
  1926 // -----------------------------------------------------------------------------
       
  1927 //
       
  1928 TBool CCalenEditorDataHandler::IsSummaryEdited()
       
  1929     {
       
  1930     TRACE_ENTRY_POINT;
       
  1931 
       
  1932     // For summary and location, we compare only that part of text
       
  1933     // that fits to editor. If it's equal, then we don't go and unnecessarily
       
  1934     // truncate existing data.
       
  1935     TRACE_EXIT_POINT;
       
  1936     return ( iOriginal->Summary().Left( iMaxTextEditorLength ) 
       
  1937                 != iEdited->Summary().Left( iMaxTextEditorLength ) );
       
  1938     }
       
  1939 
       
  1940 // -----------------------------------------------------------------------------
       
  1941 // CCalenEditorDataHandler::IsLocationEdited
       
  1942 // Returns ETrue if the location has been edited, EFalse otherwise.
       
  1943 // (other items were commented in a header).
       
  1944 // -----------------------------------------------------------------------------
       
  1945 //
       
  1946 TBool CCalenEditorDataHandler::IsLocationEdited()
       
  1947     {
       
  1948     TRACE_ENTRY_POINT;
       
  1949 
       
  1950     // For summary and location, we compare only that part of text
       
  1951     // that fits to editor. If it's equal, then we don't go and unnecessarily
       
  1952     // truncate existing data.
       
  1953     TRACE_EXIT_POINT;
       
  1954     return ( iOriginal->Location().Left( iMaxTextEditorLength ) 
       
  1955                 != iEdited->Location().Left( iMaxTextEditorLength ) );
       
  1956     }
       
  1957 
       
  1958 // -----------------------------------------------------------------------------
       
  1959 // CCalenEditorDataHandler::IsAlarmEditedL
       
  1960 // Returns ETrue if the alarm has been edited, EFalse otherwise.
       
  1961 // (other items were commented in a header).
       
  1962 // -----------------------------------------------------------------------------
       
  1963 //
       
  1964 TBool CCalenEditorDataHandler::IsAlarmEditedL()
       
  1965     {
       
  1966     TRACE_ENTRY_POINT;
       
  1967 
       
  1968     if ( iOriginal->IsAlarmActivated() && iEdited->IsAlarmActivated() )
       
  1969         {
       
  1970         // The alarm must be flagged as changed if the interval between the entry start
       
  1971         // and the alarm is different. (We can't just compare alarm times directly because
       
  1972         // the start date of the entry may have changed.)
       
  1973         TTimeIntervalMinutes origOffset, editedOffset;
       
  1974         
       
  1975         User::LeaveIfError( iOriginal->AlarmDateTime().MinutesFrom( iOriginal->StartDateTime(), origOffset ) );
       
  1976         User::LeaveIfError( iEdited->AlarmDateTime().MinutesFrom( iEdited->StartDateTime(), editedOffset ) );
       
  1977         
       
  1978         TBool alarmTimeChanged = origOffset != editedOffset;
       
  1979 
       
  1980         TRACE_EXIT_POINT;
       
  1981         return alarmTimeChanged;
       
  1982         }
       
  1983     else
       
  1984         {
       
  1985         TBool statusChanged = iOriginal->IsAlarmActivated() != iEdited->IsAlarmActivated();
       
  1986 
       
  1987         TRACE_EXIT_POINT;
       
  1988         return statusChanged;
       
  1989         }
       
  1990     }
       
  1991 
       
  1992 // -----------------------------------------------------------------------------
       
  1993 // CCalenEditorDataHandler::IsRepeatRuleEdited
       
  1994 // Returns ETrue if the repeat rule has been edited, EFalse otherwise.
       
  1995 // (other items were commented in a header).
       
  1996 // -----------------------------------------------------------------------------
       
  1997 //
       
  1998 TBool CCalenEditorDataHandler::IsRepeatRuleEdited()
       
  1999     {
       
  2000     TRACE_ENTRY_POINT;
       
  2001 
       
  2002     if ( iOriginal->IsRepeating() && iEdited->IsRepeating() )
       
  2003         {
       
  2004         TBool repeatTypeChanged = iOriginal->RepeatType() != iEdited->RepeatType();
       
  2005         TBool untilDateChanged = iOriginal->RepeatUntilDateTime() != iEdited->RepeatUntilDateTime();
       
  2006 
       
  2007         TRACE_EXIT_POINT;
       
  2008         return repeatTypeChanged || untilDateChanged;
       
  2009         }
       
  2010     else
       
  2011         {
       
  2012         TBool statusChanged = iOriginal->IsRepeating() != iEdited->IsRepeating();
       
  2013 
       
  2014         TRACE_EXIT_POINT;
       
  2015         return statusChanged;
       
  2016         }
       
  2017     }
       
  2018 
       
  2019 // -----------------------------------------------------------------------------
       
  2020 // CCalenEditorDataHandler::LocationEnabledInUiL
       
  2021 // Returns ETrue if the location is a valid field for this type of entry
       
  2022 // (i.e. meetings & reminders only), EFalse otherwise.
       
  2023 // (other items were commented in a header).
       
  2024 // -----------------------------------------------------------------------------
       
  2025 //
       
  2026 TBool CCalenEditorDataHandler::LocationEnabledInUiL()
       
  2027     {
       
  2028     TRACE_ENTRY_POINT;
       
  2029 
       
  2030     // Location is enabled for timed entries (i.e. an appointment or a
       
  2031     // reminder)
       
  2032     TRACE_EXIT_POINT;
       
  2033     return IsTimedEntry();
       
  2034     }
       
  2035 
       
  2036 // -----------------------------------------------------------------------------
       
  2037 // CCalenEditorDataHandler::IsTimedEntry
       
  2038 // Returns ETrue if this is a timed entry, EFalse otherwise.
       
  2039 // (other items were commented in a header).
       
  2040 // -----------------------------------------------------------------------------
       
  2041 //
       
  2042 TBool CCalenEditorDataHandler::IsTimedEntry() const
       
  2043     {
       
  2044     TRACE_ENTRY_POINT;
       
  2045 
       
  2046     TRACE_EXIT_POINT;
       
  2047     return IsTimed( iEdited->EntryType() );
       
  2048     }
       
  2049 
       
  2050 // -----------------------------------------------------------------------------
       
  2051 // CCalenEditorDataHandler::IsCreatingNew
       
  2052 // Returns ETrue if the user is creating a new entry, EFalse if the user is
       
  2053 // editing an existing entry.
       
  2054 // (other items were commented in a header).
       
  2055 // -----------------------------------------------------------------------------
       
  2056 //
       
  2057 TBool CCalenEditorDataHandler::IsCreatingNew() const
       
  2058     {
       
  2059     TRACE_ENTRY_POINT;
       
  2060 
       
  2061     TRACE_EXIT_POINT;
       
  2062     return iIsCreatingNew;
       
  2063     }
       
  2064 
       
  2065 // -----------------------------------------------------------------------------
       
  2066 // CCalenEditorDataHandler::IsStartDateChanged
       
  2067 // Returns ETrue if the start date of the entry has been changed, 
       
  2068 // EFalse otherwise. Note that this function only checks the date, 
       
  2069 // and not the time of day, of the entry.
       
  2070 // (other items were commented in a header).
       
  2071 // -----------------------------------------------------------------------------
       
  2072 //
       
  2073 TBool CCalenEditorDataHandler::IsStartDateChanged()
       
  2074     {
       
  2075     TRACE_ENTRY_POINT;
       
  2076 
       
  2077     TRACE_EXIT_POINT;
       
  2078     return ! CalenDateUtils::OnSameDay( iOriginal->StartDateTime(),
       
  2079                                         iEdited->StartDateTime() );
       
  2080     }
       
  2081 
       
  2082 // -----------------------------------------------------------------------------
       
  2083 // CCalenEditorDataHandler::IsAttachmentExists
       
  2084 // Returns ETrue calendar entry is having attachments
       
  2085 // (other items were commented in a header).
       
  2086 // -----------------------------------------------------------------------------
       
  2087 //
       
  2088 TBool CCalenEditorDataHandler::IsAttachmentExists()
       
  2089     {
       
  2090     TRACE_ENTRY_POINT;
       
  2091     TBool attachmentExits(EFalse);
       
  2092     
       
  2093     // TODO: Uncomment this when enabling attachment support
       
  2094     
       
  2095     if( (iOriginal->AttachmentCount() != iEdited->AttachmentCount())
       
  2096          || iServices.GetAttachmentData()->NumberOfItems() )
       
  2097         {
       
  2098         attachmentExits = ETrue;
       
  2099         }
       
  2100     
       
  2101     TRACE_EXIT_POINT;
       
  2102     return attachmentExits;
       
  2103     }
       
  2104 
       
  2105 // -----------------------------------------------------------------------------
       
  2106 // CCalenEditorDataHandler::IsEventTypeEdited
       
  2107 // (other items were commented in a header).
       
  2108 // -----------------------------------------------------------------------------
       
  2109 //
       
  2110 TBool CCalenEditorDataHandler::IsEventTypeEdited()
       
  2111     {
       
  2112     TRACE_ENTRY_POINT;
       
  2113     TBool fieldModified = EFalse;
       
  2114     
       
  2115     // Check EventType field is edited for already saved Entry
       
  2116     // For Newly created entry, ignore the EventTypeChange
       
  2117     if( (iOriginal->EntryType() != iEdited->EntryType()) && !IsCreatingNew() )
       
  2118         {
       
  2119         fieldModified = ETrue;
       
  2120         }
       
  2121     
       
  2122     TRACE_EXIT_POINT;
       
  2123     return fieldModified;
       
  2124     }
       
  2125 	
       
  2126 // -----------------------------------------------------------------------------
       
  2127 // CCalenEditorDataHandler::AllDayFieldEdited
       
  2128 // Returns ETrue if `All day event' line has been modified.
       
  2129 // (other items were commented in a header).
       
  2130 // -----------------------------------------------------------------------------
       
  2131 //
       
  2132 TBool CCalenEditorDataHandler::AllDayFieldEdited()
       
  2133     {
       
  2134     TRACE_ENTRY_POINT;
       
  2135     TBool fieldModified = EFalse;
       
  2136     
       
  2137     if( iOriginal->IsAllDayEvent() != iEdited->IsAllDayEvent() )
       
  2138         {
       
  2139         fieldModified = ETrue;
       
  2140         }
       
  2141     
       
  2142     TRACE_EXIT_POINT;
       
  2143     return fieldModified;
       
  2144     }
       
  2145 
       
  2146 // -----------------------------------------------------------------------------
       
  2147 // CCalenEditorDataHandler::SetDefaultAlarmDateTimeL
       
  2148 // Sets the alarm to the default value. This function is called after the user
       
  2149 // forces an exit, e.g. when pressing the power off button.
       
  2150 // (other items were commented in a header).
       
  2151 // -----------------------------------------------------------------------------
       
  2152 //
       
  2153 void CCalenEditorDataHandler::SetDefaultAlarmDateTimeL()
       
  2154     {
       
  2155     TRACE_ENTRY_POINT;
       
  2156 
       
  2157     /**
       
  2158      * Default alarm time is UI spec logic.
       
  2159      * It is important that this is here, because there shouldn't be UI spec logic in CCalenEntryUtil,
       
  2160      * only in CCalenEditorDataHandler.
       
  2161      *
       
  2162      * It is still a bit odd, that other set methods are in CCalenEntryUtil but not here.
       
  2163      * Maybe I add wrapper set methods for edited data also in *Handler.
       
  2164      *   e.g. void SetAlarmOffL() { Edited().SetAlarmOffL(); }
       
  2165      *
       
  2166      */
       
  2167     TTime defaultAlarm;
       
  2168 
       
  2169     if ( IsTimedEntry() )
       
  2170         {
       
  2171         TTimeIntervalMinutes defaultOffsetM( 15 ); // FIXME: should be read from central repository
       
  2172         defaultAlarm = Edited().StartDateTime() - defaultOffsetM;
       
  2173         }
       
  2174     else
       
  2175         {
       
  2176         TTimeIntervalHours defaultOffsetH( -8 );
       
  2177         defaultAlarm = CalenDateUtils::BeginningOfDay( Edited().EventDateTime() ) - defaultOffsetH;
       
  2178         }
       
  2179 
       
  2180     Edited().SetAlarmOnL( defaultAlarm );
       
  2181 
       
  2182     TRACE_EXIT_POINT;
       
  2183     }
       
  2184 
       
  2185 // -----------------------------------------------------------------------------
       
  2186 // CCalenEditorDataHandler::CalculateRepeatRuleL
       
  2187 // Calculates the repeat rule for a given entry.
       
  2188 // (other items were commented in a header).
       
  2189 // -----------------------------------------------------------------------------
       
  2190 //
       
  2191 void CCalenEditorDataHandler::CalculateRepeatRuleL(
       
  2192     const TTime& aStartDateTime,
       
  2193     TCalenRepeatIndex aNewRepeatType,
       
  2194     const TTime& aRepeatUntil,
       
  2195     TCalRRule& aRRule)
       
  2196     {
       
  2197     TRACE_ENTRY_POINT;
       
  2198 
       
  2199     // FIXME: This is copy-pasted from old implementation.
       
  2200     // This should be rewritten with care.
       
  2201         //If it ain't broke...?
       
  2202     TTime startDateTime = aStartDateTime;
       
  2203     TTime repeatUntil = aRepeatUntil;
       
  2204 
       
  2205     TCalRRule origRRule;
       
  2206     TBool hasOrigRRule = iEntry.GetRRuleL( origRRule );
       
  2207 
       
  2208     TBool isStartDateSame = CalenDateUtils::OnSameDay(
       
  2209         Original().StartDateTime(), Edited().StartDateTime() );
       
  2210 
       
  2211     //
       
  2212     // If repeat type is changed, repeat start date
       
  2213     // is replaced to the date of "Start date" field.
       
  2214     //
       
  2215     if ( hasOrigRRule &&
       
  2216          isStartDateSame &&
       
  2217          aNewRepeatType == Original().RepeatType() )
       
  2218         {
       
  2219         aRRule = origRRule; // keep the original setting...
       
  2220         // until date changed?
       
  2221         }
       
  2222     else if (aNewRepeatType == ERepeatOther)
       
  2223         {
       
  2224         // prevRptDef is ALWAYS non-NULL in this block,
       
  2225         // because previous note's repeat ALWAYS exists.
       
  2226         aRRule = origRRule;
       
  2227         TCalTime repeatStart;
       
  2228         if ( UseFloatingTimeL() )
       
  2229             {
       
  2230             repeatStart.SetTimeLocalFloatingL( startDateTime );
       
  2231             }
       
  2232         else
       
  2233             {
       
  2234             repeatStart.SetTimeLocalL( startDateTime );
       
  2235             }
       
  2236         aRRule.SetDtStart( repeatStart );
       
  2237         }
       
  2238     else
       
  2239         {
       
  2240         TCalTime repeatSt;
       
  2241         if ( UseFloatingTimeL() )
       
  2242             {
       
  2243             repeatSt.SetTimeLocalFloatingL( startDateTime );
       
  2244             }
       
  2245         else
       
  2246             {
       
  2247             repeatSt.SetTimeLocalL( startDateTime );
       
  2248             }
       
  2249         aRRule.SetDtStart( repeatSt );
       
  2250         aRRule.SetInterval( 1 );
       
  2251 
       
  2252         TInt interval(1);
       
  2253 
       
  2254         switch ( aNewRepeatType )
       
  2255             {
       
  2256             case (ERepeatDaily):  // Daily
       
  2257                 {
       
  2258                 aRRule.SetType( TCalRRule::EDaily );
       
  2259                 break;
       
  2260                 }
       
  2261             case (ERepeatWeekly):  // Weekly
       
  2262                 {
       
  2263                 if (hasOrigRRule && origRRule.Type() == TCalRRule::EDaily &&
       
  2264                     origRRule.Interval() == 7)
       
  2265                     {
       
  2266                     // If old note's repeat is every 7 days,
       
  2267                     // set repeat to every 7 days to Agenda, NOT every week.
       
  2268                     //
       
  2269                     aRRule.SetType( TCalRRule::EDaily );
       
  2270                     interval = 7;
       
  2271                     }
       
  2272                 else
       
  2273                     {
       
  2274                     aRRule.SetType( TCalRRule::EWeekly );
       
  2275 
       
  2276                     RArray<TDay> dayArray;
       
  2277                     CleanupClosePushL( dayArray );
       
  2278                     dayArray.Append( aRRule.DtStart().TimeLocalL().DayNoInWeek() );
       
  2279                     aRRule.SetByDay( dayArray );
       
  2280                     CleanupStack::PopAndDestroy( &dayArray );
       
  2281                     }
       
  2282                break;
       
  2283                 }
       
  2284             case (ERepeatBiWeekly):  // Bi-weekly
       
  2285                 {
       
  2286                 if ( hasOrigRRule && origRRule.Type() == TCalRRule::EDaily &&
       
  2287                      origRRule.Interval() == 14)
       
  2288                     {
       
  2289                     // If old note's repeat is every 14 days,
       
  2290                     // set repeat to every 14 days to Agenda, NOT every 2 weeks.
       
  2291                     //
       
  2292                     aRRule.SetType( TCalRRule::EDaily );
       
  2293                     interval = 14;
       
  2294                     }
       
  2295                 else
       
  2296                     {
       
  2297                     aRRule.SetType( TCalRRule::EWeekly );
       
  2298                     interval = 2;
       
  2299 
       
  2300                     RArray<TDay> dayArray;
       
  2301                     CleanupClosePushL( dayArray );
       
  2302                     dayArray.Append( aRRule.DtStart().TimeLocalL().DayNoInWeek() );
       
  2303                     aRRule.SetByDay( dayArray );
       
  2304                     CleanupStack::PopAndDestroy( &dayArray );
       
  2305                     }
       
  2306                 break;
       
  2307                 }
       
  2308                 case ERepeatWorkdays:// Weekly
       
  2309                     {
       
  2310                     TLocale iLocale;
       
  2311                     TUint iWorkDays = iLocale.WorkDays();
       
  2312                     if (hasOrigRRule && origRRule.Type() == TCalRRule::EDaily
       
  2313                         && origRRule.Interval() == 7)
       
  2314                         {
       
  2315                         // If old note's repeat is every 7 days,
       
  2316                         // set repeat to every 7 days to Agenda, NOT every week.
       
  2317                         //
       
  2318                         aRRule.SetType(TCalRRule::EDaily);
       
  2319                         interval = 7;
       
  2320                         }
       
  2321                     else
       
  2322                         {
       
  2323                         aRRule.SetType(TCalRRule::EWeekly);
       
  2324                         RArray<TDay> dayArray;
       
  2325                         CleanupClosePushL(dayArray); 
       
  2326                         TInt fixedNum = 1;
       
  2327                         TInt ruleday = 0;
       
  2328                         for (TInt i =0 ; i < KNoOfDaysInWeek ; i++)
       
  2329                             {
       
  2330                             ruleday = fixedNum << i;
       
  2331                             if(iWorkDays & ruleday)
       
  2332                                 {
       
  2333                                 dayArray.Append((TDay)i);
       
  2334                                 aRRule.SetByDay(dayArray);
       
  2335                                 }   
       
  2336                             } 
       
  2337                          CleanupStack::PopAndDestroy(&dayArray);
       
  2338                          }
       
  2339                     break;
       
  2340                                   
       
  2341                     }
       
  2342             case (ERepeatMonthly):
       
  2343                 // Monthly By Position
       
  2344                 {
       
  2345                 aRRule.SetType( TCalRRule::EMonthly );
       
  2346 
       
  2347                 RArray<TInt> dateArray;
       
  2348                 CleanupClosePushL( dateArray );
       
  2349                 dateArray.Append( aRRule.DtStart().TimeLocalL().DayNoInMonth() );
       
  2350                 aRRule.SetByMonthDay( dateArray );
       
  2351                 CleanupStack::PopAndDestroy( &dateArray );
       
  2352 
       
  2353                 break;
       
  2354                 }
       
  2355             case (ERepeatYearly):  // Yearly
       
  2356                 {
       
  2357                 // If old note's repeat is every 12 months,
       
  2358                 // set repeat to every 12 months to Agenda, NOT every year.
       
  2359                 //
       
  2360                 if ( hasOrigRRule && origRRule.Type() == TCalRRule::EMonthly &&
       
  2361                      origRRule.Interval() == 12)
       
  2362                     {
       
  2363                     aRRule.SetType( TCalRRule::EMonthly );
       
  2364                     interval = 12;
       
  2365                     }
       
  2366                 else
       
  2367                     {
       
  2368                     aRRule.SetType( TCalRRule::EYearly );
       
  2369                     }
       
  2370                 break;
       
  2371                 }
       
  2372             default: // Repeat item is "Other"
       
  2373                 {
       
  2374                 interval = aRRule.Interval(); // To copy previous note's interval
       
  2375                 break;
       
  2376                 }
       
  2377             }
       
  2378 
       
  2379         aRRule.SetInterval( interval );
       
  2380         }
       
  2381 
       
  2382     // If repeat until is max date of Calendar,
       
  2383     // note repeat is set to forever.
       
  2384     if ( ! CalenDateUtils::IsValidDay(repeatUntil) || IsForeverDate( repeatUntil ) )
       
  2385         {
       
  2386         // Set repeat to forever:
       
  2387         aRRule.SetCount( 0 );
       
  2388         }
       
  2389     else
       
  2390         {
       
  2391         // Change repeatuntil so that hours, minutes, ... are same as in start date
       
  2392         TDateTime dtUntil = repeatUntil.DateTime();
       
  2393         TDateTime dtStart= iEntry.StartTimeL().TimeLocalL().DateTime();
       
  2394 
       
  2395         dtUntil.Set( dtUntil.Year(), dtUntil.Month(), dtUntil.Day(),
       
  2396                      dtStart.Hour(), dtStart.Minute(), dtStart.Second(), dtStart.MicroSecond());
       
  2397 
       
  2398         TCalTime calRepeatUntil;
       
  2399         if ( UseFloatingTimeL() )
       
  2400             {
       
  2401             calRepeatUntil.SetTimeLocalFloatingL( TTime( dtUntil ) );
       
  2402             }
       
  2403         else
       
  2404             {
       
  2405             calRepeatUntil.SetTimeLocalL( TTime( dtUntil ) );
       
  2406             }
       
  2407         aRRule.SetUntil( calRepeatUntil );
       
  2408         }
       
  2409 
       
  2410     TRACE_EXIT_POINT;
       
  2411     }
       
  2412 
       
  2413 // -----------------------------------------------------------------------------
       
  2414 // CCalenEditorDataHandler::SetDefaultNewValuesL
       
  2415 // Sets the default values when creating a new entry.
       
  2416 // (other items were commented in a header).
       
  2417 // -----------------------------------------------------------------------------
       
  2418 //
       
  2419 void CCalenEditorDataHandler::SetDefaultNewValuesL(CCalenEntryUtil& aData)
       
  2420     {
       
  2421     TRACE_ENTRY_POINT;
       
  2422 
       
  2423     // FIXME: I don't know if this method should be needed or not.
       
  2424     // It's a bit unclear that if pass entry that is new,
       
  2425     // should we set default data in caller (application) or
       
  2426     // here.
       
  2427     // But to replicate old editor functionality, we set in editor
       
  2428     // side
       
  2429 
       
  2430     ASSERT( IsCreatingNew() );
       
  2431     // start time and end time are taken from passed entry.
       
  2432     // They have to be initialized outside of editors
       
  2433 
       
  2434     // subject, location, description are by default empty
       
  2435 
       
  2436     // repeat rule is by default off
       
  2437 
       
  2438     // alarm is by default off
       
  2439 
       
  2440     // synch value
       
  2441     aData.SetSynchTypeL( CCalenEntryUtil::ESynchPrivate );
       
  2442 
       
  2443     // priority
       
  2444     aData.SetPriorityL( CCalenEntryUtil::ETodoPriorityNormal );
       
  2445     
       
  2446     TRACE_EXIT_POINT;
       
  2447     }
       
  2448 
       
  2449 // -----------------------------------------------------------------------------
       
  2450 // CCalenEditorDataHandler::IsChildL
       
  2451 // Returns ETrue if the entry is a child, EFalse otherwise.
       
  2452 // (other items were commented in a header).
       
  2453 // -----------------------------------------------------------------------------
       
  2454 //
       
  2455 TBool CCalenEditorDataHandler::IsChildL() const
       
  2456     {
       
  2457     TRACE_ENTRY_POINT;
       
  2458 
       
  2459     TRACE_EXIT_POINT;
       
  2460     return iRecurrenceId.TimeUtcL() != Time::NullTTime();
       
  2461     }
       
  2462 
       
  2463 // -----------------------------------------------------------------------------
       
  2464 // CCalenEditorDataHandler::UseFloatingTimeL
       
  2465 // Returns ETrue if the entry should use floating time, EFalse otherwise.
       
  2466 // (other items were commented in a header).
       
  2467 // -----------------------------------------------------------------------------
       
  2468 //
       
  2469 TBool CCalenEditorDataHandler::UseFloatingTimeL() const
       
  2470     {
       
  2471     TRACE_ENTRY_POINT;
       
  2472 
       
  2473     // Use floating time based on type
       
  2474     // This way we ensure that entries _created_ with Calendar Editors
       
  2475     // are consistent regarding time mode.
       
  2476     //
       
  2477     TRACE_EXIT_POINT;
       
  2478     return (! IsTimedEntry()); // use floating time for non-timed entries        
       
  2479         
       
  2480     }
       
  2481 
       
  2482 // -----------------------------------------------------------------------------
       
  2483 // CCalenEditorDataHandler::WriteStartAndEndTimesToEntryL
       
  2484 // Writes the start and end times from the form to the CCalEntry.
       
  2485 // (other items were commented in a header).
       
  2486 // -----------------------------------------------------------------------------
       
  2487 //
       
  2488 void CCalenEditorDataHandler::WriteStartAndEndTimesToEntryL( CalCommon::TRecurrenceRange aRepeatTarget )
       
  2489     {
       
  2490     TRACE_ENTRY_POINT;
       
  2491 
       
  2492     const TBool unDatedTodo=(iEntry.EntryTypeL()==CCalEntry::ETodo) && (iEntry.EndTimeL().TimeLocalL()==Time::NullTTime());
       
  2493     const TBool unDatedTodoWithAlarm=unDatedTodo && (Edited().IsAlarmActivated());
       
  2494 
       
  2495     TBool shouldWriteBothTimes =
       
  2496         // For new entries
       
  2497         IsCreatingNew() ||
       
  2498         // When creating exception entry (exception entry's time are read from editors)
       
  2499         ( aRepeatTarget != CalCommon::EThisAndAll ) ||
       
  2500         // when repeating entry is modified to be non-repeating (entry's times are read from editors)
       
  2501         ( Original().IsRepeating() && ! Edited().IsRepeating() );
       
  2502 
       
  2503     if ( shouldWriteBothTimes || IsStartDateTimeEdited() || IsEndDateTimeEdited() || unDatedTodoWithAlarm )
       
  2504         {
       
  2505 
       
  2506         TCalTime entryStart;
       
  2507         TCalTime entryEnd;
       
  2508 
       
  2509         // 1) Initialize entryStart and entryEnd with original times.
       
  2510         // But for todos we need to be careful, because there might not be them originally
       
  2511         // In S60 UI, todos don't have starttime, so we use same for both start and end time.
       
  2512         if (iEntry.EntryTypeL()==CCalEntry::ETodo)
       
  2513             {
       
  2514              // if undated todo and it has alarm activated
       
  2515             if ((iEntry.EndTimeL().TimeLocalL()==Time::NullTTime()) && (Edited().IsAlarmActivated()))
       
  2516                 {
       
  2517                 entryStart.SetTimeLocalL(Edited().EventDateTime());
       
  2518                 entryEnd.SetTimeLocalL(Edited().EventDateTime());
       
  2519                 shouldWriteBothTimes=ETrue; // Ensures that times are written later
       
  2520                 }
       
  2521             else
       
  2522                 {
       
  2523                  entryStart = iEntry.EndTimeL();
       
  2524                  entryEnd = iEntry.EndTimeL();
       
  2525                 }
       
  2526             }
       
  2527         else
       
  2528             {
       
  2529             entryStart = iEntry.StartTimeL();
       
  2530             entryEnd   = iEntry.EndTimeL();
       
  2531             }
       
  2532 
       
  2533         // 2) Decide start time
       
  2534         if ( shouldWriteBothTimes || IsStartDateTimeEdited() )
       
  2535             {
       
  2536             TTime newStart = Edited().StartDateTime();
       
  2537             TDateTime newStartDT = newStart.DateTime();
       
  2538             // Special case:
       
  2539             // In case c) only start time (hh:mm) of d) existing a) repeating b) series is edited,
       
  2540             // we need to preserve start date (dd.mm.yyy), because start date in editors
       
  2541             // is instance's start date.
       
  2542             // (Example of problematic cases that brings up, when UI represents
       
  2543             // two different concepts in same start date field)
       
  2544             //   a) repeating              b) series is edited                        c) only start time is edited     d) existing
       
  2545             if ( Edited().IsRepeating() && aRepeatTarget == CalCommon::EThisAndAll && ! IsStartDateChanged()        && ! IsCreatingNew() )
       
  2546                 {
       
  2547                 TDateTime oldDt = iEntry.StartTimeL().TimeLocalL().DateTime();
       
  2548                 TDateTime editDt = newStart.DateTime();
       
  2549                 newStart = TTime( TDateTime( oldDt.Year(), oldDt.Month(), oldDt.Day(),
       
  2550                                              editDt.Hour(), editDt.Minute(),
       
  2551                                              oldDt.Second(), oldDt.MicroSecond() ) );
       
  2552                 }
       
  2553             else if ( ( Edited().RepeatType() == ERepeatOther ) && IsStartDateChanged() )
       
  2554                 {
       
  2555                 // The start time might have been disguised because the entry
       
  2556                 // consists of an rRule and rDates. The actual start time
       
  2557                 // needs to be extracted
       
  2558                 RArray<TCalTime> rDates;
       
  2559                 CleanupClosePushL( rDates );
       
  2560                 
       
  2561                 iEntry.GetRDatesL( rDates );
       
  2562                 if ( rDates.Count() > 0 )
       
  2563                     {
       
  2564                     // As we have rDates, check to see if there is an
       
  2565                     // rRule
       
  2566                     TCalRRule rRule;
       
  2567                     if ( iEntry.GetRRuleL( rRule ) )
       
  2568                         {
       
  2569                         TTime firstRDate = rDates[ 0 ].TimeLocalL();
       
  2570                         TTime rRuleStart = iEntry.StartTimeL().TimeLocalL();
       
  2571                         TTime lastRDate = rDates[ rDates.Count() - 1 ].TimeLocalL();
       
  2572                         TTimeIntervalMinutes startDateShiftInterval = 0;
       
  2573                         if ( firstRDate < rRuleStart )
       
  2574                             {
       
  2575                             // The first rDate is before the start of the rRule
       
  2576                             // So adjust the start date accordingly
       
  2577                             
       
  2578                             User::LeaveIfError( newStart.MinutesFrom( firstRDate, startDateShiftInterval ) );
       
  2579                             }
       
  2580                         else
       
  2581                             {
       
  2582                             // The start of the rRule comes first
       
  2583                             User::LeaveIfError( newStart.MinutesFrom( rRuleStart, startDateShiftInterval ) );
       
  2584                             }
       
  2585                             
       
  2586                         newStart = rRuleStart + startDateShiftInterval;
       
  2587                         
       
  2588                         TInt rRuleCount = rRule.Count();
       
  2589                         rRule.SetCount( rRuleCount );
       
  2590                         
       
  2591                         TCalTime rRuleDT;
       
  2592                         if ( UseFloatingTimeL() )
       
  2593                             {
       
  2594                             rRuleDT.SetTimeLocalFloatingL( newStart );
       
  2595                             }
       
  2596                         else
       
  2597                             {
       
  2598                             rRuleDT.SetTimeLocalL( newStart );
       
  2599                             }
       
  2600                         
       
  2601                         rRule.SetDtStart( rRuleDT );
       
  2602 						
       
  2603 						// For rearranging the recurrence pattern for an 
       
  2604 						// entry having rdates
       
  2605 						
       
  2606 						TInt repeatType = rRule.Type();	
       
  2607        					switch ( repeatType )
       
  2608             				{
       
  2609                				case ( TCalRRule::EWeekly ):  //For Weekly repeating event
       
  2610                 				{
       
  2611                 				RArray<TDay> dayArray;
       
  2612                     			CleanupClosePushL( dayArray );
       
  2613                     			dayArray.Append( rRule.DtStart().TimeLocalL().DayNoInWeek() );
       
  2614                     			rRule.SetByDay( dayArray );
       
  2615                     			CleanupStack::PopAndDestroy( &dayArray );
       
  2616                     			
       
  2617                     			// Adjust the RepeatUntil date
       
  2618                     			ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() );            
       
  2619 								break;
       
  2620                 				}
       
  2621                             case ( TCalRRule::EMonthly ):// For Monthly repeating event
       
  2622                                 {
       
  2623 				                RArray<TInt> dateArray;
       
  2624                 				CleanupClosePushL( dateArray );
       
  2625                 				dateArray.Append( rRule.DtStart().TimeLocalL().DayNoInMonth() );
       
  2626                 				rRule.SetByMonthDay( dateArray );
       
  2627                 				CleanupStack::PopAndDestroy( &dateArray );
       
  2628 							
       
  2629 								// Adjust the RepeatUntil date
       
  2630 								ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() );            
       
  2631 				                break;
       
  2632                 				}
       
  2633                 				
       
  2634                 			 case ( TCalRRule::EDaily ):// For Daily repeating event
       
  2635                                 {
       
  2636 				                TCalRRule curRule;				
       
  2637 								iEntry.GetRRuleL( curRule );
       
  2638 								
       
  2639 								// Adjust the RepeatUntil date
       
  2640 								if(lastRDate < curRule.Until().TimeLocalL() )
       
  2641 									{
       
  2642 									ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() );  	
       
  2643 									}
       
  2644 								
       
  2645 								
       
  2646 				                break;
       
  2647                 				}
       
  2648 				            default:
       
  2649                 				{
       
  2650 				                break;
       
  2651                 				}
       
  2652             				}
       
  2653 
       
  2654                         
       
  2655                         iEntry.SetRRuleL( rRule );
       
  2656                         }
       
  2657                     }
       
  2658                 
       
  2659                 CleanupStack::PopAndDestroy(); // rDates
       
  2660                 }
       
  2661 
       
  2662             if ( UseFloatingTimeL() )
       
  2663                 {
       
  2664                 entryStart.SetTimeLocalFloatingL( newStart );
       
  2665                 }
       
  2666             else
       
  2667                 {
       
  2668                 entryStart.SetTimeLocalL( newStart );
       
  2669                 }
       
  2670             }
       
  2671 
       
  2672         // 3) Decide end time
       
  2673         if ( shouldWriteBothTimes || IsEndDateTimeEdited() )
       
  2674             {
       
  2675             TTime start = Edited().StartDateTime();
       
  2676             TTime end = Edited().EndDateTime();
       
  2677             
       
  2678             // For all-day events, we add 24 hours to end date
       
  2679             // to make it full day long
       
  2680             /*if ( iEntryType == CCalEntry::EEvent)
       
  2681                 {
       
  2682                 end += TTimeIntervalDays(1);
       
  2683                 }*/
       
  2684 
       
  2685             TTimeIntervalMinutes duration;
       
  2686             TInt err = end.MinutesFrom( start, duration );
       
  2687             ASSERT( err == KErrNone );
       
  2688             ASSERT( duration >= TTimeIntervalMinutes(0) );
       
  2689 
       
  2690             if ( UseFloatingTimeL() )
       
  2691                 {
       
  2692                 entryEnd.SetTimeLocalFloatingL( entryStart.TimeLocalL() + duration );
       
  2693                 }
       
  2694             else
       
  2695                 {
       
  2696                 entryEnd.SetTimeLocalL( entryStart.TimeLocalL() + duration );
       
  2697                 }
       
  2698             }
       
  2699         
       
  2700         // If EntryType is changed as Non-timed/Timed entry, along with StartTime(AND/OR)EndTime,
       
  2701         // Both Start/End time TimeMode should be changed accordingly.
       
  2702         if ( UseFloatingTimeL() )
       
  2703             {
       
  2704             entryStart.SetTimeLocalFloatingL( entryStart.TimeLocalL() );
       
  2705             entryEnd.SetTimeLocalFloatingL( entryEnd.TimeLocalL() );
       
  2706             }
       
  2707         else
       
  2708             {
       
  2709             entryStart.SetTimeLocalL( entryStart.TimeLocalL() );
       
  2710             entryEnd.SetTimeLocalL( entryEnd.TimeLocalL() );
       
  2711             }
       
  2712         
       
  2713         // Write times to entry
       
  2714         iEntry.SetStartAndEndTimeL( entryStart, entryEnd );
       
  2715         }
       
  2716 
       
  2717     TRACE_EXIT_POINT;
       
  2718     }
       
  2719 
       
  2720 //----------------------------------------------------------------------
       
  2721 // CCalenEditorDataHandler::ResetOriginalDataL
       
  2722 // Reset original editor data
       
  2723 // (other items were commented in a header).
       
  2724 //----------------------------------------------------------------------
       
  2725 void CCalenEditorDataHandler::ResetOriginalDataL()
       
  2726     {
       
  2727     TRACE_ENTRY_POINT;
       
  2728 		
       
  2729     if(iOriginal)
       
  2730 		{
       
  2731 		delete iOriginal;
       
  2732 		iOriginal=NULL;
       
  2733 		}
       
  2734     iOriginal = CCalenEntryUtil::NewL( iEntry, iInstanceDateTime );
       
  2735 
       
  2736     TRACE_EXIT_POINT;
       
  2737     }
       
  2738 
       
  2739 //----------------------------------------------------------------------
       
  2740 // CCalenEditorDataHandler::EntryViewL
       
  2741 // Temp function to get to work 
       
  2742 // (other items were commented in a header).
       
  2743 //----------------------------------------------------------------------
       
  2744 CCalEntryView&  CCalenEditorDataHandler::EntryViewL()
       
  2745     {
       
  2746     TRACE_ENTRY_POINT;
       
  2747 
       
  2748     CCalEntryView* entryView = iServices.EntryViewL(CurrentDbCollectionId());
       
  2749 
       
  2750     TRACE_EXIT_POINT;
       
  2751     return *entryView;
       
  2752     }
       
  2753 
       
  2754 //----------------------------------------------------------------------
       
  2755 // CCalenEditorDataHandler::InstanceViewL
       
  2756 // Temp function to get to work
       
  2757 // (other items were commented in a header).
       
  2758 //----------------------------------------------------------------------
       
  2759 CCalInstanceView&  CCalenEditorDataHandler::InstanceViewL()
       
  2760     {
       
  2761     TRACE_ENTRY_POINT;
       
  2762     
       
  2763     CCalInstanceView* instanceView = iServices.InstanceViewL(iCollectionIds);
       
  2764     
       
  2765     TRACE_EXIT_POINT;
       
  2766     return *instanceView;
       
  2767     }
       
  2768 
       
  2769 // -----------------------------------------------------------------------------
       
  2770 // CCalenEditorDataHandler::GetPreviousInstanceForRepeatOtherL()
       
  2771 // Returns the time of the previous instance of a particular repeating entry
       
  2772 // (other items were commented in a header).
       
  2773 // -----------------------------------------------------------------------------
       
  2774 //
       
  2775 TTime CCalenEditorDataHandler::GetPreviousInstanceForRepeatOtherL(CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange)
       
  2776     {
       
  2777 	RPointerArray<CCalInstance> allInstances;
       
  2778     CleanupResetAndDestroyPushL( allInstances );
       
  2779     
       
  2780     TInt filter;
       
  2781     // Get the entry type to be filtered
       
  2782     switch(aEntry.EntryTypeL())
       
  2783         {
       
  2784     	case CCalEntry::EAppt:
       
  2785     		filter = CalCommon::EIncludeAppts;
       
  2786     		break;
       
  2787     	case CCalEntry::ETodo:
       
  2788     		filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos;
       
  2789     		break;
       
  2790     	case CCalEntry::EEvent:
       
  2791     		filter = CalCommon::EIncludeEvents;
       
  2792     		break;
       
  2793     	case CCalEntry::EReminder:
       
  2794     		filter = CalCommon::EIncludeReminder;
       
  2795     		break;
       
  2796     	case CCalEntry::EAnniv:
       
  2797     		filter = CalCommon::EIncludeAnnivs;
       
  2798     		break;
       
  2799     	default:
       
  2800     		filter = CalCommon::EIncludeAll;
       
  2801     		break;
       
  2802         };
       
  2803 
       
  2804     iServices.InstanceViewL()->FindInstanceL( allInstances, 
       
  2805                                      (CalCommon::TCalViewFilterFlags)filter,
       
  2806                                      timeRange);
       
  2807 
       
  2808 	TTime previousTime = Time::NullTTime();
       
  2809 	
       
  2810     for( TInt i = allInstances.Count() - 1; i >= 0; i-- )
       
  2811         {
       
  2812         if( allInstances[i]->Entry().UidL() == aEntry.UidL() )
       
  2813             {
       
  2814             TRACE_EXIT_POINT;
       
  2815             previousTime = allInstances[i]->Time().TimeLocalL();
       
  2816             break;
       
  2817             }
       
  2818         }
       
  2819 
       
  2820     CleanupStack::PopAndDestroy( &allInstances );  
       
  2821     return previousTime;
       
  2822     }
       
  2823 
       
  2824 // -----------------------------------------------------------------------------
       
  2825 // CCalenEditorDataHandler::GetNextInstanceForRepeatOtherL()
       
  2826 // Returns the time of the next instance of a particular repeating entry
       
  2827 // (other items were commented in a header).
       
  2828 // -----------------------------------------------------------------------------
       
  2829 //
       
  2830 TTime CCalenEditorDataHandler::GetNextInstanceForRepeatOtherL( CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange )
       
  2831     {
       
  2832 	RPointerArray<CCalInstance> allInstances;
       
  2833     CleanupResetAndDestroyPushL( allInstances );
       
  2834     
       
  2835     TInt filter;
       
  2836     // Get the entry type to be filtered
       
  2837     switch( aEntry.EntryTypeL() )
       
  2838         {
       
  2839     	case CCalEntry::EAppt:
       
  2840     		filter = CalCommon::EIncludeAppts;
       
  2841     		break;
       
  2842     	case CCalEntry::ETodo:
       
  2843     		filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos;
       
  2844     		break;
       
  2845     	case CCalEntry::EEvent:
       
  2846     		filter = CalCommon::EIncludeEvents;
       
  2847     		break;
       
  2848     	case CCalEntry::EReminder:
       
  2849     		filter = CalCommon::EIncludeReminder;
       
  2850     		break;
       
  2851     	case CCalEntry::EAnniv:
       
  2852     		filter = CalCommon::EIncludeAnnivs;
       
  2853     		break;
       
  2854     	default:
       
  2855     		filter = CalCommon::EIncludeAll;
       
  2856     		break;
       
  2857         };
       
  2858     
       
  2859     iServices.InstanceViewL()->FindInstanceL( allInstances, 
       
  2860                                      ( CalCommon::TCalViewFilterFlags )filter,
       
  2861                                      timeRange);
       
  2862                                      
       
  2863     TTime nextTime = Time::NullTTime();
       
  2864     
       
  2865 	TInt i( 0 );
       
  2866     for( ; i < allInstances.Count(); i++ )
       
  2867         {
       
  2868         if( allInstances[i]->Entry().UidL() == aEntry.UidL() )
       
  2869             {
       
  2870             TRACE_EXIT_POINT;
       
  2871             nextTime = allInstances[i]->Time().TimeLocalL();
       
  2872             break;
       
  2873             }
       
  2874         }
       
  2875   
       
  2876     CleanupStack::PopAndDestroy( &allInstances );  
       
  2877     return nextTime;
       
  2878     }
       
  2879 
       
  2880 // -----------------------------------------------------------------------------
       
  2881 // CCalenEditorDataHandler::SetEntryType
       
  2882 // add attachments to the entry as ccalattachments
       
  2883 // -----------------------------------------------------------------------------
       
  2884 //
       
  2885 void CCalenEditorDataHandler::SetEntryType( CCalEntry::TType aNewEntryType )
       
  2886     {
       
  2887     iEntryType = aNewEntryType;
       
  2888     }
       
  2889 
       
  2890 // -----------------------------------------------------------------------------
       
  2891 // CCalenEditorDataHandler::AddAttachementsToEntryL
       
  2892 // add attachments to the entry as ccalattachments
       
  2893 // -----------------------------------------------------------------------------
       
  2894 //
       
  2895 void CCalenEditorDataHandler::AddAttachementsToEntryL()
       
  2896     {
       
  2897     TRACE_ENTRY_POINT;
       
  2898     
       
  2899     // Get the list of attachments from model and add them to entry
       
  2900     RPointerArray<CCalenAttachmentInfo> attachmentInfoList;
       
  2901     iServices.GetAttachmentData()->GetAttachmentListL( attachmentInfoList );
       
  2902     TInt attachmentCount = iEntry.AttachmentCountL();
       
  2903     TInt modelCount = attachmentInfoList.Count();
       
  2904     
       
  2905     if( attachmentCount > 0 && modelCount == 0 )
       
  2906         {
       
  2907         // This means that all the attachments in the entry have been deleted
       
  2908         // by the user. So remove all attchments from the entry
       
  2909         for( int index = 0 ; index < attachmentCount ; index++ )
       
  2910             {
       
  2911             iEntry.DeleteAttachmentL( *iEntry.AttachmentL( 0 ) );
       
  2912             }
       
  2913         
       
  2914         // No attachments need to be added at this point, we can simply return.
       
  2915         attachmentInfoList.Close();
       
  2916         TRACE_EXIT_POINT;
       
  2917         return;
       
  2918         }
       
  2919     
       
  2920     // Delete all the attachmenst of the entry which are not present in the model
       
  2921     TInt currentIndex = 0;
       
  2922     for( TInt index=0; index < attachmentCount; index++ )
       
  2923        {
       
  2924        CCalAttachment* attachment = iEntry.AttachmentL( currentIndex );
       
  2925        TBool matchFound = EFalse;
       
  2926        for( int modelIndex = 0 ; modelIndex < modelCount ; modelIndex++ )
       
  2927            {
       
  2928            CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[ modelIndex ];
       
  2929            if( attachmentInfo->StoreType() == 
       
  2930                CCalenAttachmentInfo::ECalenAttachmentFetchedFromEntry )
       
  2931                {
       
  2932                // We are only interested in those attachments which have been
       
  2933                // fetched from the entry because any newly added attachments
       
  2934                // will not yet be updated in the entry
       
  2935                RFile attachmentHandle;
       
  2936                CleanupClosePushL( attachmentHandle );
       
  2937                attachment->FileAttachment()->FetchFileHandleL( attachmentHandle );
       
  2938                
       
  2939                TFileName systemFileName;
       
  2940                attachmentHandle.FullName( systemFileName );
       
  2941                
       
  2942                if( systemFileName == attachmentInfo->SystemFileName() )
       
  2943                    {
       
  2944                    // There is an attachment in the model which matches the
       
  2945                    // attachment in the entry. So do not delete it
       
  2946                    matchFound = ETrue;
       
  2947                    CleanupStack::PopAndDestroy( &attachmentHandle );
       
  2948                    break;
       
  2949                    }
       
  2950                CleanupStack::PopAndDestroy( &attachmentHandle );
       
  2951                }
       
  2952            }
       
  2953        if( !matchFound )
       
  2954            {
       
  2955            // There is no matching attachment in the model. Delete it from entry
       
  2956            // This will compress the attachment array. Hence do not increment the currentIndex
       
  2957            iEntry.DeleteAttachmentL( *iEntry.AttachmentL( currentIndex ) );
       
  2958            }
       
  2959        else
       
  2960            {
       
  2961            // Move to the next attachment
       
  2962            currentIndex++;
       
  2963            }
       
  2964        }
       
  2965     
       
  2966     // Now add the remaining newly added attachments to the entry
       
  2967     for( TInt index=0 ; index< modelCount ; index++ )
       
  2968         {
       
  2969         CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[ index ];
       
  2970         if( attachmentInfo->StoreType() == CCalenAttachmentInfo::ECalenNewAttachment )
       
  2971             {
       
  2972             TParsePtrC fileNameParser(attachmentInfo->FileName());
       
  2973             RFile fileHandle;
       
  2974             CEikonEnv* eikonEnv = CEikonEnv::Static();
       
  2975             RFs& fs = eikonEnv->FsSession();
       
  2976             User::LeaveIfError(fs.ShareProtected());
       
  2977             
       
  2978             TInt err = fileHandle.Open( fs, attachmentInfo->FileName(), EFileWrite );
       
  2979             if( KErrNone != err )
       
  2980                 {
       
  2981                 attachmentInfoList.Close();
       
  2982                 TRACE_EXIT_POINT;
       
  2983                 return;
       
  2984                 }
       
  2985             CleanupClosePushL(fileHandle);
       
  2986             
       
  2987             CCalAttachment* attachment = CCalAttachment::NewFileL(fileHandle);
       
  2988             CleanupStack::PopAndDestroy(&fileHandle); 
       
  2989             
       
  2990             CleanupStack::PushL( attachment );
       
  2991             // Sets the label for the attachment
       
  2992             attachment->SetLabelL( fileNameParser.NameAndExt() );
       
  2993             // Sets mime type for the attachment
       
  2994             attachment->SetMimeTypeL( attachmentInfo->DataType().Des8() );
       
  2995             attachment->SetAttribute(CCalAttachment::EExportInline);
       
  2996             iEntry.AddAttachmentL( *attachment );
       
  2997             CleanupStack::Pop( attachment );
       
  2998             }                
       
  2999         }
       
  3000     attachmentInfoList.Close();
       
  3001    
       
  3002     TRACE_EXIT_POINT;
       
  3003     }
       
  3004 
       
  3005 
       
  3006 // -----------------------------------------------------------------------------
       
  3007 // CCalenEditorDataHandler::SetCalendarFieldEditedL
       
  3008 // Set if calendar is been edited or not with previous and current collection id
       
  3009 // -----------------------------------------------------------------------------
       
  3010 //
       
  3011 void CCalenEditorDataHandler::SetCalendarFieldEditedL(TBool aEdited , 
       
  3012                                                             TCalCollectionId aPreviousDbColId,
       
  3013                                                             TCalCollectionId aCurrentDbColId)
       
  3014     {
       
  3015     TRACE_ENTRY_POINT
       
  3016     iCalendarFieldEdited = aEdited;
       
  3017     iPreviousDbColId = aPreviousDbColId;
       
  3018     iCurrentDbColId = aCurrentDbColId;
       
  3019     TRACE_EXIT_POINT
       
  3020     }
       
  3021 
       
  3022 // -----------------------------------------------------------------------------
       
  3023 // CCalenEditorDataHandler::PreviousDbCollectionId
       
  3024 // Get previous collection id
       
  3025 // -----------------------------------------------------------------------------
       
  3026 //
       
  3027 TCalCollectionId CCalenEditorDataHandler::PreviousDbCollectionId()
       
  3028     {
       
  3029     TRACE_ENTRY_POINT
       
  3030     TRACE_EXIT_POINT
       
  3031     return iPreviousDbColId;
       
  3032     }
       
  3033 
       
  3034 // -----------------------------------------------------------------------------
       
  3035 // CCalenEditorDataHandler::CurrentDbCollectionId
       
  3036 // Get current collection id 
       
  3037 // -----------------------------------------------------------------------------
       
  3038 //
       
  3039 TCalCollectionId CCalenEditorDataHandler::CurrentDbCollectionId()
       
  3040     {
       
  3041     TRACE_ENTRY_POINT
       
  3042     TRACE_EXIT_POINT
       
  3043     return iCurrentDbColId;
       
  3044     }
       
  3045 
       
  3046 // -----------------------------------------------------------------------------
       
  3047 // CCalenEditorDataHandler::CalenInstanceId
       
  3048 // Returns the instance id.
       
  3049 // (other items were commented in a header).
       
  3050 // -----------------------------------------------------------------------------
       
  3051 //
       
  3052 const TCalenInstanceId CCalenEditorDataHandler::CalenInstanceId()
       
  3053     {
       
  3054     TRACE_ENTRY_POINT;
       
  3055     
       
  3056     TRACE_EXIT_POINT;
       
  3057     
       
  3058     return iInstanceId;
       
  3059     }
       
  3060 	
       
  3061 // End of file	--Don't remove this.