meetingrequest/mrgui/src/cesmrmeetingtimevalidator.cpp
changeset 0 8466d47a6819
child 1 12c456ceeff2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meetingrequest/mrgui/src/cesmrmeetingtimevalidator.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1750 @@
+/*
+* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  ESMR time and date sanity checks and saving
+ *
+*/
+
+
+#include "emailtrace.h"
+#include <eikmfne.h>
+#include <calentry.h>
+#include <calinstance.h>
+#include <calalarm.h>
+#include <calrrule.h>
+#include "cesmrmeetingtimevalidator.h"
+#include "cesmrglobalnote.h"
+#include "mesmrfieldstorage.h"
+#include "mesmrcalentry.h"
+#include "mesmrmeetingrequestentry.h"
+#include "mesmrfieldeventqueue.h"
+#include "cesmrgenericfieldevent.h"
+
+// Unnamed namespace for local definitions
+namespace { // codescanner::namespace
+
+// Definition fom max possible time
+#define KMaxTTime (TTime(TDateTime(2100, EDecember, 31-2, 23, 59, 59, 999999)))
+
+// Definition fom min possible time
+#define KMinTTime (TTime(TDateTime(1900, EJanuary, 2-1, 0, 0, 0, 0)))
+
+// Definition for max alarm duration
+#define KMaxAlarmTime TTimeIntervalDays(31)
+
+// Definition for alarm time offset, when alarm is off
+const TInt KAlarmNotSet(-1);
+
+#ifdef _DEBUG
+
+// Literal for panics
+_LIT( KESMRMeetingTimeValidator, "ESMRMeetingTimeValidator" );
+
+/** Panic code definitions */
+enum TKESMRMeetingTimeValidator
+    {
+    /** Start time field not set */
+    EESMRMeetingTimeValidatorNullStartTime,
+    /** Stop time field not set */
+    EESMRMeetingTimeValidatorNullStopTime,
+    /** Start date field not set */
+    EESMRMeetingTimeValidatorNullStartDate,
+    /** Stop date field not set */
+    EESMRMeetingTimeValidatorNullStopDate,
+    /** Stop time field not set */
+    EESMRMeetingTimeValidatorStartLaterThanEnd,
+    /** Invalid date field id */
+    EESMRMeetingTimeValidatorInvalidDateField
+    };
+
+/**
+ * Raises system panic.
+ * @param aPanic Panic code
+ * @see TESMRRecurrentEditValidatorPanic
+ */
+void Panic( TKESMRMeetingTimeValidator aPanic )
+    {
+    User::Panic( KESMRMeetingTimeValidator, aPanic );
+    }
+
+#endif // _DEBUG
+
+const TInt KZero( 0 );
+const TInt KOne( 1 );
+const TInt KDaysInWeek( 7 );
+const TInt KDaysInFortnight( 14 );
+const TInt KNoon(12);
+
+/**
+ * Calculates time for next instance for recurrent event.
+ * @param aRecurrenceValue Defines the used recurrence.
+ * @param aPrevInstanceStartTime Start time of the previous instance.
+ */
+TTime TimeForNextInstaceStartTime(
+        TESMRRecurrenceValue aRecurrenceValue,
+        TTime& aPrevInstanceStartTime )
+    {
+    TTime nextStartTime = aPrevInstanceStartTime;
+
+    switch ( aRecurrenceValue )
+        {
+        case ERecurrenceDaily:
+            {
+            nextStartTime += TTimeIntervalDays( KOne );
+            }
+            break;
+
+        case ERecurrenceWeekly:
+            {
+            nextStartTime += TTimeIntervalDays( KDaysInWeek );
+            }
+            break;
+
+
+        case ERecurrenceEverySecondWeek:
+            {
+            nextStartTime += TTimeIntervalDays( KDaysInFortnight );
+            }
+            break;
+
+        case ERecurrenceMonthly:
+            {
+            nextStartTime += TTimeIntervalMonths( KOne );
+            }
+            break;
+
+        case ERecurrenceYearly:
+            {
+            nextStartTime += TTimeIntervalYears( KOne );
+            }
+            break;
+
+        default:
+            nextStartTime = aPrevInstanceStartTime;
+            break;
+        }
+
+    return nextStartTime;
+    }
+
+/**
+ * Returns the default alarm time for all day event
+ * @param allday event start time
+ * @return alarm time
+ */
+TTime DefaultAlldayEventAlarmTime( TTime& aMeetingStartTime )
+    {
+    TTime defaultAlarmTime = aMeetingStartTime - TTimeIntervalHours(KNoon);
+
+    if ( defaultAlarmTime < KMinTTime )
+        {
+        defaultAlarmTime = KMinTTime;
+        }
+    return defaultAlarmTime;
+    }
+
+
+/**
+ * Sets time to editor. Time is checked and adjusted
+ * between min and max before setting
+ * @param aEditor Reference to time editor
+ * @param aTime On return contains the set time.
+ */
+void SetTimeToEditor(
+        CEikTimeEditor& aEditor,
+        TTime& aTime )
+    {
+    if ( aTime < KMinTTime )
+        {
+        aTime = KMinTTime;
+        }
+    else if ( aTime > KMaxTTime )
+        {
+        aTime = KMaxTTime;
+        }
+
+    if ( aEditor.IsVisible() )
+        {
+        aEditor.SetTime( aTime );
+        }
+    }
+
+/**
+ * Sets date to editor. Date is checked and adjusted
+ * between min and max before setting
+ * @param aEditor Reference to time editor
+ * @param aDate On return contains the set date.
+ */
+void SetDateToEditor(
+        CEikDateEditor& aEditor,
+        TTime& aDate )
+    {
+    if ( aDate < KMinTTime )
+        {
+        aDate = KMinTTime;
+        }
+    else if ( aDate > KMaxTTime )
+        {
+        aDate = KMaxTTime;
+        }
+
+    if ( aEditor.IsVisible() )
+        {
+        aEditor.SetDate( aDate );
+        }
+    }
+
+} // namespace
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::CESMRMeetingTimeValidator
+// ---------------------------------------------------------------------------
+//
+inline CESMRMeetingTimeValidator::CESMRMeetingTimeValidator()
+:   iRecurrenceValue( ERecurrenceNot ),
+    iCurrentStartTime( Time::NullTTime() ),
+    iCurrentEndTime( Time::NullTTime() ),
+    iCurrentAlarmTime( Time::NullTTime() ),
+    iCurrentRecurrenceUntil( Time::NullTTime() ),
+    iStartTimeBeforeAlldayEvent( Time::NullTTime() ),
+    iEndTimeBeforeAlldayEvent( Time::NullTTime() ),
+    iAlldayEvent( EFalse ),
+    iAlarmOnOff( EFalse ),
+    iComparativeStartTime( Time::NullTTime().DateTime() )
+    {
+    FUNC_LOG;
+    // Do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::~CESMRMeetingTimeValidator
+// ---------------------------------------------------------------------------
+//
+CESMRMeetingTimeValidator::~CESMRMeetingTimeValidator( )
+    {
+    FUNC_LOG;
+    // Do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::NewL
+// ---------------------------------------------------------------------------
+//
+CESMRMeetingTimeValidator* CESMRMeetingTimeValidator::NewL( )
+    {
+    FUNC_LOG;
+    CESMRMeetingTimeValidator* self = new (ELeave) CESMRMeetingTimeValidator();
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::ValidateL
+// ---------------------------------------------------------------------------
+//
+MESMRFieldValidator::TESMRFieldValidatorError
+        CESMRMeetingTimeValidator::ValidateL(
+                    TBool aCorrectAutomatically )
+    {
+    FUNC_LOG;
+    MESMRFieldValidator::TESMRFieldValidatorError KErrorNone(
+            MESMRFieldValidator::EErrorNone );
+
+    MESMRFieldValidator::TESMRFieldValidatorError error(
+            MESMRFieldValidator::EErrorNone );
+
+    if( aCorrectAutomatically )
+        {
+        ForceValuesL();
+        }
+    else
+        {
+        TTime startTime = StartDateTime();
+        TTime endTime = EndDateTime();
+
+        // In recurrent events if user has changed the start date and
+        // presses Save or Done, we have to force the end date to same
+        // value as start date and modify the recurrence until according
+        // to the new start time value
+        if ( ERecurrenceNot != iRecurrenceValue &&
+                ( startTime.DateTime().Day() != endTime.DateTime().Day() ||
+                startTime.DateTime().Month() != endTime.DateTime().Month() ||
+                startTime.DateTime().Year() != endTime.DateTime().Year() ) )
+            {
+            endTime = ForceEndDateTime();
+
+            SetTimeToEditor( *iEndTime, endTime );
+            SetDateToEditor( *iEndDate, endTime );
+
+            // We have to also adjust the recurrence until time
+            // according to the new start time
+            TTime newUntil = ForceRecurrenceUntilTime();
+
+            SetDateToEditor( *iRecurrenceUntilDate, newUntil );
+            }
+
+        TTime currentAlarmTime = startTime - iCurrentAlarmTimeOffset;
+        TTime currentTime;
+        currentTime.HomeTime();
+
+        if ( endTime < startTime )
+            {
+            error = MESMRFieldValidator::EErrorEndEarlierThanStart;
+            }
+
+        if ( KErrorNone == error && ERecurrenceNot != iRecurrenceValue )
+            {
+            TDateTime startDt = startTime.DateTime();
+            TDateTime endDt = endTime.DateTime();
+
+            if ( startDt.Day() != endDt.Day() ||
+                    startDt.Month() != endDt.Month() ||
+                    startDt.Year() != endDt.Year() )
+                {
+                error = MESMRFieldValidator::EErrorRecDifferetStartAndEnd;
+                }
+
+            if ( KErrorNone == error &&
+                 ERecurrenceNot != iRecurrenceValue &&
+                 iRecurrenceUntilDate && iRecurrenceUntilDate->IsVisible() )
+                {
+                TTime recurUntil = RecurrenceUntilTime();
+                if ( ERecurrenceUnknown != iRecurrenceValue &&
+                     recurUntil < startTime )
+                    {
+                    error = MESMRFieldValidator::EErrorRecUntilEarlierThanStart;
+                    }
+                }
+            }
+
+        if (  KErrorNone == error &&  
+              MESMRCalEntry::EESMRCalEntryMeetingRequest == iEntry->Type() )
+            {
+            // Check that is modified entry 
+            MESMRMeetingRequestEntry* mrEntry = 
+                    static_cast<MESMRMeetingRequestEntry*>( iEntry );
+            if ( mrEntry->IsRecurrentEventL() &&
+                 MESMRCalEntry::EESMRThisOnly == mrEntry->RecurrenceModRule() )
+                {
+                TBool instanceAlreadyOnThisDay( 
+                           mrEntry->AnyInstanceOnDayL(startTime, endTime) );
+                
+                if ( instanceAlreadyOnThisDay )
+                    {
+                    error = MESMRFieldValidator::EErrorRescheduleInstance;
+                    }
+                }
+            }         
+        
+        if ( KErrorNone == error && iAlldayEvent && iAlarmOnOff )
+            {
+            TTime alarmTime = AlarmDateTime();
+            if ( alarmTime > startTime )
+                {
+                SetTimeToEditor( *iAlarmTime, iCurrentAlarmTime );
+                SetDateToEditor( *iAlarmDate, iCurrentAlarmTime );
+
+                error = MESMRFieldValidator::EErrorAlarmLaterThanStart;
+                }
+
+            TTime currentTime;
+            currentTime.HomeTime();
+            if ( KErrorNone == error && alarmTime < currentTime )
+                {
+                error = MESMRFieldValidator::EErrorAlarmInPast;
+                }
+            if ( KErrorNone == error && alarmTime < startTime )
+                {
+                TTimeIntervalDays alarmBefore = startTime.DaysFrom(alarmTime);
+                if ( alarmBefore > KMaxAlarmTime )
+                    {
+                    error =  MESMRFieldValidator::EErrorAlarmTooMuchInPast;
+                    }
+                }
+            }
+
+        MESMRCalEntry::TESMRRecurrenceModifyingRule rule =
+            MESMRCalEntry::EESMRThisOnly;
+
+        // Checking if entry is recurrent
+        if ( iEntry->IsRecurrentEventL())
+            {
+            // Getting the recurrence information
+            rule = iEntry->RecurrenceModRule();
+            }
+
+        // Showing error note if alarm in past, when
+        // entry has no recurrence
+        if ( KErrorNone == error &&
+             currentAlarmTime < currentTime &&
+             !iAlldayEvent &&
+             iCurrentAlarmTimeOffset.Int() != KAlarmNotSet &&
+             iRecurrenceValue == ERecurrenceNot )
+            {
+            error = MESMRFieldValidator::EErrorRelativeAlarmInPast;
+            }
+
+        TTime until;
+        if ( iRecurrenceValue != ERecurrenceNot &&
+             iRecurrenceValue != ERecurrenceUnknown )
+            {
+            until = RecurrenceUntilTime();
+
+            // Showing error note if is alarm in past, 
+            // when entry has recurrence
+            if ( KErrorNone == error &&
+                 iCurrentAlarmTimeOffset.Int() != KAlarmNotSet &&
+                 until < currentTime &&
+                 rule != MESMRCalEntry::EESMRAllInSeries )
+                {
+                error = MESMRFieldValidator::EErrorRelativeAlarmInPast;
+                }
+            }
+        }
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::ReadValuesFromEntryL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::ReadValuesFromEntryL(
+        MESMRCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    MESMRCalEntry::TESMRCalEntryType entryType( aEntry.Type() );
+
+    if ( MESMRCalEntry::EESMRCalEntryMeetingRequest == entryType ||
+         MESMRCalEntry::EESMRCalEntryMeeting == entryType   )
+        {
+        // Meeting or meeting request
+        __ASSERT_DEBUG(
+                iStartTime,
+                Panic(EESMRMeetingTimeValidatorNullStartTime) );
+
+        __ASSERT_DEBUG(
+                iEndTime,
+                Panic(EESMRMeetingTimeValidatorNullStopTime) );
+
+        __ASSERT_DEBUG(
+                iStartDate,
+                Panic(EESMRMeetingTimeValidatorNullStartTime) );
+
+        __ASSERT_DEBUG(
+                iEndDate,
+                Panic(EESMRMeetingTimeValidatorNullStopTime) );
+
+        iEntry = &aEntry;
+        CCalEntry& entry( aEntry.Entry() );
+
+        iCurrentStartTime = entry.StartTimeL().TimeLocalL();
+        iCurrentEndTime   = entry.EndTimeL().TimeLocalL();
+
+        //Comparative start time required for comparisons in editor
+        //recurrence handling
+        iComparativeStartTime = iCurrentStartTime.DateTime();
+
+        if ( aEntry.IsAllDayEventL() )
+            {
+            iCurrentEndTime -= TTimeIntervalDays( KOne );
+            }
+
+        TTime start = iCurrentStartTime;
+        TTime end = iCurrentEndTime;
+
+        SetTimeToEditor( *iStartTime, start );
+        SetDateToEditor( *iStartDate, start );
+
+        SetTimeToEditor( *iEndTime, end );
+        SetDateToEditor( *iEndDate, end );
+
+        ReadAlarmFromEntryL( entry );
+        ReadRecurrenceFromEntryL( aEntry );
+
+        DrawEditorsDeferred();
+        }
+    }
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::StoreValuesToEntryL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::StoreValuesToEntryL(
+        MESMRCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    CCalEntry& entry( aEntry.Entry() );
+
+    // Before writing start and end time to enty, let's
+    // check is currently edited entry exception for series
+    // If entry is an exception and start time is set after
+    // repeat until date; the calinterim API will delete
+    // the recurrence rules from entry, so the
+    // solution to avoid this is to move the repeat until date
+    // to match the new start and end time for this exception entry.
+    if ( ERecurrenceNot == iRecurrenceValue &&
+         aEntry.IsRecurrentEventL() &&
+         MESMRCalEntry::EESMRThisOnly == aEntry.RecurrenceModRule() )
+        {
+        TCalRRule originalRRule;
+        if ( iEntry->Entry().GetRRuleL( originalRRule ) )
+            {
+            TTime localUntilTime = originalRRule.Until().TimeLocalL();
+            TTime endTime = EndDateTime();
+            TDateTime datetimeendtime = endTime.DateTime();
+            TDateTime datetimelocalUntil = localUntilTime.DateTime();
+
+            if ( endTime > localUntilTime )
+                {
+                TCalRRule rRule;
+                rRule.SetDtStart( originalRRule.DtStart() );
+                rRule.SetType( originalRRule.Type() );
+
+                TCalTime newUntil;
+                newUntil.SetTimeLocalL( endTime );
+                rRule.SetUntil( newUntil );
+                rRule.SetInterval( originalRRule.Interval() );
+                iEntry->Entry().SetRRuleL( rRule );
+                }
+            }
+        }
+    else if ( aEntry.IsRecurrentEventL() &&
+              MESMRCalEntry::EESMRAllInSeries == aEntry.RecurrenceModRule() )
+        {
+        TTime orgStartTime = iEntry->Entry().StartTimeL().TimeLocalL();
+        TTime orgEndTime = iEntry->Entry().EndTimeL().TimeLocalL();
+        
+        if ( orgStartTime != StartDateTime() || 
+             orgEndTime != EndDateTime() )
+            {
+            // We are editing the series --> We need to clear the recurrence from the entry
+            // When changing start or end time --> Exceptions needs to be cleared from the series
+            // It is set later in this method.
+            aEntry.SetRecurrenceL( ERecurrenceNot, Time::NullTTime() );
+            }
+        }
+
+    WriteStartAndEndTimeToEntryL( aEntry );
+
+    if ( iAlldayEvent )
+        {
+        TTime startTime = StartDateTime();
+        TTime endTime = EndDateTime();
+
+        // For all day event end time is adjusted 24 hours 
+        // forward so that it ends correctly
+        aEntry.SetAllDayEventL( startTime, endTime );
+
+        if ( iAlarmOnOff )
+            {
+            TTime alarmTime = AlarmDateTime();
+            TTimeIntervalMinutes alarmDiff;
+            startTime.MinutesFrom( alarmTime, alarmDiff );
+
+            CCalAlarm* alarm = CCalAlarm::NewL();
+            CleanupStack::PushL( alarm );
+            alarm->SetTimeOffset( alarmDiff );
+
+            entry.SetAlarmL( alarm );
+            CleanupStack::PopAndDestroy( alarm );
+            alarm = NULL;
+            }
+        else
+            {
+            entry.SetAlarmL( NULL );
+            }
+        }
+
+    if ( ERecurrenceNot != iRecurrenceValue &&
+         ERecurrenceUnknown != iRecurrenceValue )
+        {
+        aEntry.SetRecurrenceL(
+                iRecurrenceValue,
+                RecurrenceUntilTime() );
+        }
+    else if ( ERecurrenceNot == iRecurrenceValue &&
+              aEntry.IsRecurrentEventL() &&
+              MESMRCalEntry::EESMRAllInSeries == aEntry.RecurrenceModRule() )
+        {
+        aEntry.SetRecurrenceL(
+                iRecurrenceValue,
+                Time::NullTTime() );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetStartTimeFieldL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetStartTimeFieldL(
+        CEikTimeEditor& aStartTime )
+    {
+    FUNC_LOG;
+    iStartTime = &aStartTime;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetEndTimeFieldL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetEndTimeFieldL(
+        CEikTimeEditor& aEndTime )
+    {
+    FUNC_LOG;
+    iEndTime = &aEndTime;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetStartDateFieldL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetStartDateFieldL(
+        CEikDateEditor& aStartDate )
+    {
+    FUNC_LOG;
+    iStartDate = &aStartDate;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetEndDateFieldL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetEndDateFieldL(
+        CEikDateEditor& aEndTime )
+    {
+    FUNC_LOG;
+    iEndDate = &aEndTime;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetAlarmTimeFieldL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetAlarmTimeFieldL(
+        CEikTimeEditor& aAlarmTime )
+    {
+    FUNC_LOG;
+    iAlarmTime = &aAlarmTime;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetAlarmDateFieldL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetAlarmDateFieldL(
+        CEikDateEditor& aAlarmDate )
+    {
+    FUNC_LOG;
+    iAlarmDate = &aAlarmDate;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::StartTimeChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetRecurrenceUntilDateFieldL(
+        CEikDateEditor& aRecurrenceUntil )
+    {
+    FUNC_LOG;
+    iRecurrenceUntilDate = &aRecurrenceUntil;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::StartTimeChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::StartTimeChangedL()
+    {
+    FUNC_LOG;
+    StartDateChandedL();
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::EndTimeChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::EndTimeChangedL()
+    {
+    FUNC_LOG;
+    PreValidateEditorContent();
+    HandleEndTimeChangeL();
+    DrawEditorsDeferred();
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::StartDateChandedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::StartDateChandedL()
+    {
+    FUNC_LOG;
+    PreValidateEditorContent();    
+    HandleStartTimeChangeL();
+    HandleAlarmTimeChangedL();
+    DrawEditorsDeferred();
+    SendFieldChangeEventL( EESMRFieldStartDate );
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::EndDateChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::EndDateChangedL()
+    {
+    FUNC_LOG;
+    TInt err( KErrNone );
+
+    PreValidateEditorContent();
+
+    TTime start = StartDateTime();
+    TTime end = EndDateTime();
+
+    if ( end < start )
+        {
+        err = KErrArgument;
+        }
+
+    if ( err == KErrNone )
+        {
+        HandleEndTimeChangeL();
+        HandleAlarmTimeChangedL();
+        }
+    else
+        {
+        SetTimeToEditor( *iEndTime, iCurrentEndTime );
+        SetDateToEditor( *iEndDate, iCurrentEndTime );
+        }
+
+    DrawEditorsDeferred();
+
+    User::LeaveIfError( err );
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::AlarmTimeChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::AlarmTimeChangedL()
+    {
+    FUNC_LOG;
+    AlarmDateChangedL();
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::AlarmDateChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::AlarmDateChangedL()
+    {
+    FUNC_LOG;
+    if ( iAlarmOnOff && iAlarmTime && iAlarmDate && iAlldayEvent )
+        {
+        PreValidateEditorContent();
+        HandleAlarmTimeChangedL();
+        DrawEditorsDeferred();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::RelativeAlarmChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::RelativeAlarmChangedL(
+                                TTimeIntervalMinutes aCurrentAlarmTimeOffset,
+                                TBool aHandleAlarmChange,
+                                TBool& aRelativeAlarmValid )
+    {
+    FUNC_LOG;
+    iRelativeAlarmValid = &aRelativeAlarmValid;
+    iCurrentAlarmTimeOffset = aCurrentAlarmTimeOffset;
+
+    if ( aHandleAlarmChange )
+        {
+        HandleRelativeAlarmTimeChangedL();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetAllDayEventL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetAllDayEventL(
+        TBool aAlldayEvent )
+    {
+    FUNC_LOG;
+    if ( iAlldayEvent != aAlldayEvent )
+        {
+        iAlldayEvent = aAlldayEvent;
+
+        if ( iAlldayEvent )
+            {
+            iStartTimeBeforeAlldayEvent = iCurrentStartTime;
+            iEndTimeBeforeAlldayEvent = iCurrentEndTime;
+
+            TTime start = StartDateTime();
+            iCurrentStartTime = StartDateTime();
+            iCurrentEndTime = EndDateTime();
+
+            if ( iAlarmOnOff )
+                {
+                TTime alarm = DefaultAlldayEventAlarmTime( start );
+                SetTimeToEditor( *iAlarmTime, alarm );
+                SetDateToEditor( *iAlarmDate, alarm );
+                iCurrentAlarmTime = alarm;
+                }
+
+            DrawEditorsDeferred();
+            }
+        else
+            {
+            SetTimeToEditor( *iStartTime, iStartTimeBeforeAlldayEvent );
+            SetTimeToEditor( *iEndTime, iEndTimeBeforeAlldayEvent );
+
+            TTime start = StartDateTime();
+            TTime end = EndDateTime();
+
+            if ( start > end )
+                {
+                // User has modified dates so that end time
+                // is earlier than start time
+                end = start;
+                }
+
+            SetTimeToEditor( *iStartTime, start );
+            SetDateToEditor( *iStartDate, start );
+
+            SetTimeToEditor( *iEndTime, end );
+            SetDateToEditor( *iEndDate, end );
+
+            iCurrentStartTime = start;
+            iCurrentEndTime = end;
+
+            DrawEditorsDeferred();
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetAlarmOnOffL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetAlarmOnOffL(
+        TBool aAlarmOn )
+    {
+    FUNC_LOG;
+    iAlarmOnOff = aAlarmOn;
+
+    if ( iAlarmOnOff && iAlldayEvent )
+        {
+        TTime nullTime = Time::NullTTime();
+
+        if ( iCurrentAlarmTime > iCurrentStartTime ||
+             iCurrentAlarmTime == nullTime )
+            {
+            iCurrentAlarmTime = 
+				DefaultAlldayEventAlarmTime( iCurrentStartTime );
+            SetTimeToEditor( *iAlarmTime, iCurrentAlarmTime );
+            SetDateToEditor( *iAlarmDate, iCurrentAlarmTime );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::RecurrenceChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::RecurrenceChangedL(
+        TESMRRecurrenceValue aRecurrence )
+    {
+    FUNC_LOG;
+    if ( aRecurrence != iRecurrenceValue )
+        {
+
+        TDateTime start = StartDateTime();
+        TDateTime end = EndDateTime();
+
+        if ( start.Day() != end.Day() ||
+             start.Month() != end.Month() ||
+             start.Year() != end.Year())
+            {
+            User::Leave( KErrArgument );
+            }
+
+        iRecurrenceValue = aRecurrence;
+        PreValidateEditorContent();
+        HandleRecurrenceTypeChanged();
+        DrawEditorsDeferred();
+        }
+
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::RecurrenceEndDateChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::RecurrenceEndDateChangedL()
+    {
+    FUNC_LOG;
+    PreValidateEditorContent();
+    HandleRecurrenceEndDateChangedL();
+    DrawEditorsDeferred();
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::IsRelativeAlarmValid
+// ---------------------------------------------------------------------------
+//
+TBool CESMRMeetingTimeValidator::IsRelativeAlarmValid(
+		TTimeIntervalMinutes aAlarmTimeOffset )
+    {
+    FUNC_LOG;
+    TBool validity( ETrue );
+    TTime startTime = StartDateTime();
+    TTime currentTime;
+    currentTime.HomeTime();
+
+    if ( ( startTime - aAlarmTimeOffset ) < currentTime &&
+            aAlarmTimeOffset.Int() != KAlarmNotSet )
+        {
+        validity = EFalse;
+        }
+
+    return validity;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SetFieldEventQueue
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SetFieldEventQueue(
+        MESMRFieldEventQueue* aEventQueue )
+    {
+    FUNC_LOG;
+    iEventQueue = aEventQueue;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::PreValidateEditorContent
+// ---------------------------------------------------------------------------
+//
+TInt CESMRMeetingTimeValidator::PreValidateEditorContent()
+    {
+    FUNC_LOG;
+    TInt err( KErrNone );
+    TRAP( err, PreValidateEditorContentL() );
+    return err;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::PreValidateEditorContentL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::PreValidateEditorContentL()
+    {
+    FUNC_LOG;
+    if (iStartTime && iStartTime->IsVisible() )
+        {
+        iStartTime->PrepareForFocusLossL();
+        }
+    if (iEndTime && iEndTime->IsVisible() )
+        {
+        iEndTime->PrepareForFocusLossL();
+        }
+    if (iStartDate && iStartDate->IsVisible() )
+        {
+        iStartDate->PrepareForFocusLossL();
+        }
+    if (iEndDate && iEndDate->IsVisible() )
+        {
+        iEndDate->PrepareForFocusLossL();
+        }
+    if ( iAlarmOnOff && iAlarmTime && iAlldayEvent && iAlarmTime->IsVisible() )
+        {
+        TDateTime dt = iAlarmTime->Time().DateTime();
+        iAlarmTime->PrepareForFocusLossL();
+        }
+    if ( iAlarmOnOff && iAlarmDate && iAlldayEvent && iAlarmDate->IsVisible() )
+        {
+        iAlarmDate->PrepareForFocusLossL();
+        }
+    if ( iRecurrenceUntilDate && iRecurrenceUntilDate->IsVisible() )
+        {
+        iRecurrenceUntilDate->PrepareForFocusLossL();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::HandleStartTimeChangeL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::HandleStartTimeChangeL()
+    {
+    FUNC_LOG;
+    TTime startTime = StartDateTime();
+    TTime endTime   = EndDateTime();
+    
+    SetTimeToEditor( *iStartTime, startTime );
+    SetDateToEditor( *iStartDate, startTime );
+
+    TTimeIntervalMinutes startTimeChange;
+    User::LeaveIfError(
+            startTime.MinutesFrom(
+                    iCurrentStartTime,
+                    startTimeChange ) );
+
+    endTime += startTimeChange;
+    
+    if ( MESMRCalEntry::EESMRCalEntryMeetingRequest == iEntry->Type() )
+        {
+        MESMRMeetingRequestEntry* mrEntry = 
+                static_cast<MESMRMeetingRequestEntry*>( iEntry );
+        if ( mrEntry->IsRecurrentEventL() &&
+             MESMRCalEntry::EESMRThisOnly == mrEntry->RecurrenceModRule() )
+            {
+            TBool instanceAlreadyOnThisDay( 
+                       mrEntry->AnyInstanceOnDayL(startTime, endTime) );
+            
+            if ( instanceAlreadyOnThisDay )
+                {
+                // Restore previous time
+                SetTimeToEditor( *iStartTime, iCurrentStartTime );
+                SetDateToEditor( *iStartDate, iCurrentStartTime );
+                
+                User::Leave( KErrOverflow );
+                }
+            }
+        }
+    
+    SetTimeToEditor( *iEndTime, endTime );
+    SetDateToEditor( *iEndDate, endTime );
+
+    iCurrentStartTime = startTime;
+    iCurrentEndTime = endTime;
+
+    if ( iAlldayEvent && iAlarmOnOff &&
+         iAlarmTime->IsVisible() && iAlarmDate->IsVisible() )
+        {
+        TTime alarmTime = AlarmDateTime();
+        alarmTime += startTimeChange;
+
+        SetTimeToEditor( *iAlarmTime, alarmTime );
+        SetDateToEditor( *iAlarmDate, alarmTime );
+
+        iCurrentAlarmTime = alarmTime;
+        }
+
+    if ( ERecurrenceNot != iRecurrenceValue &&
+            iRecurrenceUntilDate && iRecurrenceUntilDate->IsVisible() )
+        {
+        TTime recUntil = RecurrenceUntilTime();
+
+        if ( startTime.DateTime().Day() != iComparativeStartTime.Day() ||
+             startTime.DateTime().Month() != iComparativeStartTime.Month() ||
+             startTime.DateTime().Year() != iComparativeStartTime.Year() )
+            {
+            // We want to update the recurrence until only when
+            // a) Day, b) Month, c) or Year of the start time has changed
+            recUntil += startTimeChange;
+            iComparativeStartTime = startTime.DateTime();
+            }
+
+        SetDateToEditor( *iRecurrenceUntilDate, recUntil );
+        iCurrentRecurrenceUntil = recUntil;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::HandleEndTimeChangeL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::HandleEndTimeChangeL()
+    {
+    FUNC_LOG;
+    TInt err( KErrNone );
+    TTime startTime = StartDateTime();
+    TTime endTime   = EndDateTime();
+
+    if ( !iAlldayEvent && endTime < startTime )
+        {
+        if( ERecurrenceNot != iRecurrenceValue )
+            {
+            err = KErrArgument;
+            }
+        else
+            {
+            // End time is earlier than start time
+            // and this is not allday event.
+            endTime += TTimeIntervalDays( KOne );
+            }
+        }
+
+    if ( MESMRCalEntry::EESMRCalEntryMeetingRequest == iEntry->Type() )
+        {
+        // Check that is modified entry 
+        MESMRMeetingRequestEntry* mrEntry = 
+                static_cast<MESMRMeetingRequestEntry*>( iEntry );
+        if ( mrEntry->IsRecurrentEventL() &&
+             MESMRCalEntry::EESMRThisOnly == mrEntry->RecurrenceModRule() )
+            {
+            TBool instanceAlreadyOnThisDay( 
+                       mrEntry->AnyInstanceOnDayL(startTime, endTime) );
+            
+            if ( instanceAlreadyOnThisDay )
+                {
+                // Restore previous time
+                SetTimeToEditor( *iStartTime, iCurrentStartTime );
+                SetDateToEditor( *iStartDate, iCurrentStartTime );
+                
+                err = KErrOverflow;
+                }
+            }
+        }    
+    
+    if ( KErrNone == err )
+        {
+        iCurrentStartTime = startTime;
+        iCurrentEndTime = endTime;
+        }
+
+    if ( !iAlldayEvent )
+        {
+        SetTimeToEditor( *iStartTime, iCurrentStartTime );
+        SetTimeToEditor( *iEndTime, iCurrentEndTime );
+        }
+
+    SetDateToEditor( *iStartDate, iCurrentStartTime );
+    SetDateToEditor( *iEndDate, iCurrentEndTime );
+
+    User::LeaveIfError( err );
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::HandleAlarmTimeChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::HandleAlarmTimeChangedL()
+    {
+    FUNC_LOG;
+    TInt err(KErrNone);
+
+    if ( iAlarmOnOff && iAlarmTime && iAlarmDate && iAlldayEvent )
+        {
+        TTime alarm = AlarmDateTime();
+        TTime start = StartDateTime();
+
+        if ( start < alarm )
+            {
+            alarm = iCurrentAlarmTime;
+            err = KErrArgument;
+            }
+        else
+            {
+            iCurrentAlarmTime = alarm;
+            }
+
+        SetTimeToEditor( *iAlarmTime, iCurrentAlarmTime );
+        SetDateToEditor( *iAlarmDate, iCurrentAlarmTime );
+        }
+
+    User::LeaveIfError( err );
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::HandleRelativeAlarmTimeChangedL()
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::HandleRelativeAlarmTimeChangedL()
+    {
+    FUNC_LOG;
+    TInt err( KErrNone );
+
+    // Getting current time
+    TTime currentTime;
+    currentTime.HomeTime();
+
+    // Getting meeting start time
+    TTime meetingStartTime = StartDateTime();
+
+    // Getting current alarm time
+    TTime currentAlarmTime = meetingStartTime - iCurrentAlarmTimeOffset;
+
+    // If alarm is set, entry is not recurrent, but alarm occures in past
+    if ( currentAlarmTime < currentTime &&
+            iCurrentAlarmTimeOffset.Int() != KAlarmNotSet &&
+            iRecurrenceValue == ERecurrenceNot )
+        {
+        err = KErrArgument;
+        }
+
+    if ( iRecurrenceValue != ERecurrenceNot &&
+            iRecurrenceValue != ERecurrenceUnknown )
+        {
+        TTime until = RecurrenceUntilTime();
+
+        // if alarm is set, entry is recurrent, but until date is in past
+        if ( iCurrentAlarmTimeOffset.Int() != KAlarmNotSet &&
+                until < currentTime )
+            {
+            err = KErrArgument;
+            }
+        }
+    
+    User::LeaveIfError( err );
+    }
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::HandleRecurrenceTypeChanged
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::HandleRecurrenceTypeChanged()
+    {
+    FUNC_LOG;
+    if ( ERecurrenceNot != iRecurrenceValue )
+        {
+        TTime start = StartDateTime();
+        TTime minTimeForRecurrenceEnd =
+                TimeForNextInstaceStartTime( iRecurrenceValue, start );
+
+        TDateTime a = iCurrentRecurrenceUntil.DateTime();
+        TDateTime b = minTimeForRecurrenceEnd.DateTime();
+
+        if ( iCurrentRecurrenceUntil < minTimeForRecurrenceEnd )
+            {
+            iCurrentRecurrenceUntil = minTimeForRecurrenceEnd;
+            }
+        }
+    else
+        {
+        iCurrentRecurrenceUntil = StartDateTime();
+        }
+
+    if ( iRecurrenceUntilDate )
+        {
+        SetDateToEditor( *iRecurrenceUntilDate, iCurrentRecurrenceUntil );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::HandleRecurrenceEndDateChangedL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::HandleRecurrenceEndDateChangedL()
+    {
+    FUNC_LOG;
+    TInt err( KErrNone );
+
+    TTime start = StartDateTime();
+    TTime recurrenceUntilTime = RecurrenceUntilTime();
+
+    if ( recurrenceUntilTime <= start )
+        {
+        err = KErrArgument;
+        }
+    else
+        {
+        iCurrentRecurrenceUntil = recurrenceUntilTime;
+        }
+
+    if ( iRecurrenceUntilDate )
+        {
+        SetDateToEditor( *iRecurrenceUntilDate, iCurrentRecurrenceUntil );
+        }
+
+    User::LeaveIfError( err );
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::DrawEditorsDeferred
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::DrawEditorsDeferred()
+    {
+    FUNC_LOG;
+    if (iStartTime && iStartTime->IsVisible() )
+        {
+        iStartTime->DrawDeferred();
+        }
+    if (iEndTime && iEndTime->IsVisible() )
+        {
+        iEndTime->DrawDeferred();
+        }
+    if (iStartDate && iStartDate->IsVisible() )
+        {
+        iStartDate->DrawDeferred();
+        }
+    if (iEndDate && iEndDate->IsVisible() )
+        {
+        iEndDate->DrawDeferred();
+        }
+    if ( iAlarmOnOff && iAlarmTime && iAlldayEvent && iAlarmTime->IsVisible()  )
+        {
+        iAlarmTime->DrawDeferred();
+        }
+    if ( iAlarmOnOff && iAlarmDate && iAlldayEvent  && iAlarmDate->IsVisible() )
+        {
+        iAlarmDate->DrawDeferred();
+        }
+    if ( iRecurrenceUntilDate  && iRecurrenceUntilDate->IsVisible() )
+        {
+        iRecurrenceUntilDate->DrawDeferred();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::StartDateTime
+// ---------------------------------------------------------------------------
+//
+TDateTime CESMRMeetingTimeValidator::StartDateTime()
+    {
+    FUNC_LOG;
+    TDateTime startDateTime = iStartDate->Date().DateTime();
+    TDateTime startTime = iStartTime->Time().DateTime();
+
+    if ( iAlldayEvent )
+        {
+        startDateTime.SetHour( KZero );
+        startDateTime.SetMinute( KZero );
+        startDateTime.SetSecond( KZero );
+        }
+    else
+        {
+        startDateTime.SetHour( startTime.Hour() );
+        startDateTime.SetMinute( startTime.Minute() );
+        startDateTime.SetSecond( startTime.Second() );
+        }
+
+    return startDateTime;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::EndDateTime
+// ---------------------------------------------------------------------------
+//
+TDateTime CESMRMeetingTimeValidator::EndDateTime()
+    {
+    FUNC_LOG;
+    TDateTime endDateTime = iEndDate->Date().DateTime();
+    TDateTime endTime = iEndTime->Time().DateTime();
+
+    if ( iAlldayEvent )
+        {
+        endDateTime.SetHour( KZero );
+        endDateTime.SetMinute( KZero );
+        endDateTime.SetSecond( KZero );
+        }
+    else
+        {
+        endDateTime.SetHour( endTime.Hour() );
+        endDateTime.SetMinute( endTime.Minute() );
+        endDateTime.SetSecond( endTime.Second() );
+        }
+
+    return endDateTime;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::AlarmDateTime
+// ---------------------------------------------------------------------------
+//
+TDateTime CESMRMeetingTimeValidator::AlarmDateTime()
+    {
+    FUNC_LOG;
+    TDateTime alarmDateTime = iAlarmDate->Date().DateTime();
+    TDateTime alarmTime = iAlarmTime->Time().DateTime();
+
+    alarmDateTime.SetHour( alarmTime.Hour() );
+    alarmDateTime.SetMinute( alarmTime.Minute() );
+    alarmDateTime.SetSecond( alarmTime.Second() );
+
+    return alarmDateTime;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::RecurrenceUntilTime
+// ---------------------------------------------------------------------------
+//
+TDateTime CESMRMeetingTimeValidator::RecurrenceUntilTime()
+    {
+    FUNC_LOG;
+    TDateTime recurrenceUntil =
+            iRecurrenceUntilDate->Date().DateTime();
+    TDateTime startTime = iStartTime->Time().DateTime();
+
+    recurrenceUntil.SetHour( startTime.Hour() );
+    recurrenceUntil.SetMinute( startTime.Minute() );
+    recurrenceUntil.SetSecond( startTime.Second() );
+
+    return recurrenceUntil;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::ReadAlarmFromEntryL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::ReadAlarmFromEntryL(
+        CCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    // Alarm is set for validating
+    CCalAlarm *alarm = aEntry.AlarmL();
+    CleanupStack::PushL( alarm );
+
+    if ( alarm )
+        {
+        // Alarm is set
+        iCurrentAlarmTime = iCurrentStartTime - alarm->TimeOffset();
+        }
+    else
+        {
+        iCurrentAlarmTime = Time::NullTTime();
+        iAlarmOnOff = EFalse;
+        }
+
+    CleanupStack::PopAndDestroy( alarm );
+    alarm = NULL;
+
+    if ( iAlarmDate && iAlarmTime && iAlarmOnOff )
+        {
+        SetTimeToEditor( *iAlarmTime, iCurrentAlarmTime );
+        SetDateToEditor( *iAlarmDate, iCurrentAlarmTime );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::ReadRecurrenceFromEntryL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::ReadRecurrenceFromEntryL(
+        MESMRCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    if ( aEntry.IsRecurrentEventL() &&
+            MESMRCalEntry::EESMRAllInSeries == aEntry.RecurrenceModRule() )
+        {
+        aEntry.GetRecurrenceL(
+                iRecurrenceValue,
+                iCurrentRecurrenceUntil );
+
+        if ( iRecurrenceUntilDate && iRecurrenceUntilDate->IsVisible() )
+            {
+            // Recurrence time has to be shown in the editor as local time
+            TCalTime recurrenceTime;
+            recurrenceTime.SetTimeUtcL( iCurrentRecurrenceUntil );
+            TTime localRecurrenceTime = recurrenceTime.TimeLocalL();
+            
+            SetDateToEditor( *iRecurrenceUntilDate, localRecurrenceTime );
+            }
+        }
+    else
+        {
+        iRecurrenceValue = ERecurrenceNot;        
+        }
+
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::ForceValuesL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::ForceValuesL()
+    {
+    FUNC_LOG;
+    TTime startTime = StartDateTime();
+    TTime endTime = EndDateTime();
+
+    if ( endTime < startTime )
+        {
+        // For end and start date following check and correction is made:
+        // - Entry ends earlier than starts
+        //    --> For stored entries, orginal values are restored.
+        //    --> For unsaved entries endTime is set to start time.
+        //
+        if ( iEntry->IsStoredL() )
+            {
+            // If entry is stored, orginal values are restored
+            const CCalEntry& orginalEntry( iEntry->OriginalEntry() );
+            startTime = orginalEntry.StartTimeL().TimeLocalL();
+            endTime = orginalEntry.EndTimeL().TimeLocalL();
+            }
+        else
+            {
+            endTime = startTime;
+            }
+        }
+
+    // if entry has not directly supported recurrence value
+    // e.g. every second day; the repeat until field is
+    // in read only mode and iRecurrenceUntilDate is
+    // not set to validator
+    if ( iRecurrenceUntilDate &&
+         ERecurrenceNot != iRecurrenceValue )
+        {
+        // For recurrent event following checks and corrections are made:
+        //   - Start and end date are the same. If not --> end = start
+        //   - recurrence until is not earlier than start
+        //     --> recurrenceUntil = start + one year
+        //
+        TDateTime startDt = startTime.DateTime();
+        TDateTime endDt = endTime.DateTime();
+
+        if ( startDt.Day() != endDt.Day() ||
+             startDt.Month() != endDt.Month() ||
+             startDt.Year() != endDt.Year() )
+            {
+            // Setting start and end date to be the same day
+            endDt.SetDay( startDt.Day() );
+            endDt.SetMonth( startDt.Month() );
+            endDt.SetYear( startDt.Year() );
+            endTime = endDt;
+            }
+
+        TTime recurUntil = RecurrenceUntilTime();
+        if ( ERecurrenceUnknown != iRecurrenceValue &&
+             recurUntil < startTime )
+            {
+            recurUntil = startTime + TTimeIntervalYears( KOne );
+            iCurrentRecurrenceUntil = recurUntil;
+            }
+        }
+
+    if ( iAlldayEvent && iAlarmOnOff )
+        {
+        // For alarm following cehcks and corrections are made:
+        // - Alarm is more that 31 days before start
+        //    --> Alarm is adjusted to be 30,5 half days before
+        // - Alarm is later than start time
+        //     --> Default alarm time is set for alarm
+        // - Alarm occurs in past
+        //    --> For unsaved entries alarm is set off
+        //
+        TTime alarmTime = AlarmDateTime();
+        TTimeIntervalDays alarmBefore = startTime.DaysFrom(alarmTime);
+        if ( alarmBefore > KMaxAlarmTime )
+            {
+            // Adjust alarm time to 30,5 half days earlier
+            alarmTime = startTime - KMaxAlarmTime + TTimeIntervalHours(KNoon);
+            }
+
+        if ( alarmTime > startTime )
+            {
+            // Setting alarm to default value
+            alarmTime = DefaultAlldayEventAlarmTime( startTime );
+            }
+
+        TTime currentTime; currentTime.HomeTime();
+        if ( alarmTime < currentTime )
+            {
+            if ( !iEntry->IsStoredL() )
+                {
+                // Setting alarm to default value if entry is not stored
+                iAlarmOnOff = EFalse;
+                }
+            }
+
+        iCurrentAlarmTime = alarmTime;
+        }
+
+    TTime currentTime;
+    currentTime.HomeTime();
+
+    // If relative alarm time is in past
+    if ( !iAlldayEvent &&
+            ( startTime - iCurrentAlarmTimeOffset ) < currentTime )
+        {
+        // Setting relative alarm to off
+        iCurrentAlarmTimeOffset = KAlarmNotSet;
+        *iRelativeAlarmValid = EFalse;
+        }
+
+    iCurrentStartTime = startTime;
+    iCurrentEndTime = endTime;
+
+    // Start
+    SetTimeToEditor( *iStartTime, startTime );
+    SetDateToEditor( *iStartDate, startTime );
+
+    // End
+    SetTimeToEditor( *iEndTime, endTime );
+    SetDateToEditor( *iEndDate, endTime );
+
+    // Alarm
+    if(iAlarmTime)
+        {
+        SetTimeToEditor( *iAlarmTime, iCurrentAlarmTime );
+        }
+
+    if(iAlarmDate)
+        {
+        SetDateToEditor( *iAlarmDate, iCurrentAlarmTime );
+        }
+
+
+    // if editing certain occurance of recurrent event series
+    // the repeat until date is not available.
+    if ( iRecurrenceUntilDate )
+        {
+        // Recurrence until
+        SetDateToEditor( *iRecurrenceUntilDate, iCurrentRecurrenceUntil );
+        }
+
+    }
+
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::ForceEndDateTime
+// ---------------------------------------------------------------------------
+//
+TDateTime CESMRMeetingTimeValidator::ForceEndDateTime()
+    {
+    FUNC_LOG;
+    // In recurrent event cases, when user has modified the end date
+    // and presses Done or Save, the end date has to be adjusted to
+    // the current start date. The Hours, minutes and seconds should
+    // still remain in original value though.
+
+    TDateTime startDateTime = iStartDate->Date().DateTime();
+
+    TDateTime modifiedEndDateTime = iEndDate->Date().DateTime();
+    TDateTime endTime = iEndTime->Time().DateTime();
+
+    modifiedEndDateTime.SetDay( startDateTime.Day() );
+    modifiedEndDateTime.SetMonth( startDateTime.Month() );
+    modifiedEndDateTime.SetYear( startDateTime.Year() );
+
+    modifiedEndDateTime.SetHour( endTime.Hour() );
+    modifiedEndDateTime.SetMinute( endTime.Minute() );
+    modifiedEndDateTime.SetSecond( endTime.Second() );
+
+    return modifiedEndDateTime;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::ForceRepeatUntilTimeL
+// ---------------------------------------------------------------------------
+//
+TTime CESMRMeetingTimeValidator::ForceRecurrenceUntilTime()
+    {
+    FUNC_LOG;
+    // In recurrent event cases, when user has modified the end date
+    // and presses Done or Save, the recurrence until time has to be
+    // adjusted according to the new start date.
+
+    TTime newUntil(0);
+
+    // Let's find out what the original period of recurrence was
+    TTimeIntervalMinutes recurrencePeriod(0);
+    TDateTime originalStartTime = iComparativeStartTime;
+
+    // We do not need Hours, Minutes, seconds when setting
+    // recurrence until date
+    originalStartTime.SetHour(0);
+    originalStartTime.SetMinute(0);
+    originalStartTime.SetSecond(0);
+
+    TTime originalRecurrenceUntilTime = iRecurrenceUntilDate->Date();
+
+    originalRecurrenceUntilTime.MinutesFrom(
+            originalStartTime, recurrencePeriod );
+
+    // New recurrence until time is the new meeting start date plus
+    // the recurrence period
+    newUntil = iStartDate->Date() + recurrencePeriod;
+
+    return newUntil;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::WriteStartAndEndTimeToEntryL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::WriteStartAndEndTimeToEntryL(
+        MESMRCalEntry& aEntry )
+    {
+    FUNC_LOG;
+    CCalEntry& entry( aEntry.Entry() );
+    const CCalEntry& originalEntry( aEntry.OriginalEntry() );
+
+    TTime startTime = StartDateTime();
+    TTime endTime = EndDateTime();
+
+    TTime orgStartTime = originalEntry.StartTimeL().TimeLocalL();
+    TTime orgEndTime   = originalEntry.EndTimeL().TimeLocalL();
+
+    if ( !aEntry.IsStoredL() || orgStartTime != startTime ||
+         orgEndTime != endTime )
+        {
+        // End time has changed --> Store it to entry
+        TCalTime start;
+        start.SetTimeLocalL( startTime );
+
+        TCalTime end;
+        end.SetTimeLocalL( endTime );
+
+        TDateTime st = start.TimeLocalL().DateTime();
+        TDateTime et = end.TimeLocalL().DateTime();
+
+        entry.SetStartAndEndTimeL( start, end );
+        }
+    else if ( aEntry.IsRecurrentEventL() &&
+              MESMRCalEntry::EESMRAllInSeries == aEntry.RecurrenceModRule() )
+        {
+        // For recurrent events, parent entry's start and end time is stored
+        // to entry.
+
+        CCalInstance* instance = aEntry.InstanceL();
+        if ( instance )
+            {
+            CleanupStack::PushL( instance );
+
+            CCalEntry& parent = instance->Entry();
+            entry.SetStartAndEndTimeL(
+                    parent.StartTimeL(),
+                    parent.EndTimeL() );
+
+            CleanupStack::PopAndDestroy( instance );
+            instance = NULL;
+            }
+        }
+
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRMeetingTimeValidator::SendFieldChangeEventL
+// ---------------------------------------------------------------------------
+//
+void CESMRMeetingTimeValidator::SendFieldChangeEventL(
+        TESMREntryFieldId aFieldId )
+    {
+    FUNC_LOG;
+    if ( iEventQueue )
+        {
+        CESMRGenericFieldEvent* event =
+            CESMRGenericFieldEvent::NewLC( NULL,
+                                           MESMRFieldEvent::EESMRFieldChangeEvent );
+        TInt fieldId = aFieldId;
+        CESMRFieldEventValue* field = CESMRFieldEventValue::NewLC(
+                CESMRFieldEventValue::EESMRInteger, &fieldId );
+        event->AddParamL( field );
+        CleanupStack::Pop( field );
+        CESMRFieldEventValue* date = CESMRFieldEventValue::NewLC(
+                CESMRFieldEventValue::EESMRTTime, &iCurrentStartTime );
+        event->AddParamL( date, ETrue );
+        CleanupStack::Pop( date );
+        iEventQueue->NotifyEventL( *event );
+        CleanupStack::PopAndDestroy( event );
+        }
+    }
+
+// EOF
+