meetingrequest/mrviewer/src/cesmrviewerctrl.cpp
branchRCL_3
changeset 12 4ce476e64c59
parent 0 8466d47a6819
child 16 b5fbb9b25d57
--- a/meetingrequest/mrviewer/src/cesmrviewerctrl.cpp	Mon Mar 15 12:39:10 2010 +0200
+++ b/meetingrequest/mrviewer/src/cesmrviewerctrl.cpp	Wed Mar 31 21:08:33 2010 +0300
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). 
+* 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"
@@ -24,26 +24,31 @@
 //</cmail>
 
 #include "cesmrviewerctrl.h"
-#include "cesmrentryprocessor.h"
+#include "cmrentryprocessor.h"
 #include "mesmrmeetingrequestentry.h"
 #include "mesmrtaskextension.h"
-//<cmail>
+#include "esmrentryhelper.h"
+#include "esmrhelper.h"
 #include "cesmruifactory.h"
-//</cmail>
+
 #include "mesmruibase.h"
 #include "tesmrinputparams.h"
+#include "tmroutputparams.h"
 #include "esmrconfig.hrh"
 #include "cesmrconfirmationquery.h"
 #include "cesmrutils.h"
-#include "cesmrattachmentinfo.h"
 #include "cesmrcaluserutil.h"
-// <cmail> Removed profiling. </cmail>
+#include "cesmrlistquery.h"
+#include "cesmrcaldbmgr.h"
+
+#include "cesmrtaskfactory.h"
+#include "cesmrtaskextensionimpl.h"
 
 // Logging utilities
 
 // From System
 //<cmail>
-#include <CMRUtils.h>
+#include <cmrutils.h>
 #include "esmrutilsapiext.h"
 //</cmail>
 #include <msvstd.h>
@@ -53,6 +58,9 @@
 //</cmail>
 #include <eikappui.h>
 #include <eikenv.h>
+#include <calentry.h>
+#include <caleninterimutils2.h>
+#include <calcommon.h>
 
 // CONSTANTS
 /// Unnamed namespace for local definitions
@@ -70,6 +78,8 @@
     EESMRViewerCtrlProcessor,
     EESMRViewerCtrlTaskExt,
     EESMRViewerCtrlPolicyMgr,
+    EESMRViewerCtrlInvalidModifyingRule,
+    EESMRViewerCtrlInvalidEntryType
     };
 
 void Panic(TMRViewerCtrlPanicCode aPanicCode)
@@ -80,25 +90,140 @@
 #endif
 
 /**
- * Tests if entry contains attachments or not.
- * @param aEntry Reference to meeting request entry.
- * @return ETrue if entry contains attachments
+ * Maps calendar entry type to MR entry type
+ * @param aEntryType to be mapped to MR entry type
+ * @return MR event type
  */
-TBool ContainsAttachmentsL(
-        MESMRMeetingRequestEntry& aEntry )
+TESMRCalendarEventType MapType( const CCalEntry& aEntry )
     {
-    TBool retValue( EFalse );
+    TESMRCalendarEventType type( EESMREventTypeNone );
 
-    TESMRInputParams esmrInputParams;
-    if ( aEntry.StartupParameters(esmrInputParams)  )
+    switch ( aEntry.EntryTypeL() )
         {
-        if ( esmrInputParams.iAttachmentInfo &&
-                esmrInputParams.iAttachmentInfo->AttachmentCount() )
+        case CCalEntry::EAppt:
+            {
+            if( CCalenInterimUtils2::IsMeetingRequestL( 
+                    ( const_cast<CCalEntry&>( aEntry ) ) ) )
+                {
+                type = EESMREventTypeMeetingRequest;
+                }
+            else
+                {
+                type = EESMREventTypeAppt;
+                }
+            break;
+            }
+        case CCalEntry::ETodo:
             {
-            retValue = ETrue;
+            type = EESMREventTypeETodo;
+            break;
+            }
+        case CCalEntry::EEvent:
+            {
+            type = EESMREventTypeEEvent;
+            break;
+            }
+        case CCalEntry::EReminder:
+            {
+            type = EESMREventTypeEReminder;
+            break;
+            }
+        case CCalEntry::EAnniv:
+            {
+            type = EESMREventTypeEAnniv;
+            break;
+            }
+        default:
+            {
+            __ASSERT_DEBUG( EFalse, Panic( EESMRViewerCtrlInvalidEntryType ) );
             }
         }
-    return retValue;
+
+    return type;
+    }
+
+/**
+ * Creates calendar entry
+ * @param required parameters for creating an entry
+ * @return CCalEntry Created entry.
+ */
+CCalEntry* CreateEntryL(
+        CCalEntry::TType aType,
+        const TDesC8& aUid,
+        CCalEntry::TMethod aMethod,
+        CalCommon::TRecurrenceRange aRange )
+    {
+    HBufC8* guid = aUid.AllocLC();
+    CCalEntry* entry = CCalEntry::NewL( aType, guid, aMethod, aRange );
+    CleanupStack::Pop( guid );
+
+    return entry;
+    }
+
+/**
+ * Converts to-do specific priority to normal priority
+ * @param Calendar entry, which priority is converted
+ * @return The converted priority
+ */
+TInt ConvertTodoPriorityToNormalL( const CCalEntry& entry )
+    {
+    FUNC_LOG;
+    TInt priority( 0 );
+    if( entry.PriorityL() == EFSCalenTodoPriorityHigh )
+        {
+        priority = EFSCalenMRPriorityHigh;
+        }
+    
+    else if( entry.PriorityL() == EFSCalenTodoPriorityNormal )
+        {
+        priority = EFSCalenMRPriorityNormal;
+        }
+    
+    else if( entry.PriorityL() == EFSCalenTodoPriorityLow )
+        {
+        priority = EFSCalenMRPriorityLow;
+        }
+    
+    else
+        {
+        // Priority unknown, let's set it to normal then
+        priority = EFSCalenMRPriorityNormal;
+        }
+
+    return priority;
+    }
+
+/**
+ * Converts normal priority to to-do specific priority
+ * @param Calendar entry, which priority is converted
+ * @return The converted priority
+ */
+TInt ConvertNormalPriorityToTodoL( const CCalEntry& entry )
+    {
+    FUNC_LOG;
+    TInt priority( 0 );
+    if( entry.PriorityL() == EFSCalenMRPriorityHigh )
+        {
+        priority = EFSCalenTodoPriorityHigh;
+        }
+    
+    else if( entry.PriorityL() == EFSCalenMRPriorityNormal )
+        {
+        priority = EFSCalenTodoPriorityNormal;
+        }
+    
+    else if( entry.PriorityL() == EFSCalenMRPriorityLow )
+        {
+        priority = EFSCalenTodoPriorityLow;
+        }
+    
+    else
+        {
+        // Priority unknown, let's set it to normal then
+        priority = EFSCalenMRPriorityNormal;
+        }
+
+    return priority;
     }
 
 }  // namespace
@@ -130,10 +255,11 @@
 //
 EXPORT_C CESMRViewerController::~CESMRViewerController()
     {
-    FUNC_LOG;
-    delete iESMRUtils;
+    FUNC_LOG;    
     delete iCtrlSyncher;
     delete iGuiFactory;
+    delete iCalEntry;
+    delete iESMRUtils;
     }
 
 // -----------------------------------------------------------------------------
@@ -176,6 +302,9 @@
             iInParams.iCalSession,
             iInParams.iMsgSession );
 
+    iESMRUtils->CreateExtensionsL(
+            ESMREntryHelper::EventTypeL( *(iEntries[0]) ) );
+
     iGuiFactory = CESMRUiFactory::NewL();
     }
 
@@ -201,7 +330,7 @@
     User::LeaveIfError( iExecutionError );
 
     iEntryProcessor =
-        static_cast<CESMREntryProcessor*>(
+        static_cast<CMREntryProcessor*>(
                 iESMRUtils->ExtensionL(
                         TUid::Uid(KESMRMREntryProcessorUid) ) );
 
@@ -324,6 +453,24 @@
     }
 
 // -----------------------------------------------------------------------------
+// CESMRViewerController::PolicyProvider
+// -----------------------------------------------------------------------------
+//
+MMRPolicyProvider& CESMRViewerController::PolicyProvider() const
+    {
+    return *iPolicyMgr;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRViewerController::EntryL
+// -----------------------------------------------------------------------------
+//
+MESMRCalEntry* CESMRViewerController::EntryL()
+    {
+    return &iEntryProcessor->ESMREntryL();
+    }
+
+// -----------------------------------------------------------------------------
 // CESMRViewerController::ProcessCommandWithResultInternalL
 // -----------------------------------------------------------------------------
 //
@@ -332,10 +479,230 @@
     {
     FUNC_LOG;
 
+    TInt ret = ProcessDefaultCommandL( aCommandId );
+
+    if ( ret == KErrNotSupported )
+        {
+        ret = ProcessMeetingRequestCommandL( aCommandId );
+        }
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRViewerController::ProcessDefaultCommandL
+// -----------------------------------------------------------------------------
+//
+TInt CESMRViewerController::ProcessDefaultCommandL( TInt aCommandId )
+    {
+    FUNC_LOG;
 
     TESMRCommand command = static_cast<TESMRCommand>(aCommandId);
     TBool needToProcessOutputParams( ETrue );
-    MESMRMeetingRequestEntry& entry = iEntryProcessor->ESMREntryL();
+
+    MESMRCalEntry& entry = iEntryProcessor->ESMREntryL();
+    TInt ret = KErrNone;
+
+    MESMRCalDbMgr& dbMgr = entry.GetDBMgr();
+    switch( aCommandId )
+        {
+        case EESMRCmdSaveMR:            // Saves Entry
+        case EESMRCmdCalEntryUISave:
+            {
+            // If we are editing an existing entry.
+            if ( entry.IsStoredL() )
+                {
+                // If entry is type changed.
+                if ( entry.IsEntryTypeChangedL() )
+                    {
+                    // If entry is type changed, delete the old entry first
+                    // from db ... 
+
+                    CCalEntry* lastStoredEntry = 
+                            dbMgr.FetchEntryL( 
+                                    entry.Entry().UidL(), 
+                                    entry.Entry().RecurrenceIdL() );
+                    ASSERT( lastStoredEntry );
+                    CleanupStack::PushL( lastStoredEntry );
+                    
+                    if( CCalenInterimUtils2::IsMeetingRequestL( 
+                                    *lastStoredEntry ) )
+                        {
+                        // Last stored entry was MR. If MR is sent, it needs to be 
+                        // also cancelled before deleting
+                        CancelAndDeleteMRInEntryTypeChangeL( 
+                                *lastStoredEntry,dbMgr );
+                        }
+                    else
+                        {
+                        // Use right taskExtension                        
+                        CESMRTaskFactory* taskFactory = CESMRTaskFactory::NewL(
+                        		MapType( *lastStoredEntry ),
+                        		dbMgr );
+                        CleanupStack::PushL( taskFactory );                        
+                        
+                        MESMRTaskExtension* taskExtension =
+                            CESMRTaskExtenstionImpl::NewL( *taskFactory );
+                        CleanupDeletePushL( taskExtension );
+                        
+                        taskExtension->DeleteEntryFromLocalDBL(
+                                EESMRCmdCalEntryUIDelete,
+                                entry );
+                        
+                        CleanupStack::PopAndDestroy( taskExtension );                         
+                        CleanupStack::PopAndDestroy( taskFactory );                                                
+                        }
+                    
+                    // ... and then store the new (edited) entry to db.
+                    iTaskExt->StoreEntryToLocalDBL(
+                            command,
+                            entry );
+                    
+                    CleanupStack::PopAndDestroy( lastStoredEntry );
+                    }
+                
+                // If we are saving entry that previously existed in 
+                // different db.
+                else if ( dbMgr.EntryViewL( entry.Entry() ) != NULL
+                          && dbMgr.EntryViewL( entry.Entry() ) != dbMgr.EntryView() )
+                    {
+                    iTaskExt->MoveEntryToCurrentDBL( command, entry );
+                    }
+                
+                // And if none of the above conditions apply, we are just editing 
+                // an entry and want to save it.
+                else
+                    {
+                    iTaskExt->StoreEntryToLocalDBL(
+                                            command,
+                                            entry );
+                    }
+                }
+            
+            // Store new entry to db.
+            else
+                {
+                iTaskExt->StoreEntryToLocalDBL(
+                        command,
+                        entry );
+                }
+            }
+            break;
+
+        case EESMRCmdCalEntryUIDelete:           // Deletes Entry
+            {
+            iTaskExt->DeleteEntryFromLocalDBL(
+                    command,
+                    entry );
+
+            }
+            break;
+
+        case EESMRCmdEdit:              // Edit MR
+        case EESMRCmdEditLocal:         // Locally edit meeting request
+        case EESMRCmdCalEntryUIEdit:    // Edit calendar entries
+            {
+            iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeEdit );
+            iPolicyMgr->PushPolicyL();
+            LaunchUIL();
+
+            // No need to process parameters because the view is closed
+            // and editing view has processed to parameters
+            needToProcessOutputParams = EFalse;
+            iPolicyMgr->PopPolicy();
+
+            iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeView );
+            }
+            break;
+
+        case EESMRCmdCalEntryUISend:      // Send calendar entry item
+        case EESMRCmdCalEntryUIAddParticipants:  // Add participants to meeting item
+            {
+            ASSERT( EFalse ); // TODO: implement when tasks are ready
+            }
+            break;
+
+        case EESMRCmdEditorInitializationComplete:
+            {
+            if ( iCallback.IsCommandAvailable( EESMRCmdEditorInitializationComplete ) )
+                {
+                iCallback.ProcessCommandL( EESMRCmdEditorInitializationComplete );
+                }
+            break;
+            }
+
+        case EMRCommandSwitchToMR:
+        case EMRCommandSwitchToMeeting:
+        case EMRCommandSwitchToMemo:
+        case EMRCommandSwitchToAnniversary:
+        case EMRCommandSwitchToTodo:
+            {
+            ChangeEntryTypeL( aCommandId );
+            needToProcessOutputParams = EFalse;
+            }
+            break;
+
+        /*
+        case EMRLaunchAttachmentsView:
+        case EMRViewAttachmentInCorrespondingApp:
+            {
+            iCallback.ProcessCommandL( command );
+            }
+            break;
+*/
+        case EESMRCmdTodoMarkAsDone:
+            {
+            iTaskExt->MarkTodoAsDoneL( command,
+                    iEntryProcessor->ESMREntryL() );
+            }
+            break;
+
+        case EESMRCmdTodoMarkAsNotDone:
+            {
+            iTaskExt->MarkTodoAsNotDoneL( command,
+                    iEntryProcessor->ESMREntryL() );
+            }
+            break;
+
+        default:
+            ret = KErrNotSupported;
+            needToProcessOutputParams = EFalse;
+            break;
+        }
+
+    if ( needToProcessOutputParams )
+        {
+        iEntryProcessor->ProcessOutputParametersL(
+                iOutParams,
+                command );
+        }
+
+
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRViewerController::ProcessMeetingRequestCommandL
+// -----------------------------------------------------------------------------
+//
+TInt CESMRViewerController::ProcessMeetingRequestCommandL( TInt aCommandId )
+    {
+    FUNC_LOG;
+
+    TESMRCommand command = static_cast<TESMRCommand>(aCommandId);
+    TBool needToProcessOutputParams( ETrue );
+
+    MESMRCalEntry* tmpEntry = &iEntryProcessor->ESMREntryL();
+
+    ASSERT( tmpEntry->Type() == EESMREventTypeMeetingRequest );
+
+    if ( tmpEntry->Type() != EESMREventTypeMeetingRequest )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    MESMRMeetingRequestEntry& entry( *static_cast<MESMRMeetingRequestEntry*>( tmpEntry ) );
+    MESMRCalDbMgr& dbMgr = entry.GetDBMgr();
 
     switch( aCommandId )
         {
@@ -343,6 +710,22 @@
         case EESMRCmdSendMRUpdate:      // Send MR update
             {
             entry.ConfirmEntryL();
+
+            if( entry.IsStoredL() )
+                {
+                if( entry.IsEntryTypeChangedL() ||
+                        ( ( dbMgr.EntryViewL( entry.Entry() ) != NULL ) &&
+                        ( dbMgr.EntryViewL( entry.Entry() ) != dbMgr.EntryView() ) ) )
+                    {
+                    if(!entry.IsEntryTypeChangedL())
+                    	{
+                    	entry.SetSendCanellationAvailable( EFalse );
+                    	}
+                    iTaskExt->DeleteEntryFromLocalDBL(
+                            EESMRCmdDeleteMR,
+                            entry );
+                    }
+                }
             iTaskExt->SendAndStoreMRL(
                             command,
                             entry );
@@ -352,22 +735,11 @@
         case EESMRCmdAcceptMR:          // Accept received MR
         case EESMRCmdTentativeMR:       // Tentatively accept MR
         case EESMRCmdDeclineMR:         // Decline MR
-
             {
-            if ( entry.IsRecurrentEventL() )
-                {
-                entry.SetModifyingRuleL(MESMRCalEntry::EESMRAllInSeries);
-                }
-            
-            entry.ConfirmEntryL();
-            iTaskExt->SendAndStoreResponseL(command,entry );
-                        
-            if ( entry.IsOpenedFromMail() )
-               	{
-               	// Triggering mail delete command also
-               	needToProcessOutputParams = EFalse;
-               	iCallback.ProcessCommandL( EESMRCmdMailDelete );
-               	}
+			entry.ConfirmEntryL();
+			iTaskExt->SendAndStoreResponseL(
+					command,
+					entry );
             }
             break;
 
@@ -382,14 +754,6 @@
             }
             break;
 
-        case EESMRCmdSaveMR:            // Saves MR
-            {
-            iTaskExt->StoreMRToLocalDBL(
-                    command,
-                    entry );
-            }
-            break;
-
         case EESMRCmdDeleteMR:           // Deletes MR
         case EESMRCmdRemoveFromCalendar: // Removes MR from calendar
         case EESMRCmdMailDelete:         // Mail specific delete command
@@ -413,35 +777,24 @@
             }
             break;
 
-        case EESMRCmdEdit:              // Edit MR
-        case EESMRCmdEditLocal:         // Locally edit meeting request
-            {
-            iEntryProcessor->SwitchToEditL();
-            iPolicyMgr->PushPolicyL();
-            LaunchUIL();
-
-            // No need to process parameters because the view is closed
-            // and editing view has processed to parameters
-            needToProcessOutputParams = EFalse;
-            iPolicyMgr->PopPolicy();
-            iEntryProcessor->SwitchToViewL();
-            }
-            break;
         case EESMRCmdViewTrack:
             {
             TESMRViewMode viewMode = iEntryProcessor->ScenarioData().iViewMode;
-            iEntryProcessor->SwitchToTrackL();
+            // iEntryProcessor->SwitchToTrackL();
+            iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeTrack );
             iPolicyMgr->PushPolicyL();
             LaunchUIL();
 
             //go back to original view depending on where we came from
             if (viewMode == EESMREditMR)
                 {
-                iEntryProcessor->SwitchToEditL();
+                //iEntryProcessor->SwitchToEditL();
+                iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeEdit );
                 }
             else
                 {
-                iEntryProcessor->SwitchToViewL();
+                // iEntryProcessor->SwitchToViewL();
+                iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeView );
                 }
 
             LaunchUIL();
@@ -450,11 +803,13 @@
             break;
         case EESMRCmdForwardAsMeeting:   // Forward MR as meeting
             {
-            iEntryProcessor->SwitchToForwardL();
+            // iEntryProcessor->SwitchToForwardL();
+            iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeForward );
             iPolicyMgr->PushPolicyL();
             LaunchUIL();
             iPolicyMgr->PopPolicy();
-            iEntryProcessor->SwitchToViewL();
+            // iEntryProcessor->SwitchToViewL();
+            iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeView );
             }
             break;
 
@@ -512,27 +867,16 @@
         case EESMRCmdMailMoveMessageToDrafts:
         case EESMRCmdOpenAttachment:
         case EESMRCmdOpenAttachmentView:
-// <cmail
         case EESMRCmdDownloadAttachment:
         case EESMRCmdDownloadAllAttachments:
         case EESMRCmdSaveAttachment:
         case EESMRCmdSaveAllAttachments:
-// </cmail>
         case EESMRCmdDownloadManager:
             {
             needToProcessOutputParams = EFalse;
             iCallback.ProcessCommandL( aCommandId );
             }
             break;
-            
-        case EESMRCmdEditorInitializationComplete:
-            {
-            if ( iCallback.IsCommandAvailable( EESMRCmdEditorInitializationComplete ) )
-                {
-                iCallback.ProcessCommandL( EESMRCmdEditorInitializationComplete );
-                }
-            break;
-            }
 
         default:
             User::Leave( KErrNotSupported );
@@ -545,8 +889,120 @@
                 command );
         }
 
+    return KErrNone;
+    }
 
-    return KErrNone;
+// -----------------------------------------------------------------------------
+// CESMRViewerController::ChangeEntryTypeL
+// -----------------------------------------------------------------------------
+//
+void CESMRViewerController::ChangeEntryTypeL( TInt aCommandId )
+    {
+    TESMRCalendarEventType type = EESMREventTypeNone;
+
+    switch ( aCommandId )
+        {
+        case EMRCommandSwitchToMR:
+            {
+            type = EESMREventTypeMeetingRequest;
+            break;
+            }
+
+        case EMRCommandSwitchToMeeting:
+            {
+            type = EESMREventTypeAppt;
+            break;
+            }
+
+        case EMRCommandSwitchToMemo:
+            {
+            type = EESMREventTypeEEvent;
+            break;
+            }
+
+        case EMRCommandSwitchToAnniversary:
+            {
+            type = EESMREventTypeEAnniv;
+            break;
+            }
+
+        case EMRCommandSwitchToTodo:
+            {
+            type = EESMREventTypeETodo;
+            break;
+            }
+
+        default:
+            {
+            break;
+            }
+        }    
+   
+    // Original entry is needed for creating new comparative entry
+    CCalEntry* originalEntry =
+            ESMRHelper::CopyEntryL(
+                    iEntryProcessor->ESMREntryL().OriginalEntry(),
+                    iEntryProcessor->ESMREntryL().OriginalEntry().MethodL(),
+                    ESMRHelper::ECopyFull );
+    
+    CleanupStack::PushL( originalEntry );
+    
+    // Create a new entry by cloning the existing entry. 
+    // This also does the type conversion and judges what
+    // entry information will be copied from the old entry
+    // to the new entry
+    CCalEntry* newEntry =
+        iEntryProcessor->ESMREntryL().CloneEntryLC(
+                MESMRCalEntry::TESMRCalEntryType( type ) );
+    
+    iESMRUtils->CreateExtensionsL( type );
+    
+    iEntryProcessor =
+            static_cast<CMREntryProcessor*>(
+                    iESMRUtils->ExtensionL(
+                            TUid::Uid( KESMRMREntryProcessorUid ) ) );
+
+    iPolicyMgr =
+        static_cast<CESMRPolicyManager*>(
+                iESMRUtils->ExtensionL(
+                        TUid::Uid( KESMRPolicyMgrUid ) ) );
+
+    iTaskExt =
+        static_cast<MESMRTaskExtension*>(
+                iESMRUtils->ExtensionL(
+                        TUid::Uid( KESMRTaskExtensionUid ) ) );
+    
+    // Process entry
+    iEntryProcessor->ResetL();
+    iEntryProcessor->ProcessL( &iInParams, *newEntry, EFalse, ETrue );
+
+    if ( iInParams.iEditorMode == MAgnEntryUi::EViewEntry )
+        {
+        // If user has been viewing original entry, switch processor to editor.
+        iEntryProcessor->SwitchProcessorToModeL( EMRProcessorModeEdit );
+        }
+
+    // Resolve new policy
+    iPolicyMgr->ResolvePolicyL( iEntryProcessor->ScenarioData(),
+                                iEntryProcessor->ESMREntryL(),
+                                NULL );
+
+    if ( iCalEntry )
+        {
+        delete iCalEntry;
+        }
+
+    iCalEntry = newEntry;
+    CleanupStack::Pop( newEntry );
+    newEntry = NULL;
+
+    // Comparative entry needs to be updated also, otherwise
+    // type changed entry's saving won't function correctly
+    UpdateComparativeEntryInTypeChangeL( *originalEntry );
+    
+    iEntryProcessor->ESMREntryL().SetTypeChanged( ETrue );
+    
+    CleanupStack::PopAndDestroy( originalEntry );
     }
 
 // -----------------------------------------------------------------------------
@@ -556,37 +1012,54 @@
 void CESMRViewerController::LaunchUIL()
     {
     FUNC_LOG;
-    MESMRMeetingRequestEntry& entry = iEntryProcessor->ESMREntryL();
-
     iPolicyMgr->ResolvePolicyL(
         iEntryProcessor->ScenarioData(),
-        entry,
+        iEntryProcessor->ESMREntryL(),
         NULL ); // Passing NULL --> Default policy resolver is used
 
     MESMRUiBase* uibase =
             iGuiFactory->CreateUIL(
-            &iPolicyMgr->CurrentPolicy(),
-            entry,
+            *this,
             *this );
 
     TInt retValue = uibase->ExecuteViewLD();
-    TBool openedFromMail( entry.IsOpenedFromMail() );
-    
+
     if ( retValue == EAknCmdExit  )
-       {
-       if ( openedFromMail )
-           {
-           // Need to communicate with FS Email how this is
-           // indicated to FS EMail UI application
-           }
-       else
-           {
-           CEikAppUi* appUi =
-               CEikonEnv::Static()->EikAppUi(); // codescanner::eikonenvstatic
-           // Exit application
-           static_cast<MEikCommandObserver*>(appUi)->ProcessCommandL(EAknCmdExit);
-           }
-       }    
+        {
+        MESMRCalEntry* calEntry = &iEntryProcessor->ESMREntryL();
+        
+        if( CCalenInterimUtils2::IsMeetingRequestL( calEntry->Entry() ) )
+            {
+            // Cast safe, after we have identified the entry as mr 
+            MESMRMeetingRequestEntry& mrEntry( 
+                    *static_cast< MESMRMeetingRequestEntry* >( calEntry ) );
+            
+            if( mrEntry.IsOpenedFromMail() )
+                {
+                CEikAppUi* appUi =
+                    CEikonEnv::Static()->EikAppUi(); // codescanner::eikonenvstatic
+                // Exit application
+                static_cast<MEikCommandObserver*>( appUi )->ProcessCommandL( 
+                        EAknCmdExit );
+                }
+            else
+                {
+                // Let's inform via output parameters that 
+                // exit is desired.
+                TMROutputParams* outputParams = 
+                   reinterpret_cast< TMROutputParams* >( iOutParams.iSpare );
+                outputParams->iCommand = EMRDialogOptionsMenuExit;
+                }
+            }
+        else
+            {
+            // Let's inform via output parameters that 
+            // exit is desired.
+            TMROutputParams* outputParams = 
+               reinterpret_cast< TMROutputParams* >( iOutParams.iSpare );
+            outputParams->iCommand = EMRDialogOptionsMenuExit;
+            }
+        }
     }
 
 // -----------------------------------------------------------------------------
@@ -609,5 +1082,185 @@
         }
     }
 
+// -----------------------------------------------------------------------------
+// CESMRViewerController::UpdateComparativeEntryInTypeChangeL
+// -----------------------------------------------------------------------------
+//
+void CESMRViewerController::UpdateComparativeEntryInTypeChangeL(
+        const CCalEntry& aOriginalEntry  )
+    {
+    /* 
+     * This is needed because if user creates an entry and only type changes
+     * the entry, but does  not input any data, we cannot save the entry.
+     */
+
+    CCalEntry& esmrEntry = iEntryProcessor->ESMREntryL().Entry();
+
+    TESMRCalendarEventType type = MapType( aOriginalEntry );
+    
+    // Let's create new comparative entry based on the current 
+    // type changed entry
+    CCalEntry* newComparativeEntry = CreateEntryL(         
+            iCalEntry->EntryTypeL(),
+            iCalEntry->UidL(),
+            CCalEntry::EMethodNone,
+            CalCommon::EThisOnly );
+
+    CleanupStack::PushL( newComparativeEntry );
+    
+    newComparativeEntry->CopyFromL( *iCalEntry );
+
+    // New comparative entry needs still data from original entry.
+    // Use case:
+    // - User opens entry to editor
+    // - User changes values
+    // - User changes entry type
+    // -> We need to determine if entry values have changed from the original
+    newComparativeEntry->SetSummaryL(
+            aOriginalEntry.SummaryL() );
+    newComparativeEntry->SetLocationL(
+            aOriginalEntry.LocationL() );
+    newComparativeEntry->SetDescriptionL(
+            aOriginalEntry.DescriptionL() );
+    newComparativeEntry->SetReplicationStatusL(
+            aOriginalEntry.ReplicationStatusL() );
+    
+    // If original and new entries are both appointments,
+    // then also start and end times can be copied from original entry
+    // to comparative entry
+    if( aOriginalEntry.EntryTypeL() == CCalEntry::EAppt &&
+            esmrEntry.EntryTypeL() == CCalEntry::EAppt )
+        {
+        newComparativeEntry->SetStartAndEndTimeL(
+                aOriginalEntry.StartTimeL(),
+                aOriginalEntry.EndTimeL() );
+        }
+
+    // Time stamp must be the same as in esmrEntry
+    newComparativeEntry->SetDTStampL( esmrEntry.DTStampL() );
+
+    // If neither the original entry, nor the new entry
+    // are To-do's, we can also copy the priority from
+    // the original entry, since priority value is then compatible
+    // between the old and the new entry types
+    if( aOriginalEntry.EntryTypeL() != CCalEntry::ETodo && 
+            iCalEntry->EntryTypeL() != CCalEntry::ETodo )
+        {
+        newComparativeEntry->SetPriorityL( 
+                aOriginalEntry.PriorityL() );
+        }
+    // One of the entries, original or new, are to-do's,
+    // so the priority value is not compatible between them.
+    // we need to convert that
+    else
+        {
+        if( aOriginalEntry.EntryTypeL() == CCalEntry::ETodo )
+            {
+            newComparativeEntry->SetPriorityL( 
+                    ConvertTodoPriorityToNormalL( aOriginalEntry ) );
+            }
+        else if( iCalEntry->EntryTypeL() == CCalEntry::ETodo )
+            {
+            newComparativeEntry->SetPriorityL( 
+                    ConvertNormalPriorityToTodoL( aOriginalEntry ) );
+            }
+        }
+    
+    // If new entry is meeting request, let's also
+    // copy the same phone owner to the comparative entry
+    if( iCalEntry->MethodL() == CCalEntry::EMethodRequest )
+        {
+        CCalUser* temp = esmrEntry.OrganizerL(); // Ownership not transfered
+        CCalUser* organizer = ESMRHelper::CopyUserL( *temp );
+
+        newComparativeEntry->SetOrganizerL( organizer );
+        newComparativeEntry->SetPhoneOwnerL(
+                newComparativeEntry->OrganizerL() );
+        }
+    
+    // Attachment information is also needed from original entry
+    if( aOriginalEntry.AttachmentCountL() == 0 )
+        {
+        // Original entry did not have attachments, so let's 
+        // remove possible attachments from comparative entry also
+        TInt count = newComparativeEntry->AttachmentCountL();
+        
+        // Attachments need to be deleted in reversed order
+        for( TInt i = ( count - 1 ); i == 0; --i )
+            {
+            newComparativeEntry->DeleteAttachmentL( 
+                    *( newComparativeEntry->AttachmentL( i ) ) );
+            }
+        
+        // If original entry does have attachments, we do nothing ->
+        // If original entry has attachments, it has been already saved 
+        // and now type changed, which means that it needs to be saved 
+        // anyway.
+        }
+
+    iEntryProcessor->ESMREntryL().UpdateComparativeEntry(
+            newComparativeEntry ); // Takes ownership
+
+    CleanupStack::Pop( newComparativeEntry );
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRViewerController::CancelAndDeleteMRInEntryTypeChangeL
+// -----------------------------------------------------------------------------
+//
+void CESMRViewerController::CancelAndDeleteMRInEntryTypeChangeL( 
+        CCalEntry& aEntry, MESMRCalDbMgr& aDbMgr )
+	{
+	FUNC_LOG;
+	// We need new task factor, processor and task extension
+	// for this temporary MR action.
+    CESMRTaskFactory* taskFactory = CESMRTaskFactory::NewL(
+            EESMREventTypeMeetingRequest,
+            aDbMgr );
+    CleanupStack::PushL( taskFactory );
+    
+    CMREntryProcessor* entryProcessor = CMREntryProcessor::NewL(
+            EESMREventTypeMeetingRequest,
+            aDbMgr );
+    CleanupStack::PushL( entryProcessor );
+    
+    MESMRTaskExtension* taskExtension =
+        CESMRTaskExtenstionImpl::NewL( *taskFactory );
+    CleanupDeletePushL( taskExtension );
+    
+    entryProcessor->ProcessL( &iInParams, aEntry, EFalse, ETrue );
+    MESMRCalEntry& entry = entryProcessor->ESMREntryL();
+
+    // Cast safe, because entry is always MR
+    MESMRMeetingRequestEntry& mrEntry( 
+            static_cast<MESMRMeetingRequestEntry&>( entry ) );
+    
+    if ( EESMRRoleOrganizer == mrEntry.RoleL() )
+        {
+        CCalEntry::TStatus status( mrEntry.Entry().StatusL() );
+        if ( CCalEntry::ENullStatus != status )
+            {
+            // We are changing entry type from MR to some other type
+            // And we have sent the MR invitation to attendees.
+            // We provide possibility for user to send
+            // cancellation message to attendees.
+            mrEntry.MarkMeetingCancelledL();
+
+            taskExtension->DeleteAndSendMRL(
+                    EESMRCmdDeleteMR,
+                    mrEntry );
+            }
+        else
+            {
+            taskExtension->DeleteEntryFromLocalDBL(
+                    EESMRCmdDeleteMR,
+                    mrEntry );
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( taskExtension );
+    CleanupStack::PopAndDestroy( entryProcessor );
+    CleanupStack::PopAndDestroy( taskFactory );
+	}
+
 //  End of File
-