calendarui/editors/src/CalenEditorDataHandler.cpp
branchRCL_3
changeset 30 bd7edf625bdd
child 31 97232defd20e
equal deleted inserted replaced
29:12af337248b1 30:bd7edf625bdd
       
     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             TTime startDate = Edited().StartDateTime();
       
   794             TTime endDate = Edited().EndDateTime();
       
   795             // In case AllDay event end at "12:00am" 24/06/2009. 
       
   796             // editor should display EndDate as 23/06/2009.
       
   797             if(Edited().IsAllDayEvent())
       
   798                 {
       
   799                 if( endDate > startDate )
       
   800                     {
       
   801                     endDate -= TTimeIntervalDays( 1 );
       
   802                     if( endDate < startDate )
       
   803                         {
       
   804                         endDate = startDate;
       
   805                         }
       
   806                     }
       
   807                 }
       
   808             TTimeIntervalDays durDays = endDate.DaysFrom( startDate);
       
   809             isError = durDays >= TTimeIntervalDays(1);
       
   810             break;
       
   811             }
       
   812         case ERepeatWeekly:
       
   813             {
       
   814             TTimeIntervalDays durDays = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() );
       
   815             isError = durDays >= TTimeIntervalDays(7);
       
   816             break;
       
   817             }
       
   818         case ERepeatBiWeekly:
       
   819             {
       
   820             TTimeIntervalDays durDays = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() );
       
   821             isError = durDays >= TTimeIntervalDays(14);
       
   822             break;
       
   823             }
       
   824         case ERepeatMonthly:
       
   825             {
       
   826             TTimeIntervalMonths durMonths = Edited().EndDateTime().MonthsFrom( Edited().StartDateTime() );
       
   827             isError = durMonths >= TTimeIntervalMonths(1);
       
   828             break;
       
   829             }
       
   830         case ERepeatYearly:
       
   831             {
       
   832             TTimeIntervalYears durYears = Edited().EndDateTime().YearsFrom( Edited().StartDateTime() );
       
   833             isError = durYears >= TTimeIntervalYears(1);
       
   834             break;
       
   835             }
       
   836         case ERepeatOther:
       
   837 		    {
       
   838             isError = EFalse;
       
   839             break;
       
   840 			}
       
   841         default:
       
   842             // Not repeating, no error
       
   843             isError = EFalse;
       
   844             break;
       
   845         }
       
   846     TRACE_EXIT_POINT;
       
   847     return isError;
       
   848     }
       
   849 
       
   850 // -----------------------------------------------------------------------------
       
   851 // CCalenEditorDataHandler::CheckErrorsForThisAndAllL
       
   852 // Check for errors in the form. This function should only be called when the
       
   853 // user has decided they want to edit "This and all" from a prompt, or when the
       
   854 // entry is not repeating.
       
   855 // (other items were commented in a header).
       
   856 // -----------------------------------------------------------------------------
       
   857 //
       
   858 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckErrorsForThisAndAllL()
       
   859     {
       
   860     TRACE_ENTRY_POINT;
       
   861 
       
   862     // From UI spec:
       
   863     //   5 checks is specified, only one not needed in this phase is 2.1
       
   864 
       
   865     const TTime start = Edited().StartDateTime();
       
   866     const TTime end = Edited().EndDateTime();
       
   867 
       
   868     // 1) Check that entry doesn't end earlier than it starts
       
   869     if ( end < start )
       
   870         {
       
   871         TRACE_EXIT_POINT;
       
   872         return CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime;
       
   873         }
       
   874 
       
   875     // 2) Repeating entry checks:
       
   876     if ( Edited().IsRepeating() )
       
   877         {
       
   878         //    2.1) Check that repeat until date is a) later than start date (for new notes)
       
   879         //                                         b) not before start date (for existing notes)
       
   880         TTime repeatUntilDay = CalenDateUtils::BeginningOfDay(
       
   881             Edited().RepeatUntilDateTime() );
       
   882 
       
   883         TTime repeatStartDay;
       
   884 
       
   885         // if new note or old note isnt repeating
       
   886         //   edited.repeatUntil date must be greater than edited.start date
       
   887         // else
       
   888         //   if IsRepeatRuleEdited or IsStartDateTimeEdited 
       
   889         //     //(either one above will make a new rule in which edited.startdate is the start date)
       
   890         //     edited.repeatUntil must be greater than edited.start date
       
   891         //   else
       
   892         //     edited.repeatUntil must be greater than start date on disk
       
   893 
       
   894         TCalRRule rrule;
       
   895         if( IsCreatingNew() || 
       
   896             !Entry().GetRRuleL(rrule) ||
       
   897             IsRepeatRuleEdited() || 
       
   898             IsStartDateTimeEdited() )
       
   899             {
       
   900             // We don't have an rrule so we can't get the rrule start date,
       
   901             // or user has edited a field that will cause new start date to be used in the new rule.
       
   902             // Use the edited entry's start date.
       
   903             repeatStartDay = CalenDateUtils::BeginningOfDay( start );
       
   904             }
       
   905         else
       
   906             {
       
   907             // original rrule is valid and new rule will not be created
       
   908             repeatStartDay = CalenDateUtils::BeginningOfDay( rrule.DtStart().TimeLocalL() );
       
   909             }
       
   910 
       
   911         if ( repeatUntilDay <= repeatStartDay )
       
   912             {
       
   913             TRACE_EXIT_POINT;
       
   914             return CCalenEditorDataHandler::EFormErrRepeatUntilEarlierThanNote;
       
   915             }
       
   916 
       
   917         if( DurationGreaterThanRepeatIntervalError() )
       
   918             {
       
   919             TRACE_EXIT_POINT;
       
   920             return CCalenEditorDataHandler::EFormErrDurationGreaterThanRepeatInterval;
       
   921             }
       
   922         // 3) Alarm field checks:
       
   923         TRACE_EXIT_POINT;
       
   924         return CheckAlarmFieldsForErrorsL(ETrue); // user editing the series
       
   925         }
       
   926 
       
   927     // 3) Alarm field checks:
       
   928     TRACE_EXIT_POINT;
       
   929     return CheckAlarmFieldsForErrorsL(); // user editing the series
       
   930     }
       
   931 
       
   932 // -----------------------------------------------------------------------------
       
   933 // CCalenEditorDataHandler::CheckErrorsForThisOnlyL
       
   934 // Check for errors in the form. This function should only be called when the
       
   935 // user has decided they want to edit "This only" from a prompt, or when the
       
   936 // entry is an exception.
       
   937 // (other items were commented in a header).
       
   938 // -----------------------------------------------------------------------------
       
   939 //
       
   940 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckErrorsForThisOnlyL( CCalEntry& /*aParentEntry*/,
       
   941                                                                                   CCalInstanceView& /*aInstanceView*/ )
       
   942     {
       
   943     TRACE_ENTRY_POINT;
       
   944 
       
   945     const TTime start = Edited().StartDateTime();
       
   946     const TTime end = Edited().EndDateTime();
       
   947 
       
   948     // Check that entry doesn't end earlier than it starts
       
   949     if ( end < start )
       
   950         {
       
   951         TRACE_EXIT_POINT;
       
   952         return CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime;
       
   953         }
       
   954 
       
   955     TError error = CheckForOutOfSequenceL();
       
   956 
       
   957     if( error != EFormErrNone )
       
   958         {
       
   959         return error;
       
   960         }
       
   961 
       
   962     // Alarm field checks:
       
   963     TRACE_EXIT_POINT;
       
   964     return CheckAlarmFieldsForErrorsL(); // user creating/editing an exception
       
   965     }
       
   966 
       
   967 // -----------------------------------------------------------------------------
       
   968 // CCalenEditorDataHandler::CheckForOutOfSequenceL
       
   969 // Checks to see if the instance is being moved out of sequence, relative to
       
   970 // the rest of the series.
       
   971 // (other items were commented in a header).
       
   972 // -----------------------------------------------------------------------------
       
   973 //
       
   974 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckForOutOfSequenceL()
       
   975     {
       
   976     TRACE_ENTRY_POINT;
       
   977     // Only perform the checks when we change the start or end time of the meeting.
       
   978     if( !IsStartDateTimeEdited() && !IsEndDateTimeEdited() )
       
   979         {
       
   980         TRACE_EXIT_POINT;
       
   981         return EFormErrNone;
       
   982         }
       
   983 
       
   984     TCalTime prevStart, prevEnd;
       
   985 
       
   986     GetPreviousInstanceTimeL( prevStart, prevEnd );
       
   987 
       
   988     if( prevStart.TimeLocalL() != Time::NullTTime() )
       
   989         {
       
   990         // Does the exception end on/after prevEnd?
       
   991         if( Edited().StartDateTime() < prevEnd.TimeLocalL() )
       
   992             {
       
   993             // Does the exception start after prevStart?
       
   994             if( Edited().StartDateTime() > prevStart.TimeLocalL() )
       
   995                 {
       
   996                 TRACE_EXIT_POINT;
       
   997                 return EFormErrOverlapsExistingInstance;
       
   998                 }
       
   999             else
       
  1000                 {
       
  1001                 // Does the exception finish after prevStart?
       
  1002                 if( Edited().EndDateTime() > prevStart.TimeLocalL() )
       
  1003                     {
       
  1004                     TRACE_EXIT_POINT;
       
  1005                     return EFormErrOverlapsExistingInstance;
       
  1006                     }
       
  1007                 else
       
  1008                     {
       
  1009                     TRACE_EXIT_POINT;
       
  1010                     return EFormErrOutOfSequence;
       
  1011                     }
       
  1012                 }
       
  1013             }
       
  1014 
       
  1015         // Does the exception start on the same day as prevStart?
       
  1016         if( CalenDateUtils::OnSameDay( Edited().StartDateTime(), prevStart.TimeLocalL() ) )
       
  1017             {
       
  1018             TRACE_EXIT_POINT;
       
  1019             return EFormErrInstanceAlreadyExistsOnThisDay;
       
  1020             }
       
  1021         }
       
  1022 
       
  1023     TCalTime nextStart, nextEnd;
       
  1024 
       
  1025     GetNextInstanceTimeL( nextStart, nextEnd );
       
  1026 
       
  1027     if( nextStart.TimeLocalL() != Time::NullTTime() )
       
  1028         {
       
  1029         // Does the exception finish on/before nextStart?
       
  1030         if( Edited().EndDateTime() > nextStart.TimeLocalL() )
       
  1031             {
       
  1032             // Does the exception finish before nextFinish?
       
  1033             if( Edited().EndDateTime() < nextEnd.TimeLocalL() )
       
  1034                 {
       
  1035                 TRACE_EXIT_POINT;
       
  1036                 return EFormErrOverlapsExistingInstance;
       
  1037                 }
       
  1038             else
       
  1039                 {
       
  1040                 // Does the exception start before nextFinish?
       
  1041                 if( Edited().StartDateTime() < nextEnd.TimeLocalL() )
       
  1042                     {
       
  1043                     TRACE_EXIT_POINT;
       
  1044                     return EFormErrOverlapsExistingInstance;
       
  1045                     }
       
  1046                 else
       
  1047                     {
       
  1048                     TRACE_EXIT_POINT;
       
  1049                     return EFormErrOutOfSequence;
       
  1050                     }
       
  1051                 }
       
  1052             }
       
  1053 
       
  1054         // Does the exception start on the same day as nextStart?
       
  1055         if( CalenDateUtils::OnSameDay( Edited().StartDateTime(), nextStart.TimeLocalL() ) )
       
  1056             {
       
  1057             TRACE_EXIT_POINT;
       
  1058             return EFormErrInstanceAlreadyExistsOnThisDay;
       
  1059             }
       
  1060         }
       
  1061 
       
  1062     // Does the series have any rdates
       
  1063     RArray<TCalTime> rDateArray;
       
  1064     CleanupClosePushL( rDateArray );
       
  1065     Entry().GetRDatesL( rDateArray );
       
  1066     TInt rDateCount = rDateArray.Count();
       
  1067 
       
  1068     if ( rDateCount > 0 )
       
  1069         {
       
  1070         // If the series has rdates, check that the exception
       
  1071         // does not overlap or start on the same day
       
  1072         const TTime& startDateTime = Edited().StartDateTime();
       
  1073         const TTime& endDateTime = Edited().EndDateTime();
       
  1074         TTimeIntervalMinutes duration;
       
  1075         startDateTime.MinutesFrom( endDateTime, duration );
       
  1076 
       
  1077         for ( TInt index = 0; index < rDateCount; index++ )
       
  1078             {
       
  1079             const TTime& rDate = rDateArray[ index ].TimeLocalL();
       
  1080 
       
  1081             if ( !CalenDateUtils::OnSameDay( Original().StartDateTime(), rDate ) )
       
  1082                 {
       
  1083                 // Does the exception start or end on the same day as a rdate.
       
  1084                 if ( CalenDateUtils::OnSameDay( startDateTime, rDate ) )
       
  1085                     {
       
  1086                     CleanupStack::PopAndDestroy(); // rDateArray
       
  1087                     TRACE_EXIT_POINT;
       
  1088                     return EFormErrInstanceAlreadyExistsOnThisDay;
       
  1089                     }
       
  1090 
       
  1091                 // Does the exception overlap an rdate?
       
  1092                 TTime rDateEnd = rDate + duration;
       
  1093                 if ( endDateTime > rDateEnd && startDateTime < rDate )
       
  1094                     {
       
  1095                     CleanupStack::PopAndDestroy(); // rDateArray
       
  1096                     TRACE_EXIT_POINT;
       
  1097                     return EFormErrOverlapsExistingInstance;
       
  1098                     }
       
  1099                 }
       
  1100             }
       
  1101         }
       
  1102 
       
  1103     CleanupStack::PopAndDestroy(); // rDateArray
       
  1104     TRACE_EXIT_POINT;
       
  1105     return EFormErrNone;
       
  1106     }
       
  1107 
       
  1108 // -----------------------------------------------------------------------------
       
  1109 // CCalenEditorDataHandler::GetPreviousInstanceTimeL
       
  1110 // Gets the start and end times of the previous instance. Sets both to a null
       
  1111 // time if there is no instance before the current one
       
  1112 // (other items were commented in a header).
       
  1113 // -----------------------------------------------------------------------------
       
  1114 //
       
  1115 void CCalenEditorDataHandler::GetPreviousInstanceTimeL( TCalTime& aPreviousStartTime,
       
  1116                                                         TCalTime& aPreviousEndTime )
       
  1117     {
       
  1118     TRACE_ENTRY_POINT;
       
  1119 
       
  1120     aPreviousStartTime.SetTimeLocalL( Time::NullTTime() );
       
  1121     aPreviousEndTime.SetTimeLocalL( Time::NullTTime() );
       
  1122 
       
  1123     RPointerArray<CCalEntry> entries;
       
  1124     CleanupResetAndDestroyPushL(entries);
       
  1125 
       
  1126     EntryViewL().FetchL( Entry().UidL(), entries );
       
  1127 
       
  1128     TCalTime currentInstanceDate = Entry().RecurrenceIdL();
       
  1129     if( currentInstanceDate.TimeUtcL() == Time::NullTTime() )
       
  1130         {
       
  1131         // We must be creating a new exception. Calculate the recurrence id.
       
  1132         TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( entries[0]->StartTimeL().TimeLocalL() );
       
  1133         TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1134         currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1135         }
       
  1136 
       
  1137     TCalRRule rrule;
       
  1138     if( entries[0]->GetRRuleL(rrule) )
       
  1139         {
       
  1140         TCalenRepeatIndex repeatIndex = CalenNoteDataUtil::RepeatIndexL( *entries[0] );
       
  1141         TBool keepLooking = ETrue;
       
  1142         RArray<TCalTime> exdates;
       
  1143         CleanupClosePushL( exdates );
       
  1144         entries[0]->GetExceptionDatesL(exdates);
       
  1145         
       
  1146         // Needed for case ERepeatOther
       
  1147         TCalRRule::TType type( rrule.Type() );
       
  1148         TInt repeatInterval( rrule.Interval() );
       
  1149         TCalTime start, end;
       
  1150         TTime previousInstanceTime = Time::NullTTime(); 
       
  1151         
       
  1152         while( keepLooking )
       
  1153             {
       
  1154             // Subtract the repeat interval of the parent.
       
  1155             switch( repeatIndex )
       
  1156                 {
       
  1157                 case ERepeatDaily:
       
  1158                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(1) );
       
  1159                     break;
       
  1160                 case ERepeatWeekly:
       
  1161                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7) );
       
  1162                     break;
       
  1163                 case ERepeatBiWeekly:
       
  1164                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(14) );
       
  1165                     break;
       
  1166                 case ERepeatMonthly:
       
  1167                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalMonths(1) );
       
  1168                     break;
       
  1169                 case ERepeatYearly:
       
  1170                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalYears(1) );
       
  1171                     break;
       
  1172                 case ERepeatWorkdays:
       
  1173                     currentInstanceDate.SetTimeLocalL(currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7) );
       
  1174                 case ERepeatOther:
       
  1175                 	/* This case includes repeating events like: 3 days every week, 3rd weekday of everymonth
       
  1176                 	   that does not fall in any cases above but still have repeating rule*/
       
  1177                 	   
       
  1178                 	 // Check if the current entry being edited is child entry
       
  1179           			 // If yes, then put back the child entry time to currentInstanceDate  
       
  1180 				     if(Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime() )
       
  1181                 	 	{
       
  1182                 	 	 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( Entry().StartTimeL().TimeLocalL() );
       
  1183         				 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1184         				 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1185                 	 	}
       
  1186              
       
  1187                 	 switch( type )
       
  1188                 	 {
       
  1189                 	 	case TCalRRule::EDaily:
       
  1190                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(1 * repeatInterval));
       
  1191                 	 		break;
       
  1192                 	 	case TCalRRule::EWeekly:
       
  1193                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7 * repeatInterval));
       
  1194                 	 		break;
       
  1195                 	 	case TCalRRule::EMonthly: 
       
  1196                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1197                 	 		// can go beuong 30 days. Ex: Every third wednesday of every month 
       
  1198                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalMonths(repeatInterval)-TTimeIntervalDays(7 * repeatInterval));
       
  1199                 	 		break;
       
  1200                 	 	case TCalRRule::EYearly:  
       
  1201                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1202                 	 		// can go beuong 365 days. Ex: Every third wednesday of September of every year
       
  1203                 	 		start.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalYears(repeatInterval)-TTimeIntervalDays(7 * repeatInterval));
       
  1204                 	 		break;
       
  1205                 	 }
       
  1206                 	 
       
  1207                 	 end.SetTimeLocalL(CalenDateUtils::BeginningOfDay(currentInstanceDate.TimeLocalL()));
       
  1208                      previousInstanceTime = GetPreviousInstanceForRepeatOtherL(*entries[0], CalCommon::TCalTimeRange( start, end));
       
  1209                      currentInstanceDate.SetTimeLocalL( previousInstanceTime);
       
  1210                      break;
       
  1211                 default:
       
  1212                 case ERepeatNotRepeated:
       
  1213                     keepLooking = EFalse;
       
  1214                     break;
       
  1215                 }
       
  1216 
       
  1217             // Is currentInstanceDate before parent dt start?
       
  1218             if( currentInstanceDate.TimeLocalL() < entries[0]->StartTimeL().TimeLocalL() )
       
  1219                 {
       
  1220                 // There are no instances before the exception
       
  1221                 keepLooking = EFalse;
       
  1222                 }
       
  1223             else
       
  1224                 {
       
  1225                 // Is there an exdate on currentInstanceDate?
       
  1226                 TBool isExdateOnDay = EFalse;
       
  1227                 for(TInt i=0; i<exdates.Count(); ++i)
       
  1228                     {
       
  1229                     if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1230                         {
       
  1231                         isExdateOnDay = ETrue;
       
  1232                         // There is an exdate - is there a child associated with the exdate?
       
  1233                         for(TInt j=1; j<entries.Count(); ++j)
       
  1234                             {
       
  1235                             if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1236                                 {
       
  1237                                 // This child is the previous instance.
       
  1238                                 aPreviousStartTime = entries[j]->StartTimeL();
       
  1239                                 aPreviousEndTime = entries[j]->EndTimeL();
       
  1240                                 keepLooking = EFalse;
       
  1241                                 }
       
  1242                             }
       
  1243                         break;
       
  1244                         }
       
  1245                     }
       
  1246 
       
  1247                 if( !isExdateOnDay )
       
  1248                     {
       
  1249                     // The instance exists and hasn't been deleted or made into an exception.
       
  1250                     // Use information from the parent to set the start/end times.
       
  1251                     aPreviousStartTime = currentInstanceDate;
       
  1252 
       
  1253                     TTimeIntervalMinutes duration;
       
  1254                     TTime start = entries[0]->StartTimeL().TimeLocalL();
       
  1255                     TTime end = entries[0]->EndTimeL().TimeLocalL(); 
       
  1256                     end.MinutesFrom( start, duration );
       
  1257                     aPreviousEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration );
       
  1258                     keepLooking = EFalse;
       
  1259                     }
       
  1260                 }
       
  1261             }
       
  1262         CleanupStack::PopAndDestroy( &exdates );
       
  1263         }
       
  1264 
       
  1265     CleanupStack::PopAndDestroy(&entries);
       
  1266 
       
  1267     TRACE_EXIT_POINT;
       
  1268     }
       
  1269 
       
  1270 // -----------------------------------------------------------------------------
       
  1271 // CCalenEditorDataHandler::GetNextInstanceTimeL
       
  1272 // Gets the start and end times of the next instance. Sets both to a null
       
  1273 // time if there is no instance after the current one.
       
  1274 // (other items were commented in a header).
       
  1275 // -----------------------------------------------------------------------------
       
  1276 //
       
  1277 void CCalenEditorDataHandler::GetNextInstanceTimeL( TCalTime& aNextStartTime,
       
  1278                                                     TCalTime& aNextEndTime )
       
  1279     {
       
  1280     TRACE_ENTRY_POINT;
       
  1281 
       
  1282     aNextStartTime.SetTimeLocalL( Time::NullTTime() );
       
  1283     aNextEndTime.SetTimeLocalL( Time::NullTTime() );
       
  1284 
       
  1285     RPointerArray<CCalEntry> entries;
       
  1286     CleanupResetAndDestroyPushL(entries);
       
  1287 
       
  1288     EntryViewL().FetchL( Entry().UidL(), entries );
       
  1289 
       
  1290     TCalTime currentInstanceDate = Entry().RecurrenceIdL();
       
  1291     if( currentInstanceDate.TimeUtcL() == Time::NullTTime() )
       
  1292         {
       
  1293         // We must be creating a new exception. Calculate the recurrence id.
       
  1294         TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( entries[0]->StartTimeL().TimeLocalL() );
       
  1295         TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1296         currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1297         }
       
  1298 
       
  1299     TCalRRule rrule;
       
  1300     if( entries[0]->GetRRuleL(rrule) )
       
  1301         {
       
  1302         TCalenRepeatIndex repeatIndex = CalenNoteDataUtil::RepeatIndexL( *entries[0] );
       
  1303         TBool keepLooking = ETrue;
       
  1304         RArray<TCalTime> exdates;
       
  1305         CleanupClosePushL( exdates );
       
  1306         entries[0]->GetExceptionDatesL(exdates);
       
  1307         
       
  1308         // Needed for case ERepeatOther
       
  1309         TCalRRule::TType type( rrule.Type() );
       
  1310         TInt repeatInterval( rrule.Interval() );
       
  1311         TCalTime start, end;
       
  1312         TTime nextInstanceTime = Time::NullTTime(); 
       
  1313         
       
  1314         while( keepLooking )
       
  1315             {
       
  1316             // Subtract the repeat interval of the parent.
       
  1317             switch( repeatIndex )
       
  1318                 {
       
  1319                 case ERepeatDaily:
       
  1320                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1) );
       
  1321                     break;
       
  1322                 case ERepeatWeekly:
       
  1323                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7) );
       
  1324                     break;
       
  1325                 case ERepeatBiWeekly:
       
  1326                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(14) );
       
  1327                     break;
       
  1328                 case ERepeatMonthly:
       
  1329                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalMonths(1) );
       
  1330                     break;
       
  1331                 case ERepeatYearly:
       
  1332                     currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalYears(1) );
       
  1333                     break;
       
  1334                 case ERepeatWorkdays:
       
  1335                     currentInstanceDate.SetTimeLocalL(currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7) );
       
  1336                     break;
       
  1337                 case ERepeatOther:
       
  1338                     {
       
  1339                 	/* This case includes repeating events like: 3 days every week, 3rd weekday of everymonth
       
  1340                 	   that does not fall in any cases above but still have repeating rule*/
       
  1341           			 
       
  1342           			 // Check if the current entry being edited is child entry
       
  1343           			 // If yes, then put back the child entry time to currentInstanceDate
       
  1344 				     if(Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime())
       
  1345                 	 	{
       
  1346                 	 	 TTimeIntervalMinutes timeOfDay = CalenDateUtils::TimeOfDay( Entry().StartTimeL().TimeLocalL() );
       
  1347         				 TTime beginningOfDay = CalenDateUtils::BeginningOfDay( InstanceDateTime().TimeLocalL() );
       
  1348         				 currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
       
  1349                 	 	}
       
  1350                 	 switch( type )
       
  1351                 	     {
       
  1352                 	 	case TCalRRule::EDaily:
       
  1353                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1 * repeatInterval));
       
  1354                 	 		break;
       
  1355                 	 	case TCalRRule::EWeekly:
       
  1356                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7 * repeatInterval));
       
  1357                 	 		break;
       
  1358                 	 	case TCalRRule::EMonthly:  
       
  1359                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1360                 	 		// can go beuong 30 days. Ex: Every third wednesday of every month
       
  1361                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalMonths(repeatInterval)+TTimeIntervalDays(7 * repeatInterval));
       
  1362                 	 		break;
       
  1363                 	 	case TCalRRule::EYearly:  
       
  1364                 	 		// Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
       
  1365                 	 		// can go beuong 365 days. Ex: Every third wednesday of September of every year
       
  1366                 	 		end.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalYears(repeatInterval)+TTimeIntervalDays(7 * repeatInterval));
       
  1367                 	 		break;
       
  1368                 	     }
       
  1369                 	 
       
  1370                 	 start.SetTimeLocalL(CalenDateUtils::BeginningOfDay(currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1)));
       
  1371                 	 
       
  1372                      nextInstanceTime = GetNextInstanceForRepeatOtherL(*entries[0], CalCommon::TCalTimeRange( start, end));
       
  1373                      currentInstanceDate.SetTimeLocalL( nextInstanceTime);
       
  1374                      break;
       
  1375                     }
       
  1376                 case ERepeatNotRepeated:
       
  1377                     keepLooking = EFalse;
       
  1378                     break;
       
  1379                 default:
       
  1380                     break;
       
  1381                 }
       
  1382 
       
  1383             // Is currentInstanceDate after parent dt end?
       
  1384             if( currentInstanceDate.TimeLocalL() > rrule.Until().TimeLocalL() )
       
  1385                 {
       
  1386                 // There are no instances before the exception
       
  1387                 keepLooking = EFalse;
       
  1388                 }
       
  1389             else
       
  1390                 {
       
  1391                 // Is there an exdate on currentInstanceDate?
       
  1392                 TBool isExdateOnDay = EFalse;
       
  1393                 for(TInt i=0; i<exdates.Count(); ++i)
       
  1394                     {
       
  1395                     if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1396                         {
       
  1397                         isExdateOnDay = ETrue;
       
  1398                         // There is an exdate - is there a child associated with the exdate?
       
  1399                         for(TInt j=1; j<entries.Count(); ++j)
       
  1400                             {
       
  1401                             if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() )
       
  1402                                 {
       
  1403                                 // This child is the previous instance.
       
  1404                                 aNextStartTime = entries[j]->StartTimeL();
       
  1405                                 aNextEndTime = entries[j]->EndTimeL();
       
  1406                                 keepLooking = EFalse;
       
  1407                                 }
       
  1408                             }
       
  1409                         break;
       
  1410                         }
       
  1411                     }
       
  1412                 
       
  1413                 if( !isExdateOnDay )
       
  1414                     {
       
  1415                     // The instance exists and hasn't been deleted or made into an exception.
       
  1416                     // Use information from the parent to set the start/end times.
       
  1417                     aNextStartTime = currentInstanceDate;
       
  1418 
       
  1419                     TTimeIntervalMinutes duration;
       
  1420                     TTime start = entries[0]->StartTimeL().TimeLocalL();
       
  1421                     TTime end = entries[0]->EndTimeL().TimeLocalL();
       
  1422                     end.MinutesFrom( start, duration );
       
  1423                     aNextEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration );
       
  1424                     keepLooking = EFalse;
       
  1425                     }
       
  1426                 }
       
  1427             }
       
  1428         CleanupStack::PopAndDestroy( &exdates );
       
  1429         }
       
  1430 
       
  1431     CleanupStack::PopAndDestroy(&entries);
       
  1432 
       
  1433     TRACE_EXIT_POINT;
       
  1434     }
       
  1435 
       
  1436 // -----------------------------------------------------------------------------
       
  1437 // CCalenEditorDataHandler::CheckAlarmFieldsForErrorsL
       
  1438 // Check the alarm fields for errors. Returns the error if found, or
       
  1439 // EFormErrNone if no error found.
       
  1440 // (other items were commented in a header).
       
  1441 // -----------------------------------------------------------------------------
       
  1442 //
       
  1443 CCalenEditorDataHandler::TError CCalenEditorDataHandler::CheckAlarmFieldsForErrorsL(TBool aSeries)
       
  1444     {
       
  1445     TRACE_ENTRY_POINT;
       
  1446 
       
  1447     TError error = EFormErrNone;
       
  1448     // If alarm not active, no check
       
  1449     if ( Edited().IsAlarmActivated() )
       
  1450         {
       
  1451         TTime alarm     = Edited().AlarmDateTime();
       
  1452         TTime startTime = Edited().StartDateTime();
       
  1453         TTime now(Time::NullTTime());
       
  1454         now.HomeTime();
       
  1455 
       
  1456         if(IsAlarmInAcceptablePeriod(error, alarm, startTime))
       
  1457             {
       
  1458             // ask form (not iEntry) if it is repeating
       
  1459             // if we launched an old exception, then form has no repeat field
       
  1460             // if creating a new exception, then form has repeat field
       
  1461             TBool EventIsInFuture = (IsTimedEntry() && (startTime > now)) ||
       
  1462                                     (!IsTimedEntry() && (startTime.DaysFrom(now) >= TTimeIntervalDays(0)));
       
  1463             if( !aSeries && (alarm < now) && ( iEdited->EntryType()!=CCalEntry::EAnniv ) )
       
  1464                 {
       
  1465                 // dont let non-repeating future entries have alarms in past
       
  1466             	error = EFormErrAlarmTimePast;
       
  1467                 }
       
  1468             /*  otherwise, save alarm to past:
       
  1469              *   new/old non-repeating & in past
       
  1470              *  repeating new/old repeating in past/future
       
  1471              */
       
  1472             }
       
  1473         }
       
  1474 
       
  1475     TRACE_EXIT_POINT;
       
  1476     return error;
       
  1477     }
       
  1478 
       
  1479 // -----------------------------------------------------------------------------
       
  1480 // CCalenEditorDataHandler::IsAlarmInAcceptablePeriod
       
  1481 // Check alarm time validity
       
  1482 // (other items were commented in a header).
       
  1483 // -----------------------------------------------------------------------------
       
  1484 //
       
  1485 TBool CCalenEditorDataHandler::IsAlarmInAcceptablePeriod(TError& aError, 
       
  1486 const TTime& aAlarmTime, const TTime& aStartTime) const
       
  1487     {
       
  1488     TRACE_ENTRY_POINT;
       
  1489 
       
  1490     TTime upperLimit = IsTimedEntry() ? 
       
  1491                        aStartTime : 
       
  1492                        CalenDateUtils::BeginningOfDay(aStartTime) + TTimeIntervalDays(1);
       
  1493     TTime lowerLimit = aStartTime - TTimeIntervalDays(31);
       
  1494     TBool acceptable = ETrue;
       
  1495     if(aAlarmTime < lowerLimit)
       
  1496         {
       
  1497         acceptable = EFalse;
       
  1498         aError = EFormErrAlarmDateTooManyDaysBeforeNote;
       
  1499         }
       
  1500     else if(aAlarmTime > upperLimit)
       
  1501         {
       
  1502         acceptable = EFalse;
       
  1503         aError = EFormErrAlarmTimeLaterThanNote;
       
  1504         }
       
  1505 
       
  1506     TRACE_EXIT_POINT;
       
  1507     return acceptable;
       
  1508     }
       
  1509 
       
  1510 // -----------------------------------------------------------------------------
       
  1511 // CCalenEditorDataHandler::ForceValidValuesL
       
  1512 // Force the form to use valid values. This function gets called when the user
       
  1513 // forces the application to exit, for example by pressing the off button.
       
  1514 // We attempt to save as much data as possible from the form.
       
  1515 // (other items were commented in a header).
       
  1516 // -----------------------------------------------------------------------------
       
  1517 //
       
  1518 void CCalenEditorDataHandler::ForceValidValuesL( CalCommon::TRecurrenceRange aRepeatTarget )
       
  1519     {
       
  1520     TRACE_ENTRY_POINT;
       
  1521 
       
  1522     // Checks and valid values are
       
  1523     // from S60 Calendar UI spec, chapter 4.6.4.1 Exiting Note Editor:
       
  1524 
       
  1525     // We modify values as we go, thus we can't pre-read fields.
       
  1526     // E.g. when start time is needed in check, it should be always read
       
  1527     // from model, because previous check might have modified it.
       
  1528 
       
  1529     //  2) if ends earlier than starts
       
  1530     if ( Edited().EndDateTime() < Edited().StartDateTime() )
       
  1531         {
       
  1532         //  a) (for new entry) set end time equal to start time
       
  1533         if ( IsCreatingNew() )
       
  1534             {
       
  1535             Edited().SetEndDateTimeL( Edited().StartDateTime() );
       
  1536             }
       
  1537         //  b) (for existing entries) replace with original end time
       
  1538         else
       
  1539             {
       
  1540             Edited().SetEndDateTimeL( Original().EndDateTime() );
       
  1541             // if still wrong, replace start time also
       
  1542             Edited().SetStartDateTimeL( Original().StartDateTime() );
       
  1543             }
       
  1544         } // END end < start check
       
  1545 
       
  1546     // 1) Alarm validation
       
  1547     if ( Edited().IsAlarmActivated() )
       
  1548         {
       
  1549         TTime now;
       
  1550         now.HomeTime();
       
  1551 
       
  1552         // Note: all three checks are done for each alarm.
       
  1553         // Alarm time is read always again, because modifications are done after each check
       
  1554 
       
  1555         //  1.1) a) if alarm more than 31 days before start, alarm is set 31 days before start
       
  1556         //       b) (for todos) - "" - before due date
       
  1557         TTime maxAlarmBeforeStart = Edited().StartDateTime() - TTimeIntervalDays( 31 );
       
  1558         if ( Edited().AlarmDateTime() < maxAlarmBeforeStart  )
       
  1559             {
       
  1560             Edited().SetAlarmDateTimeL( maxAlarmBeforeStart );
       
  1561             }
       
  1562 
       
  1563         //  1.2) a) (meetings) if alarm later than start, set it to default alarm time
       
  1564         //       b) (for todos & annivs) - "" - later than due date
       
  1565         TTime atLatest = Edited().StartDateTime();
       
  1566         if(!IsTimedEntry())
       
  1567             {
       
  1568             atLatest += TTimeIntervalDays(1); 
       
  1569             atLatest -= TTimeIntervalSeconds(1);
       
  1570             // at Latest for ToDo/Anniv would be DD @ 23:59:59
       
  1571             }
       
  1572         if( Edited().AlarmDateTime() > atLatest )
       
  1573             {            
       
  1574             SetDefaultAlarmDateTimeL();
       
  1575             }
       
  1576 
       
  1577         //  1.3) if alarm is set to passed time,
       
  1578         if ( Edited().AlarmDateTime() < now )
       
  1579             {
       
  1580             // a) it is set off for
       
  1581             //    - new/old NON-REPEATING entries
       
  1582             if (!Edited().IsRepeating() && Edited().EntryType() != CCalEntry::EAnniv )
       
  1583                 {
       
  1584                 Edited().SetAlarmOffL();
       
  1585                 }
       
  1586             // b) (for existing entries) it is saved, unless it has failed 1.1 or 1.2
       
  1587             else
       
  1588                 {
       
  1589                 // keep, if it is repeating entry, since repeating entries 
       
  1590                 // can have alarms in past
       
  1591                 }
       
  1592             }
       
  1593         } // END alarm checks
       
  1594 
       
  1595     //  3) Repeat rule checks
       
  1596     if ( Edited().IsRepeating() )
       
  1597         {
       
  1598         // if repeating note's repeat until date
       
  1599         // a) (for new entries)  isn't one day later than start date
       
  1600         // b) (for existing entries) is before start date
       
  1601         // set it to one year later from start date
       
  1602         TTime repeatUntilDay = CalenDateUtils::BeginningOfDay(
       
  1603             Edited().RepeatUntilDateTime() );
       
  1604         TTime startDay = CalenDateUtils::BeginningOfDay( Edited().StartDateTime() );
       
  1605         if ( (  IsCreatingNew() && repeatUntilDay <= startDay) ||
       
  1606              (! IsCreatingNew() && repeatUntilDay < startDay) )
       
  1607             {
       
  1608             Edited().SetRepeatUntilDateTimeL( startDay + TTimeIntervalYears(1) );
       
  1609             }
       
  1610         }
       
  1611 
       
  1612     //  4) if due date of todo is passed or invalid, save it with entered date
       
  1613     // no operation (this is just clarification in UI spec
       
  1614 
       
  1615 
       
  1616     //  5) Check for out of sequence for exceptions
       
  1617     //  6) Check for duration > rpt interval for series
       
  1618     
       
  1619     if( aRepeatTarget == CalCommon::EThisOnly )
       
  1620         {
       
  1621         TError error = CheckForOutOfSequenceL();
       
  1622 
       
  1623         if( error != EFormErrNone )
       
  1624             {
       
  1625             // Revert start/end times
       
  1626             Edited().SetStartDateTimeL( Original().StartDateTime() );
       
  1627             Edited().SetEndDateTimeL( Original().EndDateTime() );
       
  1628             }
       
  1629         }
       
  1630     else if( aRepeatTarget == CalCommon::EThisAndAll )
       
  1631         {
       
  1632         if( DurationGreaterThanRepeatIntervalError() )
       
  1633             {
       
  1634             // Revert start/end times
       
  1635             Edited().SetStartDateTimeL( Original().StartDateTime() );
       
  1636             Edited().SetEndDateTimeL( Original().EndDateTime() );
       
  1637             }
       
  1638         }
       
  1639 
       
  1640     TRACE_EXIT_POINT;
       
  1641     }
       
  1642 
       
  1643 // -----------------------------------------------------------------------------
       
  1644 // CCalenEditorDataHandler::IsOldEntry
       
  1645 // Returns ETrue if the entry was already created previously so that
       
  1646 // we are now editing it, returns EFalse otherwise.
       
  1647 // (other items were commented in a header).
       
  1648 // -----------------------------------------------------------------------------
       
  1649 //
       
  1650 TBool CCalenEditorDataHandler::IsOldEntry()
       
  1651     {
       
  1652     TRACE_ENTRY_POINT;
       
  1653 
       
  1654     TRACE_EXIT_POINT;
       
  1655     return !IsCreatingNew();
       
  1656     }
       
  1657 
       
  1658 // -----------------------------------------------------------------------------
       
  1659 // CCalenEditorDataHandler::AreTextFieldsEmptyL
       
  1660 // Returns ETrue if summary && location && description text fields are all empty
       
  1661 // Returns EFalse otherwise.
       
  1662 // (other items were commented in a header).
       
  1663 // -----------------------------------------------------------------------------
       
  1664 //
       
  1665 TBool CCalenEditorDataHandler::AreTextFieldsEmptyL()
       
  1666     {
       
  1667     TRACE_ENTRY_POINT;
       
  1668 
       
  1669     // We have to consider texts empty, if only summary is empty, in case
       
  1670     // location is not supported, because location can still exists in database.
       
  1671     TBool summaryAndDescriptionEmpty = CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) && 
       
  1672     CalenAgendaUtils::IsEmptyText( iEdited->Description() );
       
  1673 
       
  1674     if(LocationEnabledInUiL())
       
  1675         {
       
  1676         TRACE_EXIT_POINT;
       
  1677         return summaryAndDescriptionEmpty && CalenAgendaUtils::IsEmptyText( iEdited->Location() );        
       
  1678         }
       
  1679     
       
  1680     TRACE_EXIT_POINT;
       
  1681 
       
  1682     return summaryAndDescriptionEmpty; // and location is empty implicitly
       
  1683     }
       
  1684 
       
  1685 // -----------------------------------------------------------------------------
       
  1686 // CCalenEditorDataHandler::AreTextFieldsClearedL
       
  1687 // Returns ETrue if the user cleared the text in the location and summary fields.
       
  1688 // (other items were commented in a header).
       
  1689 // -----------------------------------------------------------------------------
       
  1690 //
       
  1691 TBool CCalenEditorDataHandler::AreTextFieldsClearedL()
       
  1692     {
       
  1693     TRACE_ENTRY_POINT;
       
  1694 
       
  1695     if ( CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) &&
       
  1696         CalenAgendaUtils::IsEmptyText( iEdited->Description() ) )
       
  1697         {
       
  1698         if ( LocationEnabledInUiL() )
       
  1699             {
       
  1700             if ( CalenAgendaUtils::IsEmptyText( iEdited->Location() ) )
       
  1701                 {
       
  1702                 if ( IsSummaryEmptied() || IsDescriptionEmptied() || IsLocationEmptied() )
       
  1703                     {
       
  1704                     TRACE_EXIT_POINT;
       
  1705                     return ETrue;
       
  1706                     }
       
  1707                 }
       
  1708             }
       
  1709 
       
  1710         else if ( IsSummaryEmptied() || IsDescriptionEmptied() )
       
  1711             {
       
  1712             TRACE_EXIT_POINT;
       
  1713             return ETrue;
       
  1714             }
       
  1715         }
       
  1716 
       
  1717     TRACE_EXIT_POINT;
       
  1718 
       
  1719     return EFalse;
       
  1720     }
       
  1721 
       
  1722 // -----------------------------------------------------------------------------
       
  1723 // CCalenEditorDataHandler::IsDescriptionEmptied
       
  1724 // Returns ETrue, the description was not empty in original && is empty
       
  1725 // in the edited note
       
  1726 // Returns EFalse, otherwise
       
  1727 // (other items were commented in a header).
       
  1728 // -----------------------------------------------------------------------------
       
  1729 TBool CCalenEditorDataHandler::IsDescriptionEmptied()
       
  1730     {
       
  1731     TRACE_ENTRY_POINT;
       
  1732 
       
  1733     if( !CalenAgendaUtils::IsEmptyText( iOriginal->Description() ) &&
       
  1734         CalenAgendaUtils::IsEmptyText( iEdited->Description() ) )
       
  1735         {
       
  1736         TRACE_EXIT_POINT;
       
  1737         return ETrue;
       
  1738         }
       
  1739 
       
  1740     TRACE_EXIT_POINT;
       
  1741 
       
  1742     return EFalse;
       
  1743     }
       
  1744 
       
  1745 // -----------------------------------------------------------------------------
       
  1746 // CCalenEditorDataHandler::IsSummaryEmptied
       
  1747 // Returns ETrue, the summary was not empty in original && is empty
       
  1748 // in the edited note
       
  1749 // Returns EFalse, otherwise
       
  1750 // (other items were commented in a header).
       
  1751 // -----------------------------------------------------------------------------
       
  1752 TBool CCalenEditorDataHandler::IsSummaryEmptied()
       
  1753     {
       
  1754     TRACE_ENTRY_POINT;
       
  1755 
       
  1756     if( !CalenAgendaUtils::IsEmptyText( iOriginal->Summary() ) &&
       
  1757         CalenAgendaUtils::IsEmptyText( iEdited->Summary() ) )
       
  1758         {
       
  1759         TRACE_EXIT_POINT;
       
  1760         return ETrue;
       
  1761         }
       
  1762 
       
  1763     TRACE_EXIT_POINT;
       
  1764     return EFalse;
       
  1765     }
       
  1766 
       
  1767 // -----------------------------------------------------------------------------
       
  1768 // CCalenEditorDataHandler::IsLocationEmptied
       
  1769 // Returns ETrue, the summary was not empty in original && is empty
       
  1770 // in the edited note
       
  1771 // Returns EFalse, otherwise
       
  1772 // (other items were commented in a header).
       
  1773 // -----------------------------------------------------------------------------
       
  1774 TBool CCalenEditorDataHandler::IsLocationEmptied()
       
  1775     {
       
  1776     TRACE_ENTRY_POINT;
       
  1777 
       
  1778     if( !CalenAgendaUtils::IsEmptyText( iOriginal->Location() ) &&
       
  1779         CalenAgendaUtils::IsEmptyText( iEdited->Location() ) )
       
  1780         {
       
  1781         TRACE_EXIT_POINT;
       
  1782         return ETrue;
       
  1783         }
       
  1784 
       
  1785     TRACE_EXIT_POINT;
       
  1786     return EFalse;
       
  1787     }
       
  1788 
       
  1789 // -----------------------------------------------------------------------------
       
  1790 // CCalenEditorDataHandler::IsEntryTypeEdited
       
  1791 // Returns ETrue if the 'Entry Type' is edited, EFalse otherwise.
       
  1792 // (other items were commented in a header).
       
  1793 // -----------------------------------------------------------------------------
       
  1794 //
       
  1795 TBool CCalenEditorDataHandler::IsEntryTypeEdited()
       
  1796     {
       
  1797     TRACE_ENTRY_POINT;
       
  1798 
       
  1799     TRACE_EXIT_POINT;
       
  1800     return iOriginal->EntryType() != iEdited->EntryType();
       
  1801     }
       
  1802 
       
  1803 // -----------------------------------------------------------------------------
       
  1804 // CCalenEditorDataHandler::IsStartDateTimeEdited
       
  1805 // Returns ETrue if the start date/time has been edited, EFalse otherwise.
       
  1806 // (other items were commented in a header).
       
  1807 // -----------------------------------------------------------------------------
       
  1808 //
       
  1809 TBool CCalenEditorDataHandler::IsStartDateTimeEdited()
       
  1810     {
       
  1811     TRACE_ENTRY_POINT;
       
  1812     
       
  1813     TBool isEdited = EFalse;
       
  1814     
       
  1815     TTime orgTTime = iOriginal->StartDateTime();
       
  1816     TTime editedTTime = iEdited->StartDateTime();
       
  1817     
       
  1818     // Get TDateTime of Original & Edited entries.
       
  1819     TDateTime orgDT = orgTTime.DateTime();
       
  1820     TDateTime editedDT = editedTTime.DateTime();
       
  1821     
       
  1822     if( !IsTimedEntry() && IsCreatingNew() )
       
  1823         {
       
  1824         // For non-timed event,on while creating new entry.
       
  1825         // check for only Date field change only.
       
  1826         if( orgDT.Day() != editedDT.Day() ||
       
  1827                 orgDT.Month() != editedDT.Month() ||
       
  1828                 orgDT.Year() != editedDT.Year() )
       
  1829             {
       
  1830             isEdited = ETrue;
       
  1831             }
       
  1832         }
       
  1833     else
       
  1834         {
       
  1835         
       
  1836         // For timed entry, check for Entry Date/Time Changes
       
  1837         if( orgTTime != editedTTime )
       
  1838             {
       
  1839             isEdited = ETrue;
       
  1840             }
       
  1841         }
       
  1842 		
       
  1843     TRACE_EXIT_POINT;
       
  1844     return isEdited;
       
  1845     
       
  1846     //return iOriginal->StartDateTime() != iEdited->StartDateTime();
       
  1847      
       
  1848     }
       
  1849 
       
  1850 // -----------------------------------------------------------------------------
       
  1851 // CCalenEditorDataHandler::IsEndDateTimeEdited
       
  1852 // Returns ETrue if the end date/time has been edited, EFalse otherwise.
       
  1853 // (other items were commented in a header).
       
  1854 // -----------------------------------------------------------------------------
       
  1855 //
       
  1856 TBool CCalenEditorDataHandler::IsEndDateTimeEdited()
       
  1857     {
       
  1858     TRACE_ENTRY_POINT;
       
  1859     TBool isEdited = EFalse;
       
  1860     
       
  1861     TTime orgTTime = iOriginal->EndDateTime();
       
  1862     TTime editedTTime = iEdited->EndDateTime();
       
  1863     
       
  1864     // Get TDateTime of Original & Edited entries.
       
  1865     TDateTime orgDT = orgTTime.DateTime();
       
  1866     TDateTime editedDT = editedTTime.DateTime();
       
  1867     
       
  1868     if( !IsTimedEntry() && IsCreatingNew() )
       
  1869         {
       
  1870         
       
  1871         // For non-timed event, check for only Date field change.
       
  1872         // No need to check for Entry time change.
       
  1873         if( orgDT.Day() != editedDT.Day() ||
       
  1874                 orgDT.Month() != editedDT.Month() ||
       
  1875                 orgDT.Year() != editedDT.Year() )
       
  1876             {
       
  1877             isEdited = ETrue;
       
  1878             }
       
  1879         }
       
  1880     else
       
  1881         {
       
  1882         // For timed entry, check for Entry Date/Time Changes
       
  1883         if( orgTTime != editedTTime )
       
  1884             {
       
  1885             isEdited = ETrue;
       
  1886             }
       
  1887         }
       
  1888     
       
  1889 	TRACE_EXIT_POINT;
       
  1890     return isEdited;
       
  1891 
       
  1892     //return iOriginal->EndDateTime() != iEdited->EndDateTime();
       
  1893     }
       
  1894 
       
  1895 // -----------------------------------------------------------------------------
       
  1896 // CCalenEditorDataHandler::IsDescriptionEdited
       
  1897 // Returns ETrue if the description has been modified, EFalse otherwise.
       
  1898 // (other items were commented in a header).
       
  1899 // -----------------------------------------------------------------------------
       
  1900 //
       
  1901 TBool CCalenEditorDataHandler::IsDescriptionEdited()
       
  1902     {
       
  1903     TRACE_ENTRY_POINT;
       
  1904 
       
  1905     TRACE_EXIT_POINT;
       
  1906     return iOriginal->Description() != iEdited->Description();
       
  1907     }
       
  1908 
       
  1909 // -----------------------------------------------------------------------------
       
  1910 // CCalenEditorDataHandler::IsPriorityEdited
       
  1911 // Returns ETrue if the priotity has been modified, EFalse otherwise.
       
  1912 // (other items were commented in a header).
       
  1913 // -----------------------------------------------------------------------------
       
  1914 //
       
  1915 TBool CCalenEditorDataHandler::IsPriorityEdited()
       
  1916     {
       
  1917     TRACE_ENTRY_POINT;
       
  1918 
       
  1919     TRACE_EXIT_POINT;
       
  1920     return iOriginal->Priority() != iEdited->Priority();
       
  1921     }
       
  1922 
       
  1923 // -----------------------------------------------------------------------------
       
  1924 // CCalenEditorDataHandler::IsCalendarEditedL
       
  1925 // Returns ETrue if the calendar filed has been edited, EFalse otherwise.
       
  1926 // (other items were commented in a header).
       
  1927 // -----------------------------------------------------------------------------
       
  1928 //
       
  1929 TBool CCalenEditorDataHandler::IsCalendarEditedL()
       
  1930     {
       
  1931     TRACE_ENTRY_POINT;
       
  1932       
       
  1933     TRACE_EXIT_POINT;
       
  1934     return iCalendarFieldEdited;
       
  1935     }
       
  1936 
       
  1937 // -----------------------------------------------------------------------------
       
  1938 // CCalenEditorDataHandler::IsSummaryEdited
       
  1939 // Returns ETrue if the summary has been edited, EFalse otherwise.
       
  1940 // (other items were commented in a header).
       
  1941 // -----------------------------------------------------------------------------
       
  1942 //
       
  1943 TBool CCalenEditorDataHandler::IsSummaryEdited()
       
  1944     {
       
  1945     TRACE_ENTRY_POINT;
       
  1946 
       
  1947     // For summary and location, we compare only that part of text
       
  1948     // that fits to editor. If it's equal, then we don't go and unnecessarily
       
  1949     // truncate existing data.
       
  1950     TRACE_EXIT_POINT;
       
  1951     return ( iOriginal->Summary().Left( iMaxTextEditorLength ) 
       
  1952                 != iEdited->Summary().Left( iMaxTextEditorLength ) );
       
  1953     }
       
  1954 
       
  1955 // -----------------------------------------------------------------------------
       
  1956 // CCalenEditorDataHandler::IsLocationEdited
       
  1957 // Returns ETrue if the location has been edited, EFalse otherwise.
       
  1958 // (other items were commented in a header).
       
  1959 // -----------------------------------------------------------------------------
       
  1960 //
       
  1961 TBool CCalenEditorDataHandler::IsLocationEdited()
       
  1962     {
       
  1963     TRACE_ENTRY_POINT;
       
  1964 
       
  1965     // For summary and location, we compare only that part of text
       
  1966     // that fits to editor. If it's equal, then we don't go and unnecessarily
       
  1967     // truncate existing data.
       
  1968     TRACE_EXIT_POINT;
       
  1969     return ( iOriginal->Location().Left( iMaxTextEditorLength ) 
       
  1970                 != iEdited->Location().Left( iMaxTextEditorLength ) );
       
  1971     }
       
  1972 
       
  1973 // -----------------------------------------------------------------------------
       
  1974 // CCalenEditorDataHandler::IsAlarmEditedL
       
  1975 // Returns ETrue if the alarm has been edited, EFalse otherwise.
       
  1976 // (other items were commented in a header).
       
  1977 // -----------------------------------------------------------------------------
       
  1978 //
       
  1979 TBool CCalenEditorDataHandler::IsAlarmEditedL()
       
  1980     {
       
  1981     TRACE_ENTRY_POINT;
       
  1982 
       
  1983     if ( iOriginal->IsAlarmActivated() && iEdited->IsAlarmActivated() )
       
  1984         {
       
  1985         // The alarm must be flagged as changed if the interval between the entry start
       
  1986         // and the alarm is different. (We can't just compare alarm times directly because
       
  1987         // the start date of the entry may have changed.)
       
  1988         TTimeIntervalMinutes origOffset, editedOffset;
       
  1989         
       
  1990         User::LeaveIfError( iOriginal->AlarmDateTime().MinutesFrom( iOriginal->StartDateTime(), origOffset ) );
       
  1991         User::LeaveIfError( iEdited->AlarmDateTime().MinutesFrom( iEdited->StartDateTime(), editedOffset ) );
       
  1992         
       
  1993         TBool alarmTimeChanged = origOffset != editedOffset;
       
  1994 
       
  1995         TRACE_EXIT_POINT;
       
  1996         return alarmTimeChanged;
       
  1997         }
       
  1998     else
       
  1999         {
       
  2000         TBool statusChanged = iOriginal->IsAlarmActivated() != iEdited->IsAlarmActivated();
       
  2001 
       
  2002         TRACE_EXIT_POINT;
       
  2003         return statusChanged;
       
  2004         }
       
  2005     }
       
  2006 
       
  2007 // -----------------------------------------------------------------------------
       
  2008 // CCalenEditorDataHandler::IsRepeatRuleEdited
       
  2009 // Returns ETrue if the repeat rule has been edited, EFalse otherwise.
       
  2010 // (other items were commented in a header).
       
  2011 // -----------------------------------------------------------------------------
       
  2012 //
       
  2013 TBool CCalenEditorDataHandler::IsRepeatRuleEdited()
       
  2014     {
       
  2015     TRACE_ENTRY_POINT;
       
  2016 
       
  2017     if ( iOriginal->IsRepeating() && iEdited->IsRepeating() )
       
  2018         {
       
  2019         TBool repeatTypeChanged = iOriginal->RepeatType() != iEdited->RepeatType();
       
  2020         TBool untilDateChanged = iOriginal->RepeatUntilDateTime() != iEdited->RepeatUntilDateTime();
       
  2021 
       
  2022         TRACE_EXIT_POINT;
       
  2023         return repeatTypeChanged || untilDateChanged;
       
  2024         }
       
  2025     else
       
  2026         {
       
  2027         TBool statusChanged = iOriginal->IsRepeating() != iEdited->IsRepeating();
       
  2028 
       
  2029         TRACE_EXIT_POINT;
       
  2030         return statusChanged;
       
  2031         }
       
  2032     }
       
  2033 
       
  2034 // -----------------------------------------------------------------------------
       
  2035 // CCalenEditorDataHandler::LocationEnabledInUiL
       
  2036 // Returns ETrue if the location is a valid field for this type of entry
       
  2037 // (i.e. meetings & reminders only), EFalse otherwise.
       
  2038 // (other items were commented in a header).
       
  2039 // -----------------------------------------------------------------------------
       
  2040 //
       
  2041 TBool CCalenEditorDataHandler::LocationEnabledInUiL()
       
  2042     {
       
  2043     TRACE_ENTRY_POINT;
       
  2044 
       
  2045     // Location is enabled for timed entries (i.e. an appointment or a
       
  2046     // reminder)
       
  2047     TRACE_EXIT_POINT;
       
  2048     return IsTimedEntry();
       
  2049     }
       
  2050 
       
  2051 // -----------------------------------------------------------------------------
       
  2052 // CCalenEditorDataHandler::IsTimedEntry
       
  2053 // Returns ETrue if this is a timed entry, EFalse otherwise.
       
  2054 // (other items were commented in a header).
       
  2055 // -----------------------------------------------------------------------------
       
  2056 //
       
  2057 TBool CCalenEditorDataHandler::IsTimedEntry() const
       
  2058     {
       
  2059     TRACE_ENTRY_POINT;
       
  2060 
       
  2061     TRACE_EXIT_POINT;
       
  2062     return IsTimed( iEdited->EntryType() );
       
  2063     }
       
  2064 
       
  2065 // -----------------------------------------------------------------------------
       
  2066 // CCalenEditorDataHandler::IsCreatingNew
       
  2067 // Returns ETrue if the user is creating a new entry, EFalse if the user is
       
  2068 // editing an existing entry.
       
  2069 // (other items were commented in a header).
       
  2070 // -----------------------------------------------------------------------------
       
  2071 //
       
  2072 TBool CCalenEditorDataHandler::IsCreatingNew() const
       
  2073     {
       
  2074     TRACE_ENTRY_POINT;
       
  2075 
       
  2076     TRACE_EXIT_POINT;
       
  2077     return iIsCreatingNew;
       
  2078     }
       
  2079 
       
  2080 // -----------------------------------------------------------------------------
       
  2081 // CCalenEditorDataHandler::IsStartDateChanged
       
  2082 // Returns ETrue if the start date of the entry has been changed, 
       
  2083 // EFalse otherwise. Note that this function only checks the date, 
       
  2084 // and not the time of day, of the entry.
       
  2085 // (other items were commented in a header).
       
  2086 // -----------------------------------------------------------------------------
       
  2087 //
       
  2088 TBool CCalenEditorDataHandler::IsStartDateChanged()
       
  2089     {
       
  2090     TRACE_ENTRY_POINT;
       
  2091 
       
  2092     TRACE_EXIT_POINT;
       
  2093     return ! CalenDateUtils::OnSameDay( iOriginal->StartDateTime(),
       
  2094                                         iEdited->StartDateTime() );
       
  2095     }
       
  2096 
       
  2097 // -----------------------------------------------------------------------------
       
  2098 // CCalenEditorDataHandler::IsAttachmentExists
       
  2099 // Returns ETrue calendar entry is having attachments
       
  2100 // (other items were commented in a header).
       
  2101 // -----------------------------------------------------------------------------
       
  2102 //
       
  2103 TBool CCalenEditorDataHandler::IsAttachmentExists()
       
  2104     {
       
  2105     TRACE_ENTRY_POINT;
       
  2106     TBool attachmentExits(EFalse);
       
  2107     
       
  2108     // TODO: Uncomment this when enabling attachment support
       
  2109     
       
  2110     if( (iOriginal->AttachmentCount() != iEdited->AttachmentCount())
       
  2111          || iServices.GetAttachmentData()->NumberOfItems() )
       
  2112         {
       
  2113         attachmentExits = ETrue;
       
  2114         }
       
  2115     
       
  2116     TRACE_EXIT_POINT;
       
  2117     return attachmentExits;
       
  2118     }
       
  2119 
       
  2120 // -----------------------------------------------------------------------------
       
  2121 // CCalenEditorDataHandler::IsEventTypeEdited
       
  2122 // (other items were commented in a header).
       
  2123 // -----------------------------------------------------------------------------
       
  2124 //
       
  2125 TBool CCalenEditorDataHandler::IsEventTypeEdited()
       
  2126     {
       
  2127     TRACE_ENTRY_POINT;
       
  2128     TBool fieldModified = EFalse;
       
  2129     
       
  2130     // Check EventType field is edited for already saved Entry
       
  2131     // For Newly created entry, ignore the EventTypeChange
       
  2132     if( (iOriginal->EntryType() != iEdited->EntryType()) && !IsCreatingNew() )
       
  2133         {
       
  2134         fieldModified = ETrue;
       
  2135         }
       
  2136     
       
  2137     TRACE_EXIT_POINT;
       
  2138     return fieldModified;
       
  2139     }
       
  2140 	
       
  2141 // -----------------------------------------------------------------------------
       
  2142 // CCalenEditorDataHandler::AllDayFieldEdited
       
  2143 // Returns ETrue if `All day event' line has been modified.
       
  2144 // (other items were commented in a header).
       
  2145 // -----------------------------------------------------------------------------
       
  2146 //
       
  2147 TBool CCalenEditorDataHandler::AllDayFieldEdited()
       
  2148     {
       
  2149     TRACE_ENTRY_POINT;
       
  2150     TBool fieldModified = EFalse;
       
  2151     
       
  2152     if( iOriginal->IsAllDayEvent() != iEdited->IsAllDayEvent() )
       
  2153         {
       
  2154         fieldModified = ETrue;
       
  2155         }
       
  2156     
       
  2157     TRACE_EXIT_POINT;
       
  2158     return fieldModified;
       
  2159     }
       
  2160 
       
  2161 // -----------------------------------------------------------------------------
       
  2162 // CCalenEditorDataHandler::SetDefaultAlarmDateTimeL
       
  2163 // Sets the alarm to the default value. This function is called after the user
       
  2164 // forces an exit, e.g. when pressing the power off button.
       
  2165 // (other items were commented in a header).
       
  2166 // -----------------------------------------------------------------------------
       
  2167 //
       
  2168 void CCalenEditorDataHandler::SetDefaultAlarmDateTimeL()
       
  2169     {
       
  2170     TRACE_ENTRY_POINT;
       
  2171 
       
  2172     /**
       
  2173      * Default alarm time is UI spec logic.
       
  2174      * It is important that this is here, because there shouldn't be UI spec logic in CCalenEntryUtil,
       
  2175      * only in CCalenEditorDataHandler.
       
  2176      *
       
  2177      * It is still a bit odd, that other set methods are in CCalenEntryUtil but not here.
       
  2178      * Maybe I add wrapper set methods for edited data also in *Handler.
       
  2179      *   e.g. void SetAlarmOffL() { Edited().SetAlarmOffL(); }
       
  2180      *
       
  2181      */
       
  2182     TTime defaultAlarm;
       
  2183 
       
  2184     if ( IsTimedEntry() )
       
  2185         {
       
  2186         TTimeIntervalMinutes defaultOffsetM( 15 ); // FIXME: should be read from central repository
       
  2187         defaultAlarm = Edited().StartDateTime() - defaultOffsetM;
       
  2188         }
       
  2189     else
       
  2190         {
       
  2191         TTimeIntervalHours defaultOffsetH( -8 );
       
  2192         defaultAlarm = CalenDateUtils::BeginningOfDay( Edited().EventDateTime() ) - defaultOffsetH;
       
  2193         }
       
  2194 
       
  2195     Edited().SetAlarmOnL( defaultAlarm );
       
  2196 
       
  2197     TRACE_EXIT_POINT;
       
  2198     }
       
  2199 
       
  2200 // -----------------------------------------------------------------------------
       
  2201 // CCalenEditorDataHandler::CalculateRepeatRuleL
       
  2202 // Calculates the repeat rule for a given entry.
       
  2203 // (other items were commented in a header).
       
  2204 // -----------------------------------------------------------------------------
       
  2205 //
       
  2206 void CCalenEditorDataHandler::CalculateRepeatRuleL(
       
  2207     const TTime& aStartDateTime,
       
  2208     TCalenRepeatIndex aNewRepeatType,
       
  2209     const TTime& aRepeatUntil,
       
  2210     TCalRRule& aRRule)
       
  2211     {
       
  2212     TRACE_ENTRY_POINT;
       
  2213 
       
  2214     // FIXME: This is copy-pasted from old implementation.
       
  2215     // This should be rewritten with care.
       
  2216         //If it ain't broke...?
       
  2217     TTime startDateTime = aStartDateTime;
       
  2218     TTime repeatUntil = aRepeatUntil;
       
  2219 
       
  2220     TCalRRule origRRule;
       
  2221     TBool hasOrigRRule = iEntry.GetRRuleL( origRRule );
       
  2222 
       
  2223     TBool isStartDateSame = CalenDateUtils::OnSameDay(
       
  2224         Original().StartDateTime(), Edited().StartDateTime() );
       
  2225 
       
  2226     //
       
  2227     // If repeat type is changed, repeat start date
       
  2228     // is replaced to the date of "Start date" field.
       
  2229     //
       
  2230     if ( hasOrigRRule &&
       
  2231          isStartDateSame &&
       
  2232          aNewRepeatType == Original().RepeatType() )
       
  2233         {
       
  2234         aRRule = origRRule; // keep the original setting...
       
  2235         // until date changed?
       
  2236         }
       
  2237     else if (aNewRepeatType == ERepeatOther)
       
  2238         {
       
  2239         // prevRptDef is ALWAYS non-NULL in this block,
       
  2240         // because previous note's repeat ALWAYS exists.
       
  2241         aRRule = origRRule;
       
  2242         TCalTime repeatStart;
       
  2243         if ( UseFloatingTimeL() )
       
  2244             {
       
  2245             repeatStart.SetTimeLocalFloatingL( startDateTime );
       
  2246             }
       
  2247         else
       
  2248             {
       
  2249             repeatStart.SetTimeLocalL( startDateTime );
       
  2250             }
       
  2251         aRRule.SetDtStart( repeatStart );
       
  2252         }
       
  2253     else
       
  2254         {
       
  2255         TCalTime repeatSt;
       
  2256         if ( UseFloatingTimeL() )
       
  2257             {
       
  2258             repeatSt.SetTimeLocalFloatingL( startDateTime );
       
  2259             }
       
  2260         else
       
  2261             {
       
  2262             repeatSt.SetTimeLocalL( startDateTime );
       
  2263             }
       
  2264         aRRule.SetDtStart( repeatSt );
       
  2265         aRRule.SetInterval( 1 );
       
  2266 
       
  2267         TInt interval(1);
       
  2268 
       
  2269         switch ( aNewRepeatType )
       
  2270             {
       
  2271             case (ERepeatDaily):  // Daily
       
  2272                 {
       
  2273                 aRRule.SetType( TCalRRule::EDaily );
       
  2274                 break;
       
  2275                 }
       
  2276             case (ERepeatWeekly):  // Weekly
       
  2277                 {
       
  2278                 if (hasOrigRRule && origRRule.Type() == TCalRRule::EDaily &&
       
  2279                     origRRule.Interval() == 7)
       
  2280                     {
       
  2281                     // If old note's repeat is every 7 days,
       
  2282                     // set repeat to every 7 days to Agenda, NOT every week.
       
  2283                     //
       
  2284                     aRRule.SetType( TCalRRule::EDaily );
       
  2285                     interval = 7;
       
  2286                     }
       
  2287                 else
       
  2288                     {
       
  2289                     aRRule.SetType( TCalRRule::EWeekly );
       
  2290 
       
  2291                     RArray<TDay> dayArray;
       
  2292                     CleanupClosePushL( dayArray );
       
  2293                     dayArray.Append( aRRule.DtStart().TimeLocalL().DayNoInWeek() );
       
  2294                     aRRule.SetByDay( dayArray );
       
  2295                     CleanupStack::PopAndDestroy( &dayArray );
       
  2296                     }
       
  2297                break;
       
  2298                 }
       
  2299             case (ERepeatBiWeekly):  // Bi-weekly
       
  2300                 {
       
  2301                 if ( hasOrigRRule && origRRule.Type() == TCalRRule::EDaily &&
       
  2302                      origRRule.Interval() == 14)
       
  2303                     {
       
  2304                     // If old note's repeat is every 14 days,
       
  2305                     // set repeat to every 14 days to Agenda, NOT every 2 weeks.
       
  2306                     //
       
  2307                     aRRule.SetType( TCalRRule::EDaily );
       
  2308                     interval = 14;
       
  2309                     }
       
  2310                 else
       
  2311                     {
       
  2312                     aRRule.SetType( TCalRRule::EWeekly );
       
  2313                     interval = 2;
       
  2314 
       
  2315                     RArray<TDay> dayArray;
       
  2316                     CleanupClosePushL( dayArray );
       
  2317                     dayArray.Append( aRRule.DtStart().TimeLocalL().DayNoInWeek() );
       
  2318                     aRRule.SetByDay( dayArray );
       
  2319                     CleanupStack::PopAndDestroy( &dayArray );
       
  2320                     }
       
  2321                 break;
       
  2322                 }
       
  2323                 case ERepeatWorkdays:// Weekly
       
  2324                     {
       
  2325                     TLocale iLocale;
       
  2326                     TUint iWorkDays = iLocale.WorkDays();
       
  2327                     if (hasOrigRRule && origRRule.Type() == TCalRRule::EDaily
       
  2328                         && origRRule.Interval() == 7)
       
  2329                         {
       
  2330                         // If old note's repeat is every 7 days,
       
  2331                         // set repeat to every 7 days to Agenda, NOT every week.
       
  2332                         //
       
  2333                         aRRule.SetType(TCalRRule::EDaily);
       
  2334                         interval = 7;
       
  2335                         }
       
  2336                     else
       
  2337                         {
       
  2338                         aRRule.SetType(TCalRRule::EWeekly);
       
  2339                         RArray<TDay> dayArray;
       
  2340                         CleanupClosePushL(dayArray); 
       
  2341                         TInt fixedNum = 1;
       
  2342                         TInt ruleday = 0;
       
  2343                         for (TInt i =0 ; i < KNoOfDaysInWeek ; i++)
       
  2344                             {
       
  2345                             ruleday = fixedNum << i;
       
  2346                             if(iWorkDays & ruleday)
       
  2347                                 {
       
  2348                                 dayArray.Append((TDay)i);
       
  2349                                 aRRule.SetByDay(dayArray);
       
  2350                                 }   
       
  2351                             } 
       
  2352                          CleanupStack::PopAndDestroy(&dayArray);
       
  2353                          }
       
  2354                     break;
       
  2355                                   
       
  2356                     }
       
  2357             case (ERepeatMonthly):
       
  2358                 // Monthly By Position
       
  2359                 {
       
  2360                 aRRule.SetType( TCalRRule::EMonthly );
       
  2361 
       
  2362                 RArray<TInt> dateArray;
       
  2363                 CleanupClosePushL( dateArray );
       
  2364                 dateArray.Append( aRRule.DtStart().TimeLocalL().DayNoInMonth() );
       
  2365                 aRRule.SetByMonthDay( dateArray );
       
  2366                 CleanupStack::PopAndDestroy( &dateArray );
       
  2367 
       
  2368                 break;
       
  2369                 }
       
  2370             case (ERepeatYearly):  // Yearly
       
  2371                 {
       
  2372                 // If old note's repeat is every 12 months,
       
  2373                 // set repeat to every 12 months to Agenda, NOT every year.
       
  2374                 //
       
  2375                 if ( hasOrigRRule && origRRule.Type() == TCalRRule::EMonthly &&
       
  2376                      origRRule.Interval() == 12)
       
  2377                     {
       
  2378                     aRRule.SetType( TCalRRule::EMonthly );
       
  2379                     interval = 12;
       
  2380                     }
       
  2381                 else
       
  2382                     {
       
  2383                     aRRule.SetType( TCalRRule::EYearly );
       
  2384                     }
       
  2385                 break;
       
  2386                 }
       
  2387             default: // Repeat item is "Other"
       
  2388                 {
       
  2389                 interval = aRRule.Interval(); // To copy previous note's interval
       
  2390                 break;
       
  2391                 }
       
  2392             }
       
  2393 
       
  2394         aRRule.SetInterval( interval );
       
  2395         }
       
  2396 
       
  2397     // If repeat until is max date of Calendar,
       
  2398     // note repeat is set to forever.
       
  2399     if ( ! CalenDateUtils::IsValidDay(repeatUntil) || IsForeverDate( repeatUntil ) )
       
  2400         {
       
  2401         // Set repeat to forever:
       
  2402         aRRule.SetCount( 0 );
       
  2403         }
       
  2404     else
       
  2405         {
       
  2406         // Change repeatuntil so that hours, minutes, ... are same as in start date
       
  2407         TDateTime dtUntil = repeatUntil.DateTime();
       
  2408         TDateTime dtStart= iEntry.StartTimeL().TimeLocalL().DateTime();
       
  2409 
       
  2410         dtUntil.Set( dtUntil.Year(), dtUntil.Month(), dtUntil.Day(),
       
  2411                      dtStart.Hour(), dtStart.Minute(), dtStart.Second(), dtStart.MicroSecond());
       
  2412 
       
  2413         TCalTime calRepeatUntil;
       
  2414         if ( UseFloatingTimeL() )
       
  2415             {
       
  2416             calRepeatUntil.SetTimeLocalFloatingL( TTime( dtUntil ) );
       
  2417             }
       
  2418         else
       
  2419             {
       
  2420             calRepeatUntil.SetTimeLocalL( TTime( dtUntil ) );
       
  2421             }
       
  2422         aRRule.SetUntil( calRepeatUntil );
       
  2423         }
       
  2424 
       
  2425     TRACE_EXIT_POINT;
       
  2426     }
       
  2427 
       
  2428 // -----------------------------------------------------------------------------
       
  2429 // CCalenEditorDataHandler::SetDefaultNewValuesL
       
  2430 // Sets the default values when creating a new entry.
       
  2431 // (other items were commented in a header).
       
  2432 // -----------------------------------------------------------------------------
       
  2433 //
       
  2434 void CCalenEditorDataHandler::SetDefaultNewValuesL(CCalenEntryUtil& aData)
       
  2435     {
       
  2436     TRACE_ENTRY_POINT;
       
  2437 
       
  2438     // FIXME: I don't know if this method should be needed or not.
       
  2439     // It's a bit unclear that if pass entry that is new,
       
  2440     // should we set default data in caller (application) or
       
  2441     // here.
       
  2442     // But to replicate old editor functionality, we set in editor
       
  2443     // side
       
  2444 
       
  2445     ASSERT( IsCreatingNew() );
       
  2446     // start time and end time are taken from passed entry.
       
  2447     // They have to be initialized outside of editors
       
  2448 
       
  2449     // subject, location, description are by default empty
       
  2450 
       
  2451     // repeat rule is by default off
       
  2452 
       
  2453     // alarm is by default off
       
  2454 
       
  2455     // synch value
       
  2456     aData.SetSynchTypeL( CCalenEntryUtil::ESynchPrivate );
       
  2457 
       
  2458     // priority
       
  2459     aData.SetPriorityL( CCalenEntryUtil::ETodoPriorityNormal );
       
  2460     
       
  2461     TRACE_EXIT_POINT;
       
  2462     }
       
  2463 
       
  2464 // -----------------------------------------------------------------------------
       
  2465 // CCalenEditorDataHandler::IsChildL
       
  2466 // Returns ETrue if the entry is a child, EFalse otherwise.
       
  2467 // (other items were commented in a header).
       
  2468 // -----------------------------------------------------------------------------
       
  2469 //
       
  2470 TBool CCalenEditorDataHandler::IsChildL() const
       
  2471     {
       
  2472     TRACE_ENTRY_POINT;
       
  2473 
       
  2474     TRACE_EXIT_POINT;
       
  2475     return iRecurrenceId.TimeUtcL() != Time::NullTTime();
       
  2476     }
       
  2477 
       
  2478 // -----------------------------------------------------------------------------
       
  2479 // CCalenEditorDataHandler::UseFloatingTimeL
       
  2480 // Returns ETrue if the entry should use floating time, EFalse otherwise.
       
  2481 // (other items were commented in a header).
       
  2482 // -----------------------------------------------------------------------------
       
  2483 //
       
  2484 TBool CCalenEditorDataHandler::UseFloatingTimeL() const
       
  2485     {
       
  2486     TRACE_ENTRY_POINT;
       
  2487 
       
  2488     // Use floating time based on type
       
  2489     // This way we ensure that entries _created_ with Calendar Editors
       
  2490     // are consistent regarding time mode.
       
  2491     //
       
  2492     TRACE_EXIT_POINT;
       
  2493     return (! IsTimedEntry()); // use floating time for non-timed entries        
       
  2494         
       
  2495     }
       
  2496 
       
  2497 // -----------------------------------------------------------------------------
       
  2498 // CCalenEditorDataHandler::WriteStartAndEndTimesToEntryL
       
  2499 // Writes the start and end times from the form to the CCalEntry.
       
  2500 // (other items were commented in a header).
       
  2501 // -----------------------------------------------------------------------------
       
  2502 //
       
  2503 void CCalenEditorDataHandler::WriteStartAndEndTimesToEntryL( CalCommon::TRecurrenceRange aRepeatTarget )
       
  2504     {
       
  2505     TRACE_ENTRY_POINT;
       
  2506 
       
  2507     const TBool unDatedTodo=(iEntry.EntryTypeL()==CCalEntry::ETodo) && (iEntry.EndTimeL().TimeLocalL()==Time::NullTTime());
       
  2508     const TBool unDatedTodoWithAlarm=unDatedTodo && (Edited().IsAlarmActivated());
       
  2509 
       
  2510     TBool shouldWriteBothTimes =
       
  2511         // For new entries
       
  2512         IsCreatingNew() ||
       
  2513         // When creating exception entry (exception entry's time are read from editors)
       
  2514         ( aRepeatTarget != CalCommon::EThisAndAll ) ||
       
  2515         // when repeating entry is modified to be non-repeating (entry's times are read from editors)
       
  2516         ( Original().IsRepeating() && ! Edited().IsRepeating() );
       
  2517 
       
  2518     if ( shouldWriteBothTimes || IsStartDateTimeEdited() || IsEndDateTimeEdited() || unDatedTodoWithAlarm )
       
  2519         {
       
  2520 
       
  2521         TCalTime entryStart;
       
  2522         TCalTime entryEnd;
       
  2523 
       
  2524         // 1) Initialize entryStart and entryEnd with original times.
       
  2525         // But for todos we need to be careful, because there might not be them originally
       
  2526         // In S60 UI, todos don't have starttime, so we use same for both start and end time.
       
  2527         if (iEntry.EntryTypeL()==CCalEntry::ETodo)
       
  2528             {
       
  2529              // if undated todo and it has alarm activated
       
  2530             if ((iEntry.EndTimeL().TimeLocalL()==Time::NullTTime()) && (Edited().IsAlarmActivated()))
       
  2531                 {
       
  2532                 entryStart.SetTimeLocalL(Edited().EventDateTime());
       
  2533                 entryEnd.SetTimeLocalL(Edited().EventDateTime());
       
  2534                 shouldWriteBothTimes=ETrue; // Ensures that times are written later
       
  2535                 }
       
  2536             else
       
  2537                 {
       
  2538                  entryStart = iEntry.EndTimeL();
       
  2539                  entryEnd = iEntry.EndTimeL();
       
  2540                 }
       
  2541             }
       
  2542         else
       
  2543             {
       
  2544             entryStart = iEntry.StartTimeL();
       
  2545             entryEnd   = iEntry.EndTimeL();
       
  2546             }
       
  2547 
       
  2548         // 2) Decide start time
       
  2549         if ( shouldWriteBothTimes || IsStartDateTimeEdited() )
       
  2550             {
       
  2551             TTime newStart = Edited().StartDateTime();
       
  2552             TDateTime newStartDT = newStart.DateTime();
       
  2553             // Special case:
       
  2554             // In case c) only start time (hh:mm) of d) existing a) repeating b) series is edited,
       
  2555             // we need to preserve start date (dd.mm.yyy), because start date in editors
       
  2556             // is instance's start date.
       
  2557             // (Example of problematic cases that brings up, when UI represents
       
  2558             // two different concepts in same start date field)
       
  2559             //   a) repeating              b) series is edited                        c) only start time is edited     d) existing
       
  2560             if ( Edited().IsRepeating() && aRepeatTarget == CalCommon::EThisAndAll && ! IsStartDateChanged()        && ! IsCreatingNew() )
       
  2561                 {
       
  2562                 TDateTime oldDt = iEntry.StartTimeL().TimeLocalL().DateTime();
       
  2563                 TDateTime editDt = newStart.DateTime();
       
  2564                 newStart = TTime( TDateTime( oldDt.Year(), oldDt.Month(), oldDt.Day(),
       
  2565                                              editDt.Hour(), editDt.Minute(),
       
  2566                                              oldDt.Second(), oldDt.MicroSecond() ) );
       
  2567                 }
       
  2568             else if ( ( Edited().RepeatType() == ERepeatOther ) && IsStartDateChanged() )
       
  2569                 {
       
  2570                 // The start time might have been disguised because the entry
       
  2571                 // consists of an rRule and rDates. The actual start time
       
  2572                 // needs to be extracted
       
  2573                 RArray<TCalTime> rDates;
       
  2574                 CleanupClosePushL( rDates );
       
  2575                 
       
  2576                 iEntry.GetRDatesL( rDates );
       
  2577                 if ( rDates.Count() > 0 )
       
  2578                     {
       
  2579                     // As we have rDates, check to see if there is an
       
  2580                     // rRule
       
  2581                     TCalRRule rRule;
       
  2582                     if ( iEntry.GetRRuleL( rRule ) )
       
  2583                         {
       
  2584                         TTime firstRDate = rDates[ 0 ].TimeLocalL();
       
  2585                         TTime rRuleStart = iEntry.StartTimeL().TimeLocalL();
       
  2586                         TTime lastRDate = rDates[ rDates.Count() - 1 ].TimeLocalL();
       
  2587                         TTimeIntervalMinutes startDateShiftInterval = 0;
       
  2588                         if ( firstRDate < rRuleStart )
       
  2589                             {
       
  2590                             // The first rDate is before the start of the rRule
       
  2591                             // So adjust the start date accordingly
       
  2592                             
       
  2593                             User::LeaveIfError( newStart.MinutesFrom( firstRDate, startDateShiftInterval ) );
       
  2594                             }
       
  2595                         else
       
  2596                             {
       
  2597                             // The start of the rRule comes first
       
  2598                             User::LeaveIfError( newStart.MinutesFrom( rRuleStart, startDateShiftInterval ) );
       
  2599                             }
       
  2600                             
       
  2601                         newStart = rRuleStart + startDateShiftInterval;
       
  2602                         
       
  2603                         TInt rRuleCount = rRule.Count();
       
  2604                         rRule.SetCount( rRuleCount );
       
  2605                         
       
  2606                         TCalTime rRuleDT;
       
  2607                         if ( UseFloatingTimeL() )
       
  2608                             {
       
  2609                             rRuleDT.SetTimeLocalFloatingL( newStart );
       
  2610                             }
       
  2611                         else
       
  2612                             {
       
  2613                             rRuleDT.SetTimeLocalL( newStart );
       
  2614                             }
       
  2615                         
       
  2616                         rRule.SetDtStart( rRuleDT );
       
  2617 						
       
  2618 						// For rearranging the recurrence pattern for an 
       
  2619 						// entry having rdates
       
  2620 						
       
  2621 						TInt repeatType = rRule.Type();	
       
  2622        					switch ( repeatType )
       
  2623             				{
       
  2624                				case ( TCalRRule::EWeekly ):  //For Weekly repeating event
       
  2625                 				{
       
  2626                 				RArray<TDay> dayArray;
       
  2627                     			CleanupClosePushL( dayArray );
       
  2628                     			dayArray.Append( rRule.DtStart().TimeLocalL().DayNoInWeek() );
       
  2629                     			rRule.SetByDay( dayArray );
       
  2630                     			CleanupStack::PopAndDestroy( &dayArray );
       
  2631                     			
       
  2632                     			// Adjust the RepeatUntil date
       
  2633                     			ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() );            
       
  2634 								break;
       
  2635                 				}
       
  2636                             case ( TCalRRule::EMonthly ):// For Monthly repeating event
       
  2637                                 {
       
  2638 				                RArray<TInt> dateArray;
       
  2639                 				CleanupClosePushL( dateArray );
       
  2640                 				dateArray.Append( rRule.DtStart().TimeLocalL().DayNoInMonth() );
       
  2641                 				rRule.SetByMonthDay( dateArray );
       
  2642                 				CleanupStack::PopAndDestroy( &dateArray );
       
  2643 							
       
  2644 								// Adjust the RepeatUntil date
       
  2645 								ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() );            
       
  2646 				                break;
       
  2647                 				}
       
  2648                 				
       
  2649                 			 case ( TCalRRule::EDaily ):// For Daily repeating event
       
  2650                                 {
       
  2651 				                TCalRRule curRule;				
       
  2652 								iEntry.GetRRuleL( curRule );
       
  2653 								
       
  2654 								// Adjust the RepeatUntil date
       
  2655 								if(lastRDate < curRule.Until().TimeLocalL() )
       
  2656 									{
       
  2657 									ApplyUntilDateToRRuleL( rRule, Edited().RepeatUntilDateTime() );  	
       
  2658 									}
       
  2659 								
       
  2660 								
       
  2661 				                break;
       
  2662                 				}
       
  2663 				            default:
       
  2664                 				{
       
  2665 				                break;
       
  2666                 				}
       
  2667             				}
       
  2668 
       
  2669                         
       
  2670                         iEntry.SetRRuleL( rRule );
       
  2671                         }
       
  2672                     }
       
  2673                 
       
  2674                 CleanupStack::PopAndDestroy(); // rDates
       
  2675                 }
       
  2676 
       
  2677             if ( UseFloatingTimeL() )
       
  2678                 {
       
  2679                 entryStart.SetTimeLocalFloatingL( newStart );
       
  2680                 }
       
  2681             else
       
  2682                 {
       
  2683                 entryStart.SetTimeLocalL( newStart );
       
  2684                 }
       
  2685             }
       
  2686 
       
  2687         // 3) Decide end time
       
  2688         if ( shouldWriteBothTimes || IsEndDateTimeEdited() )
       
  2689             {
       
  2690             TTime start = Edited().StartDateTime();
       
  2691             TTime end = Edited().EndDateTime();
       
  2692             
       
  2693             // For all-day events, we add 24 hours to end date
       
  2694             // to make it full day long
       
  2695             /*if ( iEntryType == CCalEntry::EEvent)
       
  2696                 {
       
  2697                 end += TTimeIntervalDays(1);
       
  2698                 }*/
       
  2699 
       
  2700             TTimeIntervalMinutes duration;
       
  2701             TInt err = end.MinutesFrom( start, duration );
       
  2702             ASSERT( err == KErrNone );
       
  2703             ASSERT( duration >= TTimeIntervalMinutes(0) );
       
  2704 
       
  2705             if ( UseFloatingTimeL() )
       
  2706                 {
       
  2707                 entryEnd.SetTimeLocalFloatingL( entryStart.TimeLocalL() + duration );
       
  2708                 }
       
  2709             else
       
  2710                 {
       
  2711                 entryEnd.SetTimeLocalL( entryStart.TimeLocalL() + duration );
       
  2712                 }
       
  2713             }
       
  2714         
       
  2715         // If EntryType is changed as Non-timed/Timed entry, along with StartTime(AND/OR)EndTime,
       
  2716         // Both Start/End time TimeMode should be changed accordingly.
       
  2717         if ( UseFloatingTimeL() )
       
  2718             {
       
  2719             entryStart.SetTimeLocalFloatingL( entryStart.TimeLocalL() );
       
  2720             entryEnd.SetTimeLocalFloatingL( entryEnd.TimeLocalL() );
       
  2721             }
       
  2722         else
       
  2723             {
       
  2724             entryStart.SetTimeLocalL( entryStart.TimeLocalL() );
       
  2725             entryEnd.SetTimeLocalL( entryEnd.TimeLocalL() );
       
  2726             }
       
  2727         
       
  2728         // Write times to entry
       
  2729         iEntry.SetStartAndEndTimeL( entryStart, entryEnd );
       
  2730         }
       
  2731 
       
  2732     TRACE_EXIT_POINT;
       
  2733     }
       
  2734 
       
  2735 //----------------------------------------------------------------------
       
  2736 // CCalenEditorDataHandler::ResetOriginalDataL
       
  2737 // Reset original editor data
       
  2738 // (other items were commented in a header).
       
  2739 //----------------------------------------------------------------------
       
  2740 void CCalenEditorDataHandler::ResetOriginalDataL()
       
  2741     {
       
  2742     TRACE_ENTRY_POINT;
       
  2743 		
       
  2744     if(iOriginal)
       
  2745 		{
       
  2746 		delete iOriginal;
       
  2747 		iOriginal=NULL;
       
  2748 		}
       
  2749     iOriginal = CCalenEntryUtil::NewL( iEntry, iInstanceDateTime );
       
  2750 
       
  2751     TRACE_EXIT_POINT;
       
  2752     }
       
  2753 
       
  2754 //----------------------------------------------------------------------
       
  2755 // CCalenEditorDataHandler::EntryViewL
       
  2756 // Temp function to get to work 
       
  2757 // (other items were commented in a header).
       
  2758 //----------------------------------------------------------------------
       
  2759 CCalEntryView&  CCalenEditorDataHandler::EntryViewL()
       
  2760     {
       
  2761     TRACE_ENTRY_POINT;
       
  2762 
       
  2763     CCalEntryView* entryView = iServices.EntryViewL(CurrentDbCollectionId());
       
  2764 
       
  2765     TRACE_EXIT_POINT;
       
  2766     return *entryView;
       
  2767     }
       
  2768 
       
  2769 //----------------------------------------------------------------------
       
  2770 // CCalenEditorDataHandler::InstanceViewL
       
  2771 // Temp function to get to work
       
  2772 // (other items were commented in a header).
       
  2773 //----------------------------------------------------------------------
       
  2774 CCalInstanceView&  CCalenEditorDataHandler::InstanceViewL()
       
  2775     {
       
  2776     TRACE_ENTRY_POINT;
       
  2777     
       
  2778     CCalInstanceView* instanceView = iServices.InstanceViewL(iCollectionIds);
       
  2779     
       
  2780     TRACE_EXIT_POINT;
       
  2781     return *instanceView;
       
  2782     }
       
  2783 
       
  2784 // -----------------------------------------------------------------------------
       
  2785 // CCalenEditorDataHandler::GetPreviousInstanceForRepeatOtherL()
       
  2786 // Returns the time of the previous instance of a particular repeating entry
       
  2787 // (other items were commented in a header).
       
  2788 // -----------------------------------------------------------------------------
       
  2789 //
       
  2790 TTime CCalenEditorDataHandler::GetPreviousInstanceForRepeatOtherL(CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange)
       
  2791     {
       
  2792 	RPointerArray<CCalInstance> allInstances;
       
  2793     CleanupResetAndDestroyPushL( allInstances );
       
  2794     
       
  2795     TInt filter;
       
  2796     // Get the entry type to be filtered
       
  2797     switch(aEntry.EntryTypeL())
       
  2798         {
       
  2799     	case CCalEntry::EAppt:
       
  2800     		filter = CalCommon::EIncludeAppts;
       
  2801     		break;
       
  2802     	case CCalEntry::ETodo:
       
  2803     		filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos;
       
  2804     		break;
       
  2805     	case CCalEntry::EEvent:
       
  2806     		filter = CalCommon::EIncludeEvents;
       
  2807     		break;
       
  2808     	case CCalEntry::EReminder:
       
  2809     		filter = CalCommon::EIncludeReminder;
       
  2810     		break;
       
  2811     	case CCalEntry::EAnniv:
       
  2812     		filter = CalCommon::EIncludeAnnivs;
       
  2813     		break;
       
  2814     	default:
       
  2815     		filter = CalCommon::EIncludeAll;
       
  2816     		break;
       
  2817         };
       
  2818 
       
  2819     iServices.InstanceViewL()->FindInstanceL( allInstances, 
       
  2820                                      (CalCommon::TCalViewFilterFlags)filter,
       
  2821                                      timeRange);
       
  2822 
       
  2823 	TTime previousTime = Time::NullTTime();
       
  2824 	
       
  2825     for( TInt i = allInstances.Count() - 1; i >= 0; i-- )
       
  2826         {
       
  2827         if( allInstances[i]->Entry().UidL() == aEntry.UidL() )
       
  2828             {
       
  2829             TRACE_EXIT_POINT;
       
  2830             previousTime = allInstances[i]->Time().TimeLocalL();
       
  2831             break;
       
  2832             }
       
  2833         }
       
  2834 
       
  2835     CleanupStack::PopAndDestroy( &allInstances );  
       
  2836     return previousTime;
       
  2837     }
       
  2838 
       
  2839 // -----------------------------------------------------------------------------
       
  2840 // CCalenEditorDataHandler::GetNextInstanceForRepeatOtherL()
       
  2841 // Returns the time of the next instance of a particular repeating entry
       
  2842 // (other items were commented in a header).
       
  2843 // -----------------------------------------------------------------------------
       
  2844 //
       
  2845 TTime CCalenEditorDataHandler::GetNextInstanceForRepeatOtherL( CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange )
       
  2846     {
       
  2847 	RPointerArray<CCalInstance> allInstances;
       
  2848     CleanupResetAndDestroyPushL( allInstances );
       
  2849     
       
  2850     TInt filter;
       
  2851     // Get the entry type to be filtered
       
  2852     switch( aEntry.EntryTypeL() )
       
  2853         {
       
  2854     	case CCalEntry::EAppt:
       
  2855     		filter = CalCommon::EIncludeAppts;
       
  2856     		break;
       
  2857     	case CCalEntry::ETodo:
       
  2858     		filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos;
       
  2859     		break;
       
  2860     	case CCalEntry::EEvent:
       
  2861     		filter = CalCommon::EIncludeEvents;
       
  2862     		break;
       
  2863     	case CCalEntry::EReminder:
       
  2864     		filter = CalCommon::EIncludeReminder;
       
  2865     		break;
       
  2866     	case CCalEntry::EAnniv:
       
  2867     		filter = CalCommon::EIncludeAnnivs;
       
  2868     		break;
       
  2869     	default:
       
  2870     		filter = CalCommon::EIncludeAll;
       
  2871     		break;
       
  2872         };
       
  2873     
       
  2874     iServices.InstanceViewL()->FindInstanceL( allInstances, 
       
  2875                                      ( CalCommon::TCalViewFilterFlags )filter,
       
  2876                                      timeRange);
       
  2877                                      
       
  2878     TTime nextTime = Time::NullTTime();
       
  2879     
       
  2880 	TInt i( 0 );
       
  2881     for( ; i < allInstances.Count(); i++ )
       
  2882         {
       
  2883         if( allInstances[i]->Entry().UidL() == aEntry.UidL() )
       
  2884             {
       
  2885             TRACE_EXIT_POINT;
       
  2886             nextTime = allInstances[i]->Time().TimeLocalL();
       
  2887             break;
       
  2888             }
       
  2889         }
       
  2890   
       
  2891     CleanupStack::PopAndDestroy( &allInstances );  
       
  2892     return nextTime;
       
  2893     }
       
  2894 
       
  2895 // -----------------------------------------------------------------------------
       
  2896 // CCalenEditorDataHandler::SetEntryType
       
  2897 // add attachments to the entry as ccalattachments
       
  2898 // -----------------------------------------------------------------------------
       
  2899 //
       
  2900 void CCalenEditorDataHandler::SetEntryType( CCalEntry::TType aNewEntryType )
       
  2901     {
       
  2902     iEntryType = aNewEntryType;
       
  2903     }
       
  2904 
       
  2905 // -----------------------------------------------------------------------------
       
  2906 // CCalenEditorDataHandler::AddAttachementsToEntryL
       
  2907 // add attachments to the entry as ccalattachments
       
  2908 // -----------------------------------------------------------------------------
       
  2909 //
       
  2910 void CCalenEditorDataHandler::AddAttachementsToEntryL()
       
  2911     {
       
  2912     TRACE_ENTRY_POINT;
       
  2913     
       
  2914     // Get the list of attachments from model and add them to entry
       
  2915     RPointerArray<CCalenAttachmentInfo> attachmentInfoList;
       
  2916     iServices.GetAttachmentData()->GetAttachmentListL( attachmentInfoList );
       
  2917     TInt attachmentCount = iEntry.AttachmentCountL();
       
  2918     TInt modelCount = attachmentInfoList.Count();
       
  2919     
       
  2920     if( attachmentCount > 0 && modelCount == 0 )
       
  2921         {
       
  2922         // This means that all the attachments in the entry have been deleted
       
  2923         // by the user. So remove all attchments from the entry
       
  2924         for( int index = 0 ; index < attachmentCount ; index++ )
       
  2925             {
       
  2926             iEntry.DeleteAttachmentL( *iEntry.AttachmentL( 0 ) );
       
  2927             }
       
  2928         
       
  2929         // No attachments need to be added at this point, we can simply return.
       
  2930         attachmentInfoList.Close();
       
  2931         TRACE_EXIT_POINT;
       
  2932         return;
       
  2933         }
       
  2934     
       
  2935     // Delete all the attachmenst of the entry which are not present in the model
       
  2936     TInt currentIndex = 0;
       
  2937     for( TInt index=0; index < attachmentCount; index++ )
       
  2938        {
       
  2939        CCalAttachment* attachment = iEntry.AttachmentL( currentIndex );
       
  2940        TBool matchFound = EFalse;
       
  2941        for( int modelIndex = 0 ; modelIndex < modelCount ; modelIndex++ )
       
  2942            {
       
  2943            CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[ modelIndex ];
       
  2944            if( attachmentInfo->StoreType() == 
       
  2945                CCalenAttachmentInfo::ECalenAttachmentFetchedFromEntry )
       
  2946                {
       
  2947                // We are only interested in those attachments which have been
       
  2948                // fetched from the entry because any newly added attachments
       
  2949                // will not yet be updated in the entry
       
  2950                RFile attachmentHandle;
       
  2951                CleanupClosePushL( attachmentHandle );
       
  2952                attachment->FileAttachment()->FetchFileHandleL( attachmentHandle );
       
  2953                
       
  2954                TFileName systemFileName;
       
  2955                attachmentHandle.FullName( systemFileName );
       
  2956                
       
  2957                if( systemFileName == attachmentInfo->SystemFileName() )
       
  2958                    {
       
  2959                    // There is an attachment in the model which matches the
       
  2960                    // attachment in the entry. So do not delete it
       
  2961                    matchFound = ETrue;
       
  2962                    CleanupStack::PopAndDestroy( &attachmentHandle );
       
  2963                    break;
       
  2964                    }
       
  2965                CleanupStack::PopAndDestroy( &attachmentHandle );
       
  2966                }
       
  2967            }
       
  2968        if( !matchFound )
       
  2969            {
       
  2970            // There is no matching attachment in the model. Delete it from entry
       
  2971            // This will compress the attachment array. Hence do not increment the currentIndex
       
  2972            iEntry.DeleteAttachmentL( *iEntry.AttachmentL( currentIndex ) );
       
  2973            }
       
  2974        else
       
  2975            {
       
  2976            // Move to the next attachment
       
  2977            currentIndex++;
       
  2978            }
       
  2979        }
       
  2980     
       
  2981     // Now add the remaining newly added attachments to the entry
       
  2982     for( TInt index=0 ; index< modelCount ; index++ )
       
  2983         {
       
  2984         CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[ index ];
       
  2985         if( attachmentInfo->StoreType() == CCalenAttachmentInfo::ECalenNewAttachment )
       
  2986             {
       
  2987             TParsePtrC fileNameParser(attachmentInfo->FileName());
       
  2988             RFile fileHandle;
       
  2989             CEikonEnv* eikonEnv = CEikonEnv::Static();
       
  2990             RFs& fs = eikonEnv->FsSession();
       
  2991             User::LeaveIfError(fs.ShareProtected());
       
  2992             
       
  2993             TInt err = fileHandle.Open( fs, attachmentInfo->FileName(), EFileWrite );
       
  2994             if( KErrNone != err )
       
  2995                 {
       
  2996                 attachmentInfoList.Close();
       
  2997                 TRACE_EXIT_POINT;
       
  2998                 return;
       
  2999                 }
       
  3000             CleanupClosePushL(fileHandle);
       
  3001             
       
  3002             CCalAttachment* attachment = CCalAttachment::NewFileL(fileHandle);
       
  3003             CleanupStack::PopAndDestroy(&fileHandle); 
       
  3004             
       
  3005             CleanupStack::PushL( attachment );
       
  3006             // Sets the label for the attachment
       
  3007             attachment->SetLabelL( fileNameParser.NameAndExt() );
       
  3008             // Sets mime type for the attachment
       
  3009             attachment->SetMimeTypeL( attachmentInfo->DataType().Des8() );
       
  3010             attachment->SetAttribute(CCalAttachment::EExportInline);
       
  3011             iEntry.AddAttachmentL( *attachment );
       
  3012             CleanupStack::Pop( attachment );
       
  3013             }                
       
  3014         }
       
  3015     attachmentInfoList.Close();
       
  3016    
       
  3017     TRACE_EXIT_POINT;
       
  3018     }
       
  3019 
       
  3020 
       
  3021 // -----------------------------------------------------------------------------
       
  3022 // CCalenEditorDataHandler::SetCalendarFieldEditedL
       
  3023 // Set if calendar is been edited or not with previous and current collection id
       
  3024 // -----------------------------------------------------------------------------
       
  3025 //
       
  3026 void CCalenEditorDataHandler::SetCalendarFieldEditedL(TBool aEdited , 
       
  3027                                                             TCalCollectionId aPreviousDbColId,
       
  3028                                                             TCalCollectionId aCurrentDbColId)
       
  3029     {
       
  3030     TRACE_ENTRY_POINT
       
  3031     iCalendarFieldEdited = aEdited;
       
  3032     iPreviousDbColId = aPreviousDbColId;
       
  3033     iCurrentDbColId = aCurrentDbColId;
       
  3034     TRACE_EXIT_POINT
       
  3035     }
       
  3036 
       
  3037 // -----------------------------------------------------------------------------
       
  3038 // CCalenEditorDataHandler::PreviousDbCollectionId
       
  3039 // Get previous collection id
       
  3040 // -----------------------------------------------------------------------------
       
  3041 //
       
  3042 TCalCollectionId CCalenEditorDataHandler::PreviousDbCollectionId()
       
  3043     {
       
  3044     TRACE_ENTRY_POINT
       
  3045     TRACE_EXIT_POINT
       
  3046     return iPreviousDbColId;
       
  3047     }
       
  3048 
       
  3049 // -----------------------------------------------------------------------------
       
  3050 // CCalenEditorDataHandler::CurrentDbCollectionId
       
  3051 // Get current collection id 
       
  3052 // -----------------------------------------------------------------------------
       
  3053 //
       
  3054 TCalCollectionId CCalenEditorDataHandler::CurrentDbCollectionId()
       
  3055     {
       
  3056     TRACE_ENTRY_POINT
       
  3057     TRACE_EXIT_POINT
       
  3058     return iCurrentDbColId;
       
  3059     }
       
  3060 
       
  3061 // -----------------------------------------------------------------------------
       
  3062 // CCalenEditorDataHandler::CalenInstanceId
       
  3063 // Returns the instance id.
       
  3064 // (other items were commented in a header).
       
  3065 // -----------------------------------------------------------------------------
       
  3066 //
       
  3067 const TCalenInstanceId CCalenEditorDataHandler::CalenInstanceId()
       
  3068     {
       
  3069     TRACE_ENTRY_POINT;
       
  3070     
       
  3071     TRACE_EXIT_POINT;
       
  3072     
       
  3073     return iInstanceId;
       
  3074     }
       
  3075 	
       
  3076 // End of file	--Don't remove this.