--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarui/editors/src/calenunifiededitor.cpp Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,3417 @@
+/*
+* Copyright (c) 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 : Class description for unified editor
+*
+*/
+
+// user includes
+#include "calenunifiededitor.h"
+#include "CalenDefaultEditors.hrh"
+#include "calenglobaldata.h"
+#include "calenunifiededitorcontrol.h"
+#include "calendbfield.h"
+#include "calenlocationutil.h"
+#include "CalenEntryUpdater.h"
+#include "CalenEditorDataHandler.h"
+#include "calenentryutil.h"
+#include "calensend.h"
+#include "CalenDescription.h"
+#include "calenattachmentinfo.h"
+#include "calenattachmentmodel.h"
+#include "CleanupResetAndDestroy.h"
+#include "CalendarPrivateCRKeys.h"
+
+// system includes
+#include <coemain.h>
+#include <eikdialg.h>
+#include <bacntf.h>
+#include <eikspane.h>
+#include <akntitle.h>
+#include <aknnavi.h>
+#include <eikcapc.h>
+#include <StringLoader.h>
+#include <featmgr.h>
+#include <hlplch.h>
+#include <AknQueryDialog.h>
+#include <AknUtils.h>
+#include <AknIconUtils.h>
+#include <aknlayoutscalable_apps.cdl.h>
+#include <eikrted.h>
+#include <txtrich.h>
+#include <aknnotewrappers.h>
+#include <sysutil.h>
+#include <ErrorUI.h>
+#include <EPos_CPosLandmark.h>
+#include <lbsposition.h>
+#include <calentry.h>
+#include <CalenDefaultEditorsData.rsg>
+#include <Calendar.rsg>
+#include <calenagendautils.h> // Need to conform the access.
+#include <calrrule.h>
+#include <calendateutils.h>
+#include <CalenInterimUtils2.h>
+#include <centralrepository.h>
+#include <calencommands.hrh> // Calendar commands
+#include <calencontext.h>
+#include <caleninstanceid.h> // TCalenInstanceId
+#include <calenservices.h>
+#include <calcalendarinfo.h>
+
+// debug
+#include "calendarui_debug.h"
+
+const TInt KCalenMaxELAFTextEditorLength(160);
+const TInt KCalenMaxAPACTextEditorLength(70);
+
+// Custom id for command to close form without any checks.
+// We need just to close form without saving, when entry is deleted from options menu
+const TInt KCalenButtonIdCloseForm(-400);
+
+_LIT(KComma, ",");
+_LIT(KEmpty,"");
+_LIT(KAttachmentSeparator,"; ");
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCalenUnifiedEditor* CCalenUnifiedEditor::NewL( CCalEntry& aEntry,
+ const TAgnEntryUiInParams& aParams,
+ MAgnEntryUiCallback& aCallback,
+ TAgnEntryUiOutParams& aOutParams,
+ CalCommon::TRecurrenceRange aRepeatType)
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalenUnifiedEditor* self =
+ new (ELeave) CCalenUnifiedEditor( aEntry, aParams, aCallback, aOutParams, aRepeatType );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ TRACE_EXIT_POINT;
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCalenUnifiedEditor* CCalenUnifiedEditor::NewL( CCalEntry& aEntry,
+ const TAgnEntryUiInParams& aParams,
+ MAgnEntryUiCallback& aCallback,
+ TAgnEntryUiOutParams& aOutParams )
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalenUnifiedEditor* self =
+ new (ELeave) CCalenUnifiedEditor( aEntry, aParams, aCallback, aOutParams );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ TRACE_EXIT_POINT;
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::~CCalenUnifiedEditor
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CCalenUnifiedEditor::~CCalenUnifiedEditor()
+ {
+ TRACE_ENTRY_POINT;
+
+ if( iGlobalData )
+ {
+ iGlobalData->Release();
+ }
+
+ // Remove default status pane
+ if( iNaviContainer )
+ {
+ iNaviContainer->Pop();
+ iNaviContainer = NULL;
+ }
+
+ if( iIdle )
+ {
+ delete iIdle;
+ }
+ iCoeEnv->RemoveFepObserver( *this );
+
+ if( iServices )
+ {
+ iServices->CancelNotifications( this );
+ }
+ delete iLocaleChangeNotifier;
+ delete iOriginalCalEntry;
+ delete iEditorDataHandler;
+ delete iEntryUpdater;
+ delete iUnifiedEditorControl;
+
+ iCollectionIds.Reset();
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::CCalenUnifiedEditor
+// Default constructor
+// -----------------------------------------------------------------------------
+//
+CCalenUnifiedEditor::CCalenUnifiedEditor( CCalEntry& aEntry,
+ const TAgnEntryUiInParams& aParams,
+ MAgnEntryUiCallback& aCallback,
+ TAgnEntryUiOutParams& aOutParams,
+ CalCommon::TRecurrenceRange aRepeatType )
+ : iEditedCalEntry( aEntry ), iEntryUiInParams( aParams ),
+ iEntryUiCallback( aCallback ), iEntryUiOutParams( aOutParams ),
+ iRepeatType( aRepeatType ), iEntryType( aEntry.EntryTypeL() ),
+ iHasChosenRepeatType( ETrue ), iIgnoreFirstLocaleChange( ETrue ),
+ iCurrentDurationDay( 0 ), iTwoSeconds( 2 )
+
+
+ {
+ TRACE_ENTRY_POINT;
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::CCalenUnifiedEditor
+// Default constructor
+// -----------------------------------------------------------------------------
+//
+CCalenUnifiedEditor::CCalenUnifiedEditor( CCalEntry& aEntry,
+ const TAgnEntryUiInParams& aParams,
+ MAgnEntryUiCallback& aCallback,
+ TAgnEntryUiOutParams& aOutParams )
+ : iEditedCalEntry( aEntry ), iEntryUiInParams( aParams ),
+ iEntryUiCallback( aCallback ), iEntryUiOutParams( aOutParams ),
+ iRepeatType( CalCommon::EThisAndAll ),
+ iEntryType( aEntry.EntryTypeL() ),
+ iHasChosenRepeatType( EFalse ),
+ iIgnoreFirstLocaleChange( ETrue ),
+ iCurrentDurationDay( 0 ), iTwoSeconds( 2 )
+
+
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ConstructL
+// Second phase construction
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::ConstructL()
+ {
+ TRACE_ENTRY_POINT;
+
+ // Construct dialog
+ CAknDialog::ConstructL( R_CALEN_UNIFIED_EDITOR_MENUBAR );
+
+ // Take a timestamp of the editors opening time - 2 seconds
+ // We use this to compare against the last database change time
+ // to determine if the current entry has been deleted through
+ // another CCalSession
+ iTimeStamp.UniversalTime();
+
+ iGlobalData = CCalenGlobalData::InstanceL( iEntryUiInParams.iCalSession );
+
+ iOriginalCalEntry = CCalenUnifiedEditor::CreateCopyL( iEditedCalEntry );
+
+ // Setup title and status panes
+ CEikStatusPane* sp = iEikonEnv->AppUiFactory()->StatusPane();
+ CAknTitlePane* tp = static_cast<CAknTitlePane*>( sp->ControlL( TUid::Uid(EEikStatusPaneUidTitle) ) );
+ HBufC* titleText = StringLoader::LoadLC( R_QTN_CALE_UNIFIED_EDITOR_TITLE, iCoeEnv );
+ tp->SetTextL( *titleText );
+ CleanupStack::PopAndDestroy( titleText );
+
+ // Put default, empty Status Pane.
+ iNaviContainer = static_cast<CAknNavigationControlContainer *>( sp->ControlL(TUid::Uid(EEikStatusPaneUidNavi) ) );
+ iNaviContainer->PushDefaultL();
+
+ // Connect to services, and register for notifications of
+ // changes to the database.
+ TInt services( iEntryUiInParams.iSpare );
+ iServices = reinterpret_cast< MCalenServices* >( services );
+
+ RArray<TCalenNotification> notificationArray;
+ notificationArray.Append( ECalenNotifyEntryDeleted );
+ notificationArray.Append( ECalenNotifyInstanceDeleted );
+ notificationArray.Append( ECalenNotifyDeleteFailed );
+ notificationArray.Append( ECalenNotifyEntryInstanceViewCreated );
+ notificationArray.Append( ECalenNotifyExternalDatabaseChanged );
+ notificationArray.Append( ECalenNotifyMapClosed );
+ notificationArray.Append( ECalenNotifyAttachmentAdded );
+ notificationArray.Append( ECalenNotifyAttachmentRemoved );
+ notificationArray.Append( ECalenNotifyCalendarFileDeleted );
+
+
+ iServices->RegisterForNotificationsL( this, notificationArray );
+ notificationArray.Reset();
+
+ GetAllCollectionidsL(iCollectionIds);
+
+ iEditorDataHandler = CCalenEditorDataHandler::NewL( iEditedCalEntry,
+ iEntryUiInParams.iInstanceDate,
+ IsCreatingNewEntry(),
+ MaxTextEditorLength(),
+ *iServices , iCollectionIds);
+ iEntryUpdater = CCalenEntryUpdater::NewL( *iServices , iCollectionIds);
+
+
+
+ //iServices->EntryViewL(iServices->Context().InstanceId().iColId);
+
+ iUnifiedEditorControl = CCalenUnifiedEditorControl::NewL( *this,*iServices );
+
+ isReplaceLocation = EFalse;
+
+ iIdle = CIdle::NewL( CActive::EPriorityUserInput );
+ iIdle->Start( TCallBack( KeyCallBack, this) );
+ iCoeEnv->AddFepObserverL( *this );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ExecuteViewL
+// Dummy implementation. Use ExecuteLD() instead.
+// -----------------------------------------------------------------------------
+//
+TInt CCalenUnifiedEditor::ExecuteViewL( RPointerArray<CCalEntry>& /*aEntries*/,
+ const TAgnEntryUiInParams& /*aInParams*/,
+ TAgnEntryUiOutParams& /*aOutParams*/,
+ MAgnEntryUiCallback& /*aCallback*/ )
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::SetHelpContext
+// Sets the help context.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetHelpContext( const TCoeHelpContext& /*aContext*/ )
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleNotification
+// Handles calendar notifications
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::HandleNotification( TCalenNotification aNotification )
+ {
+ TRACE_ENTRY_POINT;
+
+ switch( aNotification )
+ {
+ case ECalenNotifyExternalDatabaseChanged:
+ {
+ iLastDbChangeNotification.UniversalTime();
+ }
+ break;
+ case ECalenNotifyEntryDeleted:
+ {
+ iEntryUiOutParams.iAction = MAgnEntryUi::EMeetingDeleted;
+ PIM_TRAPD_HANDLE( CloseFormWithoutActionsL() );
+ }
+ break;
+ case ECalenNotifyInstanceDeleted:
+ {
+ iEntryUiOutParams.iAction = MAgnEntryUi::EInstanceDeleted;
+ PIM_TRAPD_HANDLE( CloseFormWithoutActionsL() );
+ }
+ break;
+ case ECalenNotifyMapClosed:
+ {
+ // User has closed the map, store/update necessary details
+ PIM_TRAPD_HANDLE( UpdateLocationInfoToFormL() );
+ }
+ break;
+ case ECalenNotifyDeleteFailed:
+ {
+ iEntryUiOutParams.iAction = MAgnEntryUi::ENoAction;
+ }
+ break;
+ case ECalenNotifyAttachmentAdded:
+ case ECalenNotifyAttachmentRemoved:
+ {
+ // TODO: Uncomment this when enabling attachment support
+ PIM_TRAPD_HANDLE( UpdateAttachmentInfoToEditorL() );
+ }
+ break;
+
+ case ECalenNotifyEntryInstanceViewCreated:
+ break;
+ case ECalenNotifyCalendarFileDeleted:
+ {
+ TPtrC fileNamePtr = iServices->Context().GetCalendarFileNameL();
+ if(!fileNamePtr.CompareF(iUnifiedEditorControl->GetCalendarNameForEntryL()))
+ {
+ DisplayErrorMsgL( CCalenEditorDataHandler::EFormErrDbConflictEntryDeleted );
+ iEntryUiOutParams.iAction = EMeetingDeleted;
+ TryExitL( KCalenButtonIdCloseForm );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::InsertFieldL
+// Inserts dialog line (form field) defined by aResourceI
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::InsertFieldL( TInt aResourceId, TInt aControlId,
+ TInt aPrevControlId )
+ {
+ TRACE_ENTRY_POINT;
+
+ CCoeControl* prevControl = Control( aPrevControlId );
+ __ASSERT_DEBUG( prevControl, User::Invariant() );
+ TInt pos = FindLineIndex( *prevControl );
+ pos = pos + 1;
+ InsertLineL( pos, aResourceId );
+
+ // We need to activate line, otherwise drawing doesn't work correctly
+ Line( aControlId )->ActivateL();
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HasField
+// Check for field exists in unified editor
+// -----------------------------------------------------------------------------
+//
+TBool CCalenUnifiedEditor::HasField( TInt aField )
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ return ControlOrNull( aField ) != NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::UpdateFormL
+// Update form. You can force update of form with this,
+// if you modify some of the field values dynamically.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::UpdateFormL()
+ {
+ TRACE_ENTRY_POINT;
+
+ UpdatePageL(ETrue);
+
+ TRACE_EXIT_POINT;
+ }
+
+// --------------------------------------------------------------------------
+// CreateCopyL
+// Create a copy of the given entry.
+// --------------------------------------------------------------------------
+//
+CCalEntry* CCalenUnifiedEditor::CreateCopyL( CCalEntry& aOther )
+ {
+ TRACE_ENTRY_POINT;
+
+ HBufC8* guid = aOther.UidL().AllocLC();
+ CCalEntry* entry;
+ if( aOther.RecurrenceIdL().TimeUtcL() != Time::NullTTime() )
+ {
+ entry = CCalEntry::NewL( aOther.EntryTypeL(), guid,
+ aOther.MethodL(),
+ aOther.SequenceNumberL(),
+ aOther.RecurrenceIdL(),
+ aOther.RecurrenceRangeL() );
+ }
+ else
+ {
+ entry = CCalEntry::NewL( aOther.EntryTypeL(), guid,
+ aOther.MethodL(),
+ aOther.SequenceNumberL() );
+ }
+ CleanupStack::Pop( guid ); // ownership was passed
+ CleanupStack::PushL( entry );
+ aOther.DescriptionL(); // make sure entry is fully loaded
+ entry->CopyFromL( aOther );
+ entry->DescriptionL(); // make sure entry is fully copied
+ CleanupStack::Pop( entry );
+
+ TRACE_EXIT_POINT;
+ return entry;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::OkToExitL
+// Handles exiting of the unified editor
+// -----------------------------------------------------------------------------
+//
+TBool CCalenUnifiedEditor::OkToExitL( TInt aButtonId )
+ {
+ TRACE_ENTRY_POINT;
+ TBool isExitForm( ETrue );
+ TBool active = EFalse;
+
+ TCalCollectionId colId = iEditorDataHandler->CurrentDbCollectionId();
+ VerifyCollectionIdL(colId);
+
+ TInt newCtrlId=IdOfFocusControl();
+ switch ( aButtonId )
+ {
+ case EAknSoftkeyChange:
+ {
+ isExitForm=EFalse;
+
+ // to Handle MSK key 'Change'
+ if(newCtrlId == ECalenEditorEventType || newCtrlId == ECalenEditorRepeat
+ || newCtrlId == ECalenEditorDBName
+ || newCtrlId == ECalenEditorPriority)
+ {
+
+ CEikCaptionedControl* line=CurrentLine();
+ TInt type=line->iControlType;
+ TBool isPopUp=( type && EAknCtPopupField ) || ( type == EAknCtPopupFieldText );
+ if (isPopUp)
+ {
+ CAknPopupField* ctrl = static_cast<CAknPopupField*>( line->iControl );
+ ctrl->ActivateSelectionListL();
+ }
+ }
+ else if( newCtrlId == ECalenEditorReminder )
+ {
+ if( iUnifiedEditorControl->IsAlarmActiveInForm() )
+ {
+ SetAlarmFieldOnOffL( EFalse );
+ active = EFalse;
+ }
+ else
+ {
+ SetAlarmFieldOnOffL( ETrue );
+ active = ETrue;
+ }
+ iUnifiedEditorControl->CheckAlarmActive( active );
+ TryChangeFocusToL( ECalenEditorReminder );
+ }
+ else if( newCtrlId == ECalenEditorAllDayItem )
+ {
+ if( iUnifiedEditorControl->IsAllDayEvent() )
+ {
+ SetAllDayFieldL( EFalse );
+ active = EFalse;
+ }
+ else
+ {
+ SetAllDayFieldL( ETrue );
+ active = ETrue;
+ }
+ iUnifiedEditorControl->SetAllDayEvent( active );
+
+ }
+ break;
+ }
+ case EAknSoftkeyOptions:
+ {
+ DisplayMenuL();
+ isExitForm = EFalse;
+ break;
+ }
+ case KCalenButtonIdCloseForm:
+ {
+ // Do nothing, just close.
+ // This is called when entry is deleted
+ // via menu or clearing texts
+ isExitForm = ETrue;
+ break;
+ }
+ case ECalenCmdCloseDialog:
+ {
+ // Forced close of the dialog when calendar is reopened from the
+ // command line. We do not want to update calendars stored focus
+ // in case we override any command line parameters
+ // Intentional fall through to EEikBidCancel below
+ iEntryUiOutParams.iAction = ENoAction;
+ iEntryUiOutParams.iSpare = 0;
+ // Fall through...
+ }
+ case ECalenEditSeries:
+ case ECalenEditOccurrence:
+ case EAknCmdExit:
+ case EEikBidCancel:
+ {
+ // EEikBidCancel is called when Red End key is pressed or
+ // MMC card is taken out or application is killed via Swap Window
+ // EAknCmdExit is called, when user selects Options->Exit
+ // (see OnCmdExit)
+
+ // At this point, CAknShutter fires us EEikBidCancel key events
+ // offering it to our dialog control. Firing key events continues
+ // until our dialog is closed, which is detected by FW.
+
+ // Entry can't be stored if EntryView does not exist.
+ // Will exit and lose some data if entry was really edited.
+
+ if( iServices->EntryViewL(colId) )
+ {
+ PIM_TRAPD_HANDLE( TryToSaveNoteOnForcedExitL() );
+ }
+ break;
+ }
+ case EAknSoftkeyDone:
+ {
+ // Need an entry view before starting to
+ // handle the done button.
+ if( iServices->EntryViewL(colId) )
+ {
+ isExitForm = HandleDoneL();
+ }
+ else
+ {
+ // The entry view has not been constructed yet
+ //iCreatingEntryView = EFalse;
+ isExitForm = EFalse;
+ }
+ }
+ break;
+ case ECalenGetLocation:
+ {
+ // Issue command to framework to launch the map
+ isExitForm=EFalse;
+ ReadPlaceFromEditorL(); // to remove any picture characters in location string
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ GetEdwinText(location, ECalenEditorPlace);
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ CPosLandmark* landmark = CPosLandmark::NewL();
+ landmark->SetLandmarkNameL(location);
+ TReal latitude;
+ TReal longitude;
+ geoValue->GetLatLong(latitude, longitude);
+ TPosition position;
+ position.SetCoordinate(latitude, longitude);
+ landmark->SetPositionL(position);
+ delete geoValue;
+ MCalenContext& context = iServices->Context();
+ context.SetLandMark(landmark);
+ }
+ else if(location.Length())
+ {
+ CPosLandmark* landmark = CPosLandmark::NewL();
+ landmark->SetLandmarkNameL(location);
+ MCalenContext& context = iServices->Context();
+ context.SetLandMark(landmark);
+ }
+ iServices->IssueCommandL(ECalenGetLocation);
+ }
+ break;
+ default:
+ isExitForm = EFalse;
+ break;
+ }
+ TRACE_EXIT_POINT;
+ return isExitForm;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::OfferKeyEventL
+// Handles key events
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CCalenUnifiedEditor::OfferKeyEventL( const TKeyEvent& aKeyEvent,
+ TEventCode aType )
+ {
+ TRACE_ENTRY_POINT;
+ TBool isMapIconHandled = EFalse;
+ TKeyResponse keyResponse( EKeyWasNotConsumed );
+ TInt ctrlid=IdOfFocusControl();
+
+ /* If KeyCallBack has not been called after construction
+ * (= initialization of iIdle) call it now to
+ * handle key event queue.
+ */
+ if ( iIdle )
+ {
+ KeyCallBack( this );
+ }
+
+ if ( aType == EEventKey )
+ {
+ switch ( aKeyEvent.iCode )
+ {
+ case EKeyOK:
+ // TODO: Uncomment this when enabling attachment support
+
+ if(ctrlid == ECalenEditorAttachment)
+ {
+ if(Edited().AttachmentCount() || iServices->GetAttachmentData()->NumberOfItems())
+ {
+ iServices->IssueCommandL( ECalenViewAttachmentList );
+ }
+ }
+ break;
+ case EKeyEscape:
+ // Calendar relaunched from cmd line - close viewer
+ // NOTE: This was changed from EAknCmdExit to ECalenCmdCloseDialog since launching
+ // the calanedar from cmd line or opening missed alarm view while calendar editor is
+ // opened is closing the application.
+ TryExitL( ECalenCmdCloseDialog );
+ keyResponse = EKeyWasConsumed;
+ break;
+ case EKeyEnter: // For Enter key
+ {
+ keyResponse = CAknForm::OfferKeyEventL(aKeyEvent,aType); // Let framework handle the key event
+ // when enter key is pressed on subject line or on location line, call AddPictureL to recalculate the map icon position properly
+ // as location field could habe moved up or down
+ if(ctrlid == ECalenEditorPlace || ctrlid == ECalenEditorSubject)
+ {
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ isMapIconHandled = ETrue;
+ AddPictureL();
+ delete geoValue;
+ }
+ }
+ }
+ break;
+ case EKeyDelete:
+ {
+ if(ctrlid == ECalenEditorPlace)
+ {
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ CEikRichTextEditor* locationControl = static_cast<CEikRichTextEditor*>(Control(ECalenEditorPlace));
+ CRichText* text = locationControl->RichText();
+ TPtrC ptr = text->Read(0,text->DocumentLength());
+ TInt pos = ptr.Locate(TChar(CEditableText::EPictureCharacter));
+ if(locationControl->CursorPos() == pos)
+ {
+ isMapIconHandled = ETrue;
+ keyResponse = EKeyWasConsumed;
+ delete geoValue;
+ break;
+ }
+ delete geoValue;
+ }
+ }
+ keyResponse = CAknForm::OfferKeyEventL(aKeyEvent,aType); // Let framework handle the key event
+ }
+ break;
+ case EKeyBackspace: // For back space character
+ {
+ if(ctrlid == ECalenEditorPlace)
+ {
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ CEikRichTextEditor* locationControl = static_cast<CEikRichTextEditor*>(Control(ECalenEditorPlace));
+ CRichText* text = locationControl->RichText();
+ TPtrC ptr = text->Read(0,text->DocumentLength());
+ TInt pos = ptr.Locate(TChar(CEditableText::EPictureCharacter));
+ TInt curpos = locationControl->CursorPos();
+
+ // When only one visible character is there and picture byte is there at second position, then
+ // empty the location field and redraw the map icon
+ if(text->DocumentLength() <= 2)
+ {
+ TBuf<1> newLocation;
+ SetEdwinTextL(ECalenEditorPlace, &newLocation);
+ keyResponse = EKeyWasConsumed;
+ delete geoValue;
+ isMapIconHandled = ETrue;
+ AddPictureL();
+ break;
+ }
+ // when cursor position is at the end, then since, picture byte is at the end
+ // delete last but one character (for user, it looks as if last visible character is being deleted)
+ // and redraw the icon
+ else if( curpos == pos + 1)
+ {
+ text->DeleteL(text->DocumentLength() - 2,1);
+
+ AddPictureL();
+ locationControl->SetCursorPosL(curpos - 1, EFalse);
+ isMapIconHandled = ETrue;
+ keyResponse = EKeyWasConsumed;
+ delete geoValue;
+ break;
+ }
+ delete geoValue;
+ }
+ }
+ // This is to handle backspaces in subject field when there nore that one lines,
+ // location field will move up, hence, need to redraw the map icon
+ else if(ctrlid == ECalenEditorSubject)
+ {
+ keyResponse = CAknForm::OfferKeyEventL(aKeyEvent,aType);
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ AddPictureL();
+ isMapIconHandled = ETrue;
+ delete geoValue;
+ }
+ break;
+ }
+ }
+ case EKeyLeftArrow:
+ case EKeyRightArrow:
+ {
+ if( ECalenEditorEventType == IdOfFocusControl() )
+ {
+ keyResponse = EKeyWasConsumed;
+ }
+ else
+ {
+ keyResponse = CAknForm::OfferKeyEventL( aKeyEvent, aType );
+ }
+ }
+ break;
+
+ default:
+ {
+ keyResponse = CAknForm::OfferKeyEventL(aKeyEvent,aType);
+ if(!isMapIconHandled)
+ {
+ if((ctrlid == ECalenEditorPlace) || (ctrlid == ECalenEditorSubject))
+ {
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ isMapIconHandled = ETrue;
+ AddPictureL();
+ delete geoValue;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ // For handling geokeys on corolla hardware
+ // For Add location hard key
+ if( aKeyEvent.iScanCode == EStdKeyApplication1C && aType == EEventKeyUp )
+ {
+ if(CCalenLocationUtil::IsMapProviderAvailableL())
+ {
+ TryChangeFocusToL(ECalenEditorPlace);
+ ReadPlaceFromEditorL(); // to remove any picture characters in location string
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ GetEdwinText(location, ECalenEditorPlace);
+ CPosLandmark* landmark = NULL;
+ if(location.Length())
+ {
+ landmark = CPosLandmark::NewL();
+ landmark->SetLandmarkNameL(location);
+ }
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ if(!landmark)
+ {
+ landmark = CPosLandmark::NewL();
+ }
+ TReal latitude;
+ TReal longitude;
+ geoValue->GetLatLong(latitude, longitude);
+ TPosition position;
+ position.SetCoordinate(latitude, longitude);
+ landmark->SetPositionL(position);
+ delete geoValue;
+ }
+ MCalenContext& context = iServices->Context();
+ context.SetLandMark(landmark);
+ iServices->IssueCommandL(ECalenGetLocation);
+ keyResponse = EKeyWasConsumed;
+ }
+ }
+ // For Show location hard key
+ else if( aKeyEvent.iScanCode == EStdKeyApplication1B && aType == EEventKeyUp )
+ {
+ ReadPlaceFromEditorL();
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ GetEdwinText(location, ECalenEditorPlace);
+ if(CCalenLocationUtil::IsMapProviderAvailableL())
+ {
+ TryChangeFocusToL(ECalenEditorPlace);
+ MCalenContext& context = iServices->Context();
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ CPosLandmark* landmark = CPosLandmark::NewL();
+ landmark->SetLandmarkNameL(location);
+ TReal latitude;
+ TReal longitude;
+ geoValue->GetLatLong(latitude, longitude);
+ TPosition position;
+ position.SetCoordinate(latitude, longitude);
+ landmark->SetPositionL(position);
+ context.SetLandMark(landmark);
+ iServices->IssueCommandL(ECalenShowLocation);
+ delete geoValue;
+ }
+ else if(location.Length())
+ {
+ CPosLandmark* landmark = CPosLandmark::NewL();
+ landmark->SetLandmarkNameL(location);
+ context.SetLandMark(landmark);
+ isReplaceLocation = ETrue;
+ iServices->IssueCommandL(ECalenGetLocation);
+ }
+ keyResponse = EKeyWasConsumed;
+ }
+ }
+
+ // Swallow all other keyevents to prevent the active container processing them.
+ keyResponse = EKeyWasConsumed;
+
+ TRACE_EXIT_POINT;
+ return keyResponse;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleCompletionOfTransactionL
+// Is called when fep transaction has been completed. If this
+// happens before key event queue has been simulated, events in
+// key buffer must be ignored. If key events are simulated after this
+// result is duplicate characters or wrong order of characters.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+void CCalenUnifiedEditor::HandleCompletionOfTransactionL()
+ {
+ TRACE_ENTRY_POINT;
+ if( iIdle )
+ {
+ delete iIdle;
+ iIdle = NULL;
+ iServices->ResetKeyEventQueue();/*ignore all events*/
+ }
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::KeyCallBack
+// Handles key events in key event queue
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+TInt CCalenUnifiedEditor::KeyCallBack( TAny *aSelf )
+ {
+ TRACE_ENTRY_POINT;
+ CCalenUnifiedEditor *self = static_cast<CCalenUnifiedEditor*>( aSelf );
+ delete self->iIdle;
+ self->iIdle = NULL;
+
+ TKeyEvent event;
+ TEventCode type;
+
+ while( self->iServices->GetQueuedKeyEvent( event, type ) )
+ {
+ TRAPD(err,
+ self->iCoeEnv->SimulateKeyEventL( event, type );
+ );
+ if ( err != KErrNone )
+ {
+ CEikEdwin* edwin = static_cast<CEikEdwin*>( self->Control( self->IdOfFocusControl() ) );
+ edwin->CancelFepTransaction(); // indispensable to avoid crash
+ self->iCoeEnv->HandleError( err );
+ }
+ }
+ TRACE_EXIT_POINT;
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::LocaleCallback
+// This function is called when a locale(or today) is changed.
+// -----------------------------------------------------------------------------
+//
+TInt CCalenUnifiedEditor::LocaleCallback( TAny* aThisPtr ) // A CCalenFormBase pointer
+ {
+ TRACE_ENTRY_POINT;
+ CCalenUnifiedEditor* unifiededitor = static_cast<CCalenUnifiedEditor*>( aThisPtr );
+
+ if( unifiededitor->iIgnoreFirstLocaleChange )
+ {
+ // Ignore the first locale change so we don't rebuild for no reason.
+ unifiededitor->iIgnoreFirstLocaleChange = EFalse;
+ TRACE_ENTRY_POINT;
+ return EFalse;
+ }
+
+ TRACE_EXIT_POINT;
+ return unifiededitor->HandleLocaleChange( unifiededitor->iLocaleChangeNotifier->Change() );
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleLocaleChange
+// CCalenUnifiedEditor::LocaleCallback() methods calls this method
+// -----------------------------------------------------------------------------
+//
+TInt CCalenUnifiedEditor::HandleLocaleChange( TInt aChange )
+ {
+ TRACE_ENTRY_POINT;
+
+ PIM_TRAPD_HANDLE( DoHandleLocaleChangeL( aChange ) );
+
+ TRACE_EXIT_POINT;
+ return FALSE;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::DoHandleLocaleChange
+// HandleLocaleChange calls this function
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::DoHandleLocaleChangeL( TInt aChange )
+ {
+ TRACE_ENTRY_POINT;
+
+ if( aChange & EChangesSystemTime )
+ {
+ // System time zone change. Recreate the handler, so that
+ // the new local time is shown in the viewer.
+ if( !IsCreatingNewEntry() )
+ {
+ if( !iEditorDataHandler->IsEditedL() )
+ {
+ delete iEditorDataHandler;
+ iEditorDataHandler = NULL;
+ iEditorDataHandler = CCalenEditorDataHandler::NewL( iEditedCalEntry,
+ iEntryUiInParams.iInstanceDate,
+ IsCreatingNewEntry(),
+ MaxTextEditorLength(),
+ *iServices ,iCollectionIds);
+ }
+ else
+ {
+ iEditorDataHandler->ResetOriginalDataL();
+ }
+ }
+ iUnifiedEditorControl->SetDataToEditorL();
+ }
+
+ if ( aChange & EChangesLocale )
+ {
+ iUnifiedEditorControl->ReadDataFromEditorL( ETrue );
+ iUnifiedEditorControl->UpdateLinesOnLocaleChangeL();
+ }
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::PreLayoutDynInitL
+// Initializes the dialog's controls before the dialog is sized
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::PreLayoutDynInitL()
+ {
+ TRACE_ENTRY_POINT;
+
+ iUnifiedEditorControl->MakeUnifiedEditorL();
+ // Hides Entry type and Calendar Field for exceptional entry/single
+ // instance of recurrent entry.
+ HideFieldsForEditSingleInstance();
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::PostLayoutDynInitL
+// Initializes the dialog's controls after the dialog has been sized
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::PostLayoutDynInitL()
+ {
+ TRACE_ENTRY_POINT;
+
+ SetEditableL(ETrue);
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ AddPictureL();
+ delete geoValue;
+ }
+ TCallBack callback( LocaleCallback, this );
+ iLocaleChangeNotifier =
+ CEnvironmentChangeNotifier::NewL( EActivePriorityLogonA, callback );
+
+ iLocaleChangeNotifier->Start();
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleControlStateChangeL
+// IHandles a state change in the control with id aControlId.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::HandleControlStateChangeL( TInt aControlId )
+ {
+ TRACE_ENTRY_POINT;
+
+ iUnifiedEditorControl->HandleControlStateChangeL( aControlId );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::PrepareForFocusTransitionL
+// Tries to change focus to the specified line.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::PrepareForFocusTransitionL()
+ {
+ TRACE_ENTRY_POINT;
+
+ CEikDialog::PrepareForFocusTransitionL();
+
+ iUnifiedEditorControl->PrepareForFocusTransitionL( IdOfFocusControl() );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ActivateL
+// Try to change item focus here
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::ActivateL()
+ {
+ TRACE_ENTRY_POINT;
+
+ CAknForm::ActivateL();
+ TryChangeFocusToL( ECalenEditorSubject );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ProcessCommandL
+// Handles editor menu commands
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::ProcessCommandL( TInt aCommandId )
+ {
+ TRACE_ENTRY_POINT;
+
+ HideMenu();
+ switch( aCommandId )
+ {
+ case ECalenCmdCancel:
+ OnCmdCancelL();
+ break;
+ case ECalenDeleteCurrentEntry:
+ OnCmdDeleteNoteL();
+ break;
+ case EAknCmdExit:
+ OnCmdExitL();
+ break;
+ case EAknCmdHelp:
+ OnCmdHelpL();
+ break;
+ case ECalenSend:
+ OnCmdSendL( aCommandId );
+ break;
+ case ECalenGetLocation:
+ {
+ ReadPlaceFromEditorL(); // to remove any picture characters in location string
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ GetEdwinText(location, ECalenEditorPlace);
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ CPosLandmark* landmark = CPosLandmark::NewL();
+ landmark->SetLandmarkNameL(location);
+ TReal latitude;
+ TReal longitude;
+ geoValue->GetLatLong(latitude, longitude);
+ TPosition position;
+ position.SetCoordinate(latitude, longitude);
+ landmark->SetPositionL(position);
+ delete geoValue;
+ MCalenContext& context = iServices->Context();
+ context.SetLandMark(landmark);
+ }
+ else if(location.Length())
+ {
+ CPosLandmark* landmark = CPosLandmark::NewL();
+ landmark->SetLandmarkNameL(location);
+ MCalenContext& context = iServices->Context();
+ context.SetLandMark( landmark );
+ }
+ iServices->IssueCommandL( ECalenGetLocation );
+ }
+ break;
+ case ECalenCmdAddAttachment:
+ {
+ // TODO: Uncomment this when enabling attachment support
+ iServices->IssueCommandL( ECalenAddAttachment );
+ }
+ break;
+ case ECalenCmdViewAttachmentList:
+ {
+ iServices->IssueCommandL(ECalenViewAttachmentList);
+ }
+ break;
+ case ECalenCmdRemoveAttachment:
+ {
+ // TODO: Uncomment this when enabling attachment support
+
+ TInt attachmentCount = iServices->GetAttachmentData()->NumberOfItems();
+
+ if(Edited().AttachmentCount() || attachmentCount)
+ {
+ iServices->IssueCommandL( ECalenRemoveAttachment );
+ }
+ }
+ break;
+ default:
+ {
+ if( iUnifiedEditorControl->Description() )
+ {
+ iUnifiedEditorControl->Description()->ProcessCommandL( aCommandId );
+ }
+ }
+ // NOP, pass command through (for FEP etc.)
+ break;
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+//Single click integration
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleDialogPageEventL
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::HandleDialogPageEventL( TInt aEventID )
+ {
+ CAknForm::HandleDialogPageEventL( aEventID );
+ if ( aEventID == MEikDialogPageObserver::EDialogPageTapped )
+ {
+ TInt focusControl( IdOfFocusControl() );
+ if ( focusControl == ECalenEditorAttachment
+ || focusControl == ECalenEditorDescription )
+ {
+
+
+ switch ( focusControl )
+ {
+ case ECalenEditorAttachment:
+ {
+
+ if(Edited().AttachmentCount() || iServices->GetAttachmentData()->NumberOfItems())
+ {
+ ProcessCommandL( ECalenCmdViewAttachmentList );
+ }
+ else
+ {
+ ProcessCommandL( ECalenCmdAddAttachment );
+ }
+ break;
+ }
+ case ECalenEditorDescription:
+ {
+ CEikEdwin* edwin = static_cast<CEikEdwin*>( Control( focusControl ) );
+ if ( edwin && edwin->Text()->DocumentLength() == 0 )
+ {
+ ProcessCommandL( ECalenCmdAddDescription );
+ }
+ else
+ {
+ ProcessCommandL( ECalenCmdShowDescription );
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ }
+ else if ( focusControl == ECalenEditorAllDayItem )
+ {
+ // Tap on AllDay field, Switch the status of AllDay field
+ iUnifiedEditorControl->SetAllDayEvent(
+ !( iUnifiedEditorControl->IsAllDayEvent() ) );
+ }
+ else if ( focusControl == ECalenEditorReminder )
+ {
+ TBool active;
+ if( iUnifiedEditorControl->IsAlarmActiveInForm() )
+ {
+ SetAlarmFieldOnOffL( EFalse );
+ active = EFalse;
+ }
+ else
+ {
+ SetAlarmFieldOnOffL( ETrue );
+ active = ETrue;
+ }
+ iUnifiedEditorControl->CheckAlarmActive( active );
+ TryChangeFocusToL( ECalenEditorReminder );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleResourceChange
+// Handdles the resource change
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::HandleResourceChange( TInt aType )
+ {
+ TRACE_ENTRY_POINT;
+
+ if( aType == KEikDynamicLayoutVariantSwitch )
+ {
+ CAknForm::HandleResourceChange( aType );
+ }
+
+ CCoeControl::HandleResourceChange( aType );
+
+ CCalGeoValue* geoValue = NULL;
+ TRAP_IGNORE(geoValue = iEditorDataHandler->Entry().GeoValueL());
+ if(geoValue)
+ {
+ TRAP_IGNORE(AddPictureL());
+ delete geoValue;
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::DynInitMenuPaneL
+// Dynamic initialistaion of menu pane
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::DynInitMenuPaneL(
+ TInt aResourceId,
+ CEikMenuPane* aMenuPane )
+ {
+ TInt ctrlid=IdOfFocusControl();
+
+ switch ( aResourceId )
+ {
+ case R_CALEN_UNIFIED_EDITOR_MENUPANE:
+ {
+ // Here we have to call other classes DynInitMenuPaneL
+ // in that order that we want items to appear!
+ if( ctrlid == ECalenEditorDescription )
+ {
+ iUnifiedEditorControl->Description()->DynInitMenuPaneL(
+ aResourceId,
+ aMenuPane );
+ }
+
+ // TODO: Uncomment this when enabling attachment support
+
+ if( ctrlid == ECalenEditorAttachment )
+ {
+ aMenuPane->AddMenuItemsL( R_CALEN_EDITOR_ATTACHMENTS_MENUPANE );
+ if( !EntryHasAttachments() )
+ {
+ aMenuPane->DeleteMenuItem( ECalenCmdRemoveAttachment );
+ }
+ }
+
+ aMenuPane->AddMenuItemsL( R_CALEN_UNIFIED_EDITOR_DEFAULT_MENUPANE );
+
+ if( ( ctrlid != ECalenEditorPlace ) ||
+ ( !CCalenLocationUtil::IsMapProviderAvailableL() ) )
+ {
+ aMenuPane->DeleteMenuItem( ECalenGetLocation );
+ }
+
+ if( IsCreatingNewEntry() )
+ {
+ // Always remove the `Discard Changes' option from the menu-
+ // pane when a new entry is being created.
+ aMenuPane->DeleteMenuItem( ECalenCmdCancel );
+ }
+ else
+ {
+ // While editing, first check if any of the fields have changed.
+ // Then check if the entry type field has changed.
+ if( !EditorDataHandler().IsEditedL() )
+ {
+ if( !EditorDataHandler().IsEntryTypeEdited() )
+ {
+ aMenuPane->DeleteMenuItem( ECalenCmdCancel );
+ }
+ }
+ }
+
+ if( !FeatureManager::FeatureSupported( KFeatureIdHelp ) )
+ {
+ aMenuPane->DeleteMenuItem( EAknCmdHelp );
+ }
+
+ if( ctrlid != ECalenEditorPeople )
+ {
+ aMenuPane->DeleteMenuItem( ECalenCmdAddPeople );
+ }
+
+ TryInsertSendMenuL( aResourceId, aMenuPane );
+ }
+ break;
+
+ default:
+ {
+ break;
+ }
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::OnCmdCancelL
+// Handles cancel command.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::OnCmdCancelL()
+ {
+ TRACE_ENTRY_POINT;
+
+ CAknQueryDialog* dlg = CAknQueryDialog::NewL();
+ if( dlg->ExecuteLD( R_CALEN_CANCEL_CHANGES_QUERY ) )
+ {
+ CloseFormWithoutActionsL();
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::OnCmdDeleteNoteL
+// Handles delete command.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::OnCmdDeleteNoteL()
+ {
+ TRACE_ENTRY_POINT;
+
+ TryToDeleteNoteL( ETrue );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::OnCmdSendL
+// Handles the send command. This function differs from the ViewerBase version
+// in that the ViewerBase does not attempt to save or delete the entry first.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::OnCmdSendL( TInt aCommandId )
+ {
+ TRACE_ENTRY_POINT;
+
+ // Show menu to user
+ // CCalenSend handles selection internally, so we don't get anything in return
+ iGlobalData->CalenSendL().DisplaySendCascadeMenuL();
+
+ // Try to send
+ if ( iGlobalData->CalenSendL().CanSendL(aCommandId) )
+ {
+ TBool canSend(ETrue);
+
+ const TBool continueOnError = EFalse;
+ iUnifiedEditorControl->ReadDataFromEditorL( continueOnError );
+ CCalenEditorDataHandler::TAction action =
+ EditorDataHandler().ShouldSaveOrDeleteOrDoNothingL();
+ if( action == CCalenEditorDataHandler::EActionSave )
+ {
+ canSend = TryToSaveNoteL();
+ }
+
+ if ( canSend )
+ {
+ iGlobalData->CalenSendL().SendAsVCalendarL( aCommandId, EditorDataHandler().Entry() );
+ }
+ }
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::OnCmdHelpL
+// Handles help command.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::OnCmdHelpL()
+ {
+ TRACE_ENTRY_POINT;
+
+ if( FeatureManager::FeatureSupported( KFeatureIdHelp ) )
+ {
+ HlpLauncher::LaunchHelpApplicationL(
+ iCoeEnv->WsSession(),
+ static_cast<CCoeAppUi*>( iCoeEnv->AppUi() )->AppHelpContextL() );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::OnCmdExitL
+// Handles exit command.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::OnCmdExitL()
+ {
+ TRACE_ENTRY_POINT;
+
+ TryExitL( EAknCmdExit );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::TryToDeleteNoteL
+// Deletes the note from agenda.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::TryToDeleteNoteL( TBool /* aIsViaDeleteMenu */ )
+ {
+ TRACE_ENTRY_POINT;
+ if (IsCreatingNewEntry())
+ {
+ iEntryUpdater->TryDeleteInstanceWithUiL( EditorDataHandler().Entry() ,
+ EditorDataHandler().InstanceDateTime() ,
+ *iServices );
+ }
+ else
+ {
+ // FIXME. With new MAgnEntryUi we could use MAgnEntryUi::EInstanceDeleted
+ iEntryUpdater->TryDeleteInstanceWithUiL( EditorDataHandler().Entry() ,
+ EditorDataHandler().InstanceDateTime() ,
+ iRepeatType, *iServices );
+ }
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::TryInsertSendMenuL
+// Inserts the send menu, if needed.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::TryInsertSendMenuL( TInt aResourceId, CEikMenuPane* aMenuPane )
+ {
+ TRACE_ENTRY_POINT;
+
+ // Only insert if there is some summary (or location)
+ if( !EditorDataHandler().AreTextFieldsEmptyL() )
+ {
+ // Insert Send menu item
+ iServices->OfferMenuPaneL( aResourceId, aMenuPane );
+ }
+ else
+ {// Delete Send Menu item if exists
+ aMenuPane->DeleteMenuItem( ECalenSend );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::CloseFormWithoutActionsL
+// Closes the form. We have to do it via dialog's exit mechanism
+// with custom id (KCalenButtonIdCloseForm).
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::CloseFormWithoutActionsL()
+ {
+ TRACE_ENTRY_POINT;
+
+ TryExitL( KCalenButtonIdCloseForm );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::CreateCustomControlL
+// Returns a new custom control.
+// -----------------------------------------------------------------------------
+//
+SEikControlInfo CCalenUnifiedEditor::CreateCustomControlL( TInt aControlType )
+ {
+ TRACE_ENTRY_POINT;
+
+ __ASSERT_ALWAYS( aControlType==ECalenCtDescriptionField, User::Invariant() );
+
+ TRACE_EXIT_POINT;
+ return iUnifiedEditorControl->Description()->CreateFieldL();
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ConvertCustomControlTypeToBaseControlType
+// This method has to be implemented, otherwise custom components do not work with forms.
+// -----------------------------------------------------------------------------
+//
+MEikDialogPageObserver::TFormControlTypes
+ CCalenUnifiedEditor::ConvertCustomControlTypeToBaseControlType( TInt aControlType ) const
+ {
+ TRACE_ENTRY_POINT;
+
+ if( aControlType == ECalenCtDescriptionField )
+ {
+ TRACE_EXIT_POINT;
+ return MEikDialogPageObserver::EEdwinDerived;
+ }
+
+ TRACE_EXIT_POINT;
+ return MEikDialogPageObserver::EUnknownType;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::AskRepeatingNoteQueriesL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCalenEditorDataHandler::TError CCalenUnifiedEditor::AskRepeatingNoteQueriesL(
+ CalCommon::TRecurrenceRange& aRepeatType )
+ {
+ TRACE_ENTRY_POINT
+ CCalenEditorDataHandler::TError error = CCalenEditorDataHandler::EFormErrNone;
+
+ switch( GetEntryType() )
+ {
+ case CCalEntry::EAnniv:
+ {
+
+ if ( ShouldQueryForStartDateChange() )
+ {
+ // Query for StartDate change
+ error = QueryStartDateChangeL();
+ }
+
+ TRACE_EXIT_POINT;
+ return error;
+ }
+ //break;
+
+ case CCalEntry::EAppt:
+ {
+ if ( ShouldQueryForStartDateChange() )
+ {
+ if ( EditorDataHandler().IsStartDateChanged() )
+ {
+ TRACE_EXIT_POINT;
+
+ // Query for StartDate change
+ return QueryStartDateChangeL();
+ }
+ }
+
+ if( iHasChosenRepeatType )
+ {
+ // Don't ask the "this/series" question when we have chosen already.
+ return error;
+ }
+ TRACE_EXIT_POINT;
+ return iUnifiedEditorControl->AskRepeatingNoteQueriesL(aRepeatType);
+ }
+ //break;
+
+ case CCalEntry::ETodo:
+ case CCalEntry::EEvent:
+ {
+ TRACE_EXIT_POINT;
+ return error;
+ }
+ //break;
+
+ default:
+ break;
+ }
+ return error;
+ }
+
+
+
+TBool CCalenUnifiedEditor::ShouldQueryForStartDateChange()
+ {
+ TBool shouldQuery = EFalse;
+ // For Meeting entry type.
+ if( GetEntryType() == CCalEntry::EAppt )
+ {
+ TRACE_EXIT_POINT;
+ shouldQuery = ! IsCreatingNewEntry() &&
+ ( Edited().IsRepeating() && EditorDataHandler().Original().IsRepeating() );
+ }
+
+ // For Anniversary enty type
+ if( GetEntryType() == CCalEntry::EAnniv )
+ {
+ TRACE_EXIT_POINT;
+ shouldQuery = ! IsCreatingNewEntry();
+ }
+ return shouldQuery;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::QueryStartDateChangeL
+// If the entry is repeating, and the edited start date is different from the
+// original start date, prompt the user and ask if they are sure they want to
+// change the start date of the repeating entry.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCalenEditorDataHandler::TError CCalenUnifiedEditor::QueryStartDateChangeL()
+ {
+ TRACE_ENTRY_POINT;
+ TTime oldStartDate = EditorDataHandler().Original().StartDateTime();
+ TTime newStartDate = Edited().StartDateTime();
+
+ // The "Are you sure you want to change start date of repeating note?"
+ // query should only be shown for repeating notes.
+ if ( iRepeatType == CalCommon::EThisAndAll
+ && ! CalenDateUtils::OnSameDay( oldStartDate, newStartDate ) )
+ {
+ CAknQueryDialog* queryDlg = CAknQueryDialog::NewL();
+ TInt answer = queryDlg->ExecuteLD( R_CALEN_REPEAT_NOTE_START_CHANGED );
+ if (!answer) // Answer "No"
+ {
+ TRACE_EXIT_POINT;
+ return CCalenEditorDataHandler::EFormErrCancelSaveRepNoteWhenStartChange;
+ }
+ }
+ TRACE_EXIT_POINT;
+ return CCalenEditorDataHandler::EFormErrNone;
+ }
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::IsCreatingNewEntry
+// Returns ETrue if the entry has just been created, EFalse if the entry
+// already existed in agenda.
+// -----------------------------------------------------------------------------
+//
+TBool CCalenUnifiedEditor::IsCreatingNewEntry() const
+ {
+ TRACE_ENTRY_POINT;
+
+ TRACE_EXIT_POINT;
+ return iEntryUiInParams.iEditorMode == MAgnEntryUi::ECreateNewEntry;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::MaxTextEditorLength
+// Returns the maximum length the text editor can be.
+// -----------------------------------------------------------------------------
+//
+TInt CCalenUnifiedEditor::MaxTextEditorLength() const
+ {
+ TRACE_ENTRY_POINT;
+
+ switch ( AknLayoutUtils::Variant() )
+ {
+ case EEuropeanVariant:
+ {
+ TRACE_EXIT_POINT;
+ return KCalenMaxELAFTextEditorLength;
+ }
+ case EApacVariant:
+ {
+ TRACE_EXIT_POINT;
+ return KCalenMaxAPACTextEditorLength;
+ }
+ }
+
+ TRACE_EXIT_POINT;
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::EditorDataHandler
+// Returns the editor data handler.
+// -----------------------------------------------------------------------------
+//
+CCalenEditorDataHandler& CCalenUnifiedEditor::EditorDataHandler()
+ {
+ TRACE_ENTRY_POINT;
+
+ TRACE_EXIT_POINT;
+ return *iEditorDataHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::Edited
+// Returns the data being edited.
+// -----------------------------------------------------------------------------
+//
+CCalenEntryUtil& CCalenUnifiedEditor::Edited()
+ {
+ TRACE_ENTRY_POINT;
+
+ TRACE_EXIT_POINT;
+ return iEditorDataHandler->Edited();
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::Original
+// Returns the original data.
+// -----------------------------------------------------------------------------
+//
+const CCalenEntryUtil& CCalenUnifiedEditor::Original() const
+ {
+ TRACE_ENTRY_POINT;
+
+ TRACE_EXIT_POINT;
+ return iEditorDataHandler->Original();
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::SetEditorTextL
+// Sets editor text
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetEditorTextL( TInt aControlId, const TDesC* aDes )
+ {
+ TRACE_ENTRY_POINT;
+
+ SetEdwinTextL( aControlId, aDes );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ReadSubjectFromEditorL
+// Reads subject field from unified editor
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::ReadSubjectFromEditorL()
+ {
+ TRACE_ENTRY_POINT;
+
+ TBuf<ECalenAbsoluteMaxTextEditorLength> editorText;
+ GetEdwinText( editorText,ECalenEditorSubject );
+ Edited().SetSummaryL( editorText );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ReadPlaceFromEditorL
+// Reads "Place" item from unified editor
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::ReadPlaceFromEditorL()
+ {
+ TRACE_ENTRY_POINT;
+
+ // Location
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ GetEdwinText(location, ECalenEditorPlace);
+
+ TInt pos = location.Locate(TChar(CEditableText::EPictureCharacter));
+ while(pos != KErrNotFound)
+ {
+ location.Delete(pos, 1);
+ pos = location.Locate(TChar(CEditableText::EPictureCharacter));
+ }
+
+ Edited().SetLocationL( location );
+ SetEdwinTextL( ECalenEditorPlace, &location );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::SetEntryType
+// Sets the unified editor's entry type
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetEntryType( CCalEntry::TType aEntryType )
+ {
+ TRACE_ENTRY_POINT;
+ iEntryType = aEntryType;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::GetEntryType
+// Gets unified editor entry type
+// -----------------------------------------------------------------------------
+//
+CCalEntry::TType CCalenUnifiedEditor::GetEntryType()
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ return iEntryType;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::EditorFields
+// Access to the unified editor's fields
+// -----------------------------------------------------------------------------
+//
+CCalenUnifiedEditorControl& CCalenUnifiedEditor::EditorFields()
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ return *iUnifiedEditorControl;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::SetAlarmFieldOnOffL
+// Set alarm field on or off
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetAlarmFieldOnOffL( TBool aOnOff )
+ {
+ TRACE_ENTRY_POINT;
+
+ HBufC* String;
+ CEikEdwin* alarmFieldText =( CEikEdwin* )Control( ECalenEditorReminder );
+ if( aOnOff )
+ {
+ // load string 'ON'
+ String = StringLoader::LoadLC( R_QTN_ALARM_ACTIVE, iCoeEnv );
+ }
+ else
+ {
+ // load string 'OFF'
+ String = StringLoader::LoadLC( R_QTN_ALARM_OFF,iCoeEnv );
+ }
+ // set Alarm field string as 'ON'/'OFF'
+ alarmFieldText->SetTextL(String);
+ CleanupStack::PopAndDestroy(String);
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::SetAllDayFieldL
+// Set alarm field on or off
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetAllDayFieldL(TBool aYesNo)
+ {
+ TRACE_ENTRY_POINT;
+
+ HBufC* String;
+ CEikEdwin* allDayFieldText =( CEikEdwin* )ControlOrNull( ECalenEditorAllDayItem );
+ if( aYesNo )
+ {
+ // load string 'YES'
+ String = StringLoader::LoadLC( R_QTN_ALLDAY_EVENT_YES,iCoeEnv );
+ }
+ else
+ {
+ // load string 'NO'
+ String = StringLoader::LoadLC( R_QTN_ALLDAY_EVENT_NO,iCoeEnv );
+ }
+ if( allDayFieldText )
+ {
+ // Set AllDay field text as 'YES'/'NO'
+ allDayFieldText->SetTextL( String );
+ }
+ CleanupStack::PopAndDestroy( String );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::IdOfFocusedControl
+// For getting Id of the focused control
+// -----------------------------------------------------------------------------
+//
+TInt CCalenUnifiedEditor::IdOfFocusedControl()
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ return IdOfFocusControl();
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleDoneL
+// Handle pressing of Done (LSK). Entry is saved or deleted, or if not edited
+// nothing is done.
+// -----------------------------------------------------------------------------
+//
+TBool CCalenUnifiedEditor::HandleDoneL()
+ {
+ TRACE_ENTRY_POINT;
+
+ const TBool continueOnError = EFalse;
+ iUnifiedEditorControl->ReadDataFromEditorL( continueOnError );
+
+ TEntryExistenceStatus status = EntryStillExistsL();
+ TTimeIntervalDays aDay(0);
+ if( iCurrentDurationDay<aDay )
+ {
+ DisplayErrorMsgL( CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime );
+ return EFalse;
+ }
+
+ if ( status == EEntryOk )
+ {
+
+ TTime startDate = Edited().StartDateTime();
+ TTime endDate = Edited().EndDateTime();
+
+ if( startDate == CalenDateUtils::BeginningOfDay( startDate ) &&
+ endDate == CalenDateUtils::BeginningOfDay( endDate ) )
+ {
+ if( CCalEntry::EAppt == Edited().EntryType() && startDate != endDate )
+ {
+ Edited().SetEntryType( CCalEntry::EEvent );
+ }
+ }
+
+ switch ( EditorDataHandler().ShouldSaveOrDeleteOrDoNothingL() )
+ {
+ case CCalenEditorDataHandler::EActionSave:
+ {
+ TRACE_EXIT_POINT;
+ return TryToSaveNoteL();
+ }
+ case CCalenEditorDataHandler::EActionDelete:
+ {
+ TryToDeleteNoteL( EFalse );
+ TRACE_EXIT_POINT;
+ // don't exit from the editor dialog here
+ // wait for the delete success/ delete failed notification
+ // exit from CCalenFormBase::HandleNotification( aNotification );
+ // return ETrue;
+ return EFalse;
+ }
+ case CCalenEditorDataHandler::EActionNothing:
+ {
+ TRACE_EXIT_POINT;
+ return ETrue;
+ }
+ }
+ }
+ else
+ {
+ if( status == EEntryModifiedByAnotherProcess )
+ {
+ // Entry no longer exists. Show an error message then return to the viewer.
+ DisplayErrorMsgL( CCalenEditorDataHandler::EFormErrDbConflictEntryModified );
+ // Other process may have changed start day/time.
+
+ // FIXME
+ // Assumes the entry view is not null
+ CCalEntry *newEntry = NULL;
+ for(TInt i = 0 ; i < iCollectionIds.Count() ; i++)
+ {
+ newEntry = ( *( iServices->EntryViewL(iCollectionIds[i]) ) )
+ .FetchL( iOriginalCalEntry->LocalUidL() );
+ }
+
+ if(newEntry)
+ {
+ CleanupStack::PushL( newEntry );
+ iEntryUiOutParams.iNewInstanceDate = newEntry->StartTimeL();
+ iEntryUiOutParams.iSpare = (TUint32) newEntry->LocalUidL();
+ CleanupStack::PopAndDestroy(newEntry);
+ iEntryUiOutParams.iAction = EMeetingSaved;
+ }
+ }
+ else
+ {
+ if( status == EEntryDeletedByAnotherProcess )
+ {
+ // Entry no longer exists. Show an error message then close the form.
+ DisplayErrorMsgL( CCalenEditorDataHandler::EFormErrDbConflictEntryDeleted );
+ iEntryUiOutParams.iAction = EMeetingDeleted;
+ }
+ }
+
+ TRACE_EXIT_POINT;
+ return ETrue;
+ }
+
+ // All cases should be handled above
+ __ASSERT_ALWAYS( EFalse, User::Invariant() );
+ TRACE_EXIT_POINT;
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CheckSpaceBelowCriticalLevelL
+// Checks if the Flash File System storage will fall below critical level.
+// If there is not enough space, display an error message and return EFalse.
+// Return ETrue otherwise.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CCalenUnifiedEditor::CheckSpaceBelowCriticalLevelL()
+ {
+ TRACE_ENTRY_POINT;
+ // FIXME: Could be moved to commonui
+ TBool retcode(EFalse);
+
+ if ( SysUtil::FFSSpaceBelowCriticalLevelL( &( iCoeEnv->FsSession() ) ) )
+ {
+ CErrorUI* errorUi = CErrorUI::NewLC();
+ errorUi->ShowGlobalErrorNoteL( KErrDiskFull );
+ CleanupStack::PopAndDestroy( errorUi );
+ retcode = ETrue;
+ }
+ TRACE_EXIT_POINT;
+ return retcode;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::TryToSaveNoteL
+// Save form data. Return ETrue if saving is successful, EFalse otherwise.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CCalenUnifiedEditor::TryToSaveNoteL()
+ {
+ TRACE_ENTRY_POINT;
+
+ if( CheckSpaceBelowCriticalLevelL() )
+ {
+ TRACE_EXIT_POINT;
+ return EFalse;
+ }
+
+ // Check if location field is edited manually
+ CheckManualEditionOfLocationL();
+
+
+ CCalenEditorDataHandler::TError error = CCalenEditorDataHandler::EFormErrNone;
+
+ if( ( !iHasChosenRepeatType && ! EditorDataHandler().IsChildL() ) ||
+ (iHasChosenRepeatType && iRepeatType == CalCommon::EThisAndAll ) )
+ {
+ // Check for the errors, with the entered data
+ error = EditorDataHandler().CheckErrorsForThisAndAllL();
+ }
+ else if( EditorDataHandler().IsChildL() || iRepeatType == CalCommon::EThisOnly )
+ {
+ // Check for the errors, for editing Child entry.
+ error = EditorDataHandler().CheckErrorsForThisOnlyL( ParentEntryL(), *(iServices->InstanceViewL(iCollectionIds) ));
+ }
+
+ if ( error == CCalenEditorDataHandler::EFormErrNone )
+ {
+ error = AskRepeatingNoteQueriesL(iRepeatType);
+ if(error == CCalenEditorDataHandler::EFormErrNone)
+ {
+ iHasChosenRepeatType = ETrue;
+ }
+ }
+
+ if ( error == CCalenEditorDataHandler::EFormErrNone )
+ {
+ ModifyDbField();//default calendar code
+ EditorDataHandler().WriteChangesToEntryL( iRepeatType );
+
+ TCalTime newInstanceStartDate, newInstanceEndDate;
+ CalculateNewInstanceStartAndEndDateL( newInstanceStartDate, newInstanceEndDate );
+
+ TInt saveErr( 0 );
+ TBool dbChange = iEditorDataHandler->IsCalendarEditedL();
+ if( iEditedCalEntry.EntryTypeL() != Edited().EntryType() || dbChange )
+ {
+ // If calendar EntryType is changed,
+ // Entry should be re-created with new EntryType and Save.
+ saveErr = TryToSaveEntryWithEntryChangeL( EFalse );
+ }
+ else
+ {
+ TRAP( saveErr, iEntryUpdater->UpdateInstanceL(
+ EditorDataHandler().Entry(),
+ *iOriginalCalEntry,
+ EditorDataHandler().InstanceDateTime(),
+ iRepeatType,
+ newInstanceStartDate,
+ newInstanceEndDate,
+ iUnifiedEditorControl->GetCalendarNameForEntryL() ) );
+
+ iEntryUiOutParams.iSpare
+ = (TUint32) EditorDataHandler().Entry().LocalUidL();
+ }
+
+ if ( saveErr != KErrNone )
+ {
+ iEikonEnv->ResolveError( saveErr );
+ }
+ else
+ {
+ iEntryUiOutParams.iAction = MAgnEntryUi::EMeetingSaved;
+ iEntryUiOutParams.iNewInstanceDate = newInstanceStartDate;
+ }
+ TRACE_EXIT_POINT;
+ return ETrue;
+ }
+
+ else
+ {
+ // If save error occurs, display error message.
+ DisplayErrorMsgL( error );
+ // HandleErrorL(error);
+ TRACE_EXIT_POINT;
+ return EFalse;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::TryToSaveEntryWithEntryTypeChangeL
+// Save form data. Return EErrNone if saving is successful, error value otherwise.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+TInt CCalenUnifiedEditor::TryToSaveEntryWithEntryChangeL( TBool aForcedExit)
+ {
+ CCalEntry* entry;
+
+ //Get the guid from original entry and set it to new entry.
+ HBufC8* guid = iOriginalCalEntry->UidL().AllocL();
+
+
+ if( iEditedCalEntry.RecurrenceIdL().TimeUtcL() != Time::NullTTime() )
+ {
+ entry = CCalEntry::NewL( Edited().EntryType(),
+ guid,
+ iEditedCalEntry.MethodL(),
+ iEditedCalEntry.SequenceNumberL(),
+ iEditedCalEntry.RecurrenceIdL(),
+ iEditedCalEntry.RecurrenceRangeL() );
+
+ }
+ else
+ {
+ entry = CCalEntry::NewL( Edited().EntryType(),
+ guid,
+ iEditedCalEntry.MethodL(),
+ iEditedCalEntry.SequenceNumberL() );
+
+ }
+
+ // CleanupStack::Pop( guid ); // ownership was passed
+
+ CleanupStack::PushL( entry );
+ iEditedCalEntry.DescriptionL(); // make sure entry is fully loaded
+ entry->CopyFromL(iEditedCalEntry, CCalEntry::EDontCopyId);
+ entry->DescriptionL(); // make sure entry is fully copied
+
+ TCalTime newInstanceStartDate, newInstanceEndDate;
+ CalculateNewInstanceStartAndEndDateL( newInstanceStartDate, newInstanceEndDate );
+ entry->SetStartAndEndTimeL( newInstanceStartDate, newInstanceEndDate );
+ if(iEditedCalEntry.EntryTypeL() != GetEntryType())
+ {
+ if( entry->EntryTypeL() == CCalEntry::EAnniv )
+ {
+ // Set yearly rule to Anniversary entry, to create Annaiversary instance yearly
+ TCalRRule rrule( TCalRRule::EYearly );
+ TCalTime startDate;
+ rrule.SetDtStart( newInstanceStartDate );
+ rrule.SetInterval( 1 ); // once a year
+ entry->SetRRuleL( rrule );
+ }
+ }
+
+ if(!IsCreatingNewEntry())
+ {
+ iServices->EntryViewL(iEditorDataHandler->PreviousDbCollectionId())
+ ->DeleteL(*iOriginalCalEntry);
+ }
+
+ TInt saveErr( KErrNone );
+ if( aForcedExit )
+ {
+ iEntryUpdater->UpdateInstanceL(
+ *entry,
+ *iOriginalCalEntry,
+ EditorDataHandler().InstanceDateTime(),
+ iRepeatType,
+ newInstanceStartDate,
+ newInstanceEndDate,
+ iUnifiedEditorControl->GetCalendarNameForEntryL() );
+
+ }
+ else
+ {
+ TRAP( saveErr, iEntryUpdater->UpdateInstanceL(
+ *entry,
+ *iOriginalCalEntry,
+ EditorDataHandler().InstanceDateTime(),
+ iRepeatType,
+ newInstanceStartDate,
+ newInstanceEndDate,
+ iUnifiedEditorControl->GetCalendarNameForEntryL() ) );
+ }
+
+ iEntryUiOutParams.iSpare = (TUint32) entry->LocalUidL();
+
+ CleanupStack::PopAndDestroy(entry);
+ return saveErr;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::TryToSaveNoteOnForcedExitL
+// Try to save note when editors are forced to exit.
+// This can happen when the user presses the red key, power off, Options->Exit,
+// or in out-of-memory situations.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::TryToSaveNoteOnForcedExitL()
+ {
+ TRACE_ENTRY_POINT;
+
+ if( EntryStillExistsL() == EEntryOk )
+ {
+ if( CheckSpaceBelowCriticalLevelL() )
+ {
+ TRACE_EXIT_POINT;
+ return;
+ }
+
+ // Check if location field is edited manually
+ CheckManualEditionOfLocationL();
+
+ const TBool continueOnError = ETrue;
+ iUnifiedEditorControl->ReadDataFromEditorL( continueOnError );
+
+ CCalenEditorDataHandler::TAction action =
+ EditorDataHandler().ShouldSaveOrDeleteOrDoNothingL();
+
+ if( iHasChosenRepeatType && iRepeatType == CalCommon::EThisAndAll )
+ {
+ // Check for the errors, with the entered data
+ if ( EditorDataHandler().CheckErrorsForThisAndAllL() != KErrNone )
+ return;
+ }
+ if ( action == CCalenEditorDataHandler::EActionSave )
+ {
+ EditorDataHandler().ForceValidValuesL( iHasChosenRepeatType? iRepeatType
+ : CalCommon::EThisAndAll );
+ ModifyDbField();//Default Calendar code
+ EditorDataHandler().WriteChangesToEntryL( iHasChosenRepeatType? iRepeatType
+ : CalCommon::EThisAndAll );
+
+ TCalTime newInstanceStartDate, newInstanceEndDate;
+ CalculateNewInstanceStartAndEndDateL( newInstanceStartDate,
+ newInstanceEndDate );
+
+ TBool onDbChange = iEditorDataHandler->IsCalendarEditedL();
+ if( iEditedCalEntry.EntryTypeL() != GetEntryType() || onDbChange)
+ {
+ TryToSaveEntryWithEntryChangeL( ETrue );
+ }
+ else
+ {
+ iEntryUpdater->UpdateInstanceL( EditorDataHandler().Entry(),
+ *iOriginalCalEntry,
+ EditorDataHandler().InstanceDateTime(),
+ iRepeatType,
+ newInstanceStartDate,
+ newInstanceEndDate,
+ iUnifiedEditorControl->GetCalendarNameForEntryL() );
+ }
+ }
+ else
+ {
+ if ( action == CCalenEditorDataHandler::EActionDelete )
+ {
+ // FIXME, should we write date/time changes to entry?
+ if ( !IsCreatingNewEntry() )
+ {
+ if( iHasChosenRepeatType && iRepeatType == CalCommon::EThisOnly )
+ {
+ iEntryUpdater->DeleteInstanceL( EditorDataHandler().Entry(), EditorDataHandler().CalenInstanceId() );
+ }
+ else
+ {
+ iEntryUpdater->DeleteEntryL( EditorDataHandler().Entry(), EditorDataHandler().CalenInstanceId() );
+ }
+ }
+ }
+ }
+ }
+ TRACE_EXIT_POINT;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::CalculateNewInstanceStartAndEndDateL
+// Calculate the new start and end time and date of the instance.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::CalculateNewInstanceStartAndEndDateL( TCalTime& aNewInstanceStartDate,
+ TCalTime& aNewInstanceEndDate )
+ {
+ TRACE_ENTRY_POINT;
+
+ // Use floating time for non-timed entries
+ if (EditorDataHandler().UseFloatingTimeL())
+ {
+ aNewInstanceStartDate.SetTimeLocalFloatingL( EditorDataHandler().Edited().StartDateTime() );
+ aNewInstanceEndDate.SetTimeLocalFloatingL( EditorDataHandler().Edited().EndDateTime() );
+ }
+ else
+ {
+ aNewInstanceStartDate.SetTimeLocalL( EditorDataHandler().Edited().StartDateTime() );
+ aNewInstanceEndDate.SetTimeLocalL( EditorDataHandler().Edited().EndDateTime() );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::DisplayErrorMsgL
+// Display the given error message.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::DisplayErrorMsgL( const TInt& aError )
+ {
+ TRACE_ENTRY_POINT;
+ TBool toContinue( ETrue );
+ TInt resourceId( -1 );
+
+ switch ( aError )
+ {
+ case CCalenEditorDataHandler::EFormErrStopTimeEarlierThanStartTime:
+ {
+ resourceId = R_QTN_CALE_INFO_NOTE_ENDS_BEFORE;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrAlarmTimeLaterThanNote:
+ {
+ resourceId = R_QTN_CALE_LATER_DATE;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrAlarmTimePast:
+ {
+ resourceId = R_QTN_CALE_NOT_EXPIRED;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrAlarmDateTooManyDaysBeforeNote:
+ {
+ resourceId = R_QTN_CALE_DATE_ALARM_PAST;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrRepeatUntilEarlierThanNote:
+ {
+ resourceId = R_QTN_CALE_INFO_REPEAT_INVALID;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrDbConflictEntryModified:
+ {//"Calendar database conflict. This entry has been modified by another application."
+ DisplayErrorMsgInNoteDlgL( R_QTN_CALE_NOTE_DB_MODIFIED );
+ toContinue = EFalse;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrDbConflictEntryDeleted:
+ {//"Calendar database conflict. This entry has been deleted by another application."
+ DisplayErrorMsgInNoteDlgL( R_QTN_CALE_NOTE_DB_CONFLICT );
+ toContinue = EFalse;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrDurationGreaterThanRepeatInterval:
+ {
+ DispalyErrorMsgByRepeatTypeL();
+ toContinue = EFalse;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrOverlapsExistingInstance:
+ {
+ resourceId = R_QTN_CALE_NOTE_CHILD_OVERLAP;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrOutOfSequence:
+ {
+ resourceId = R_QTN_CALE_NOTE_CHILD_OUT_OF_SEQUENCE;
+ break;
+ }
+ case CCalenEditorDataHandler::EFormErrInstanceAlreadyExistsOnThisDay:
+ {
+ resourceId = R_QTN_CALE_NOTE_CHILD_SAME_DAY;
+ break;
+ }
+ default:
+ {
+ toContinue = EFalse;
+ }
+ }
+ if( toContinue )
+ {
+ CAknInformationNote* dialog = new ( ELeave ) CAknInformationNote();
+ HBufC* buf = StringLoader::LoadLC( resourceId, iEikonEnv );
+ dialog->ExecuteLD( *buf );
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ParentEntryL
+// Returns the parent entry of the entry being edited.
+// -----------------------------------------------------------------------------
+//
+CCalEntry& CCalenUnifiedEditor::ParentEntryL()
+ {
+ TRACE_ENTRY_POINT;
+ TCalCollectionId colId = iEditorDataHandler->CurrentDbCollectionId();
+ VerifyCollectionIdL(colId);
+
+ if( iFetchedEntries.Count() == 0 )
+ {
+ iServices->EntryViewL(colId)
+ ->FetchL( EditorDataHandler().Entry().UidL(), iFetchedEntries );
+ }
+
+ TRACE_EXIT_POINT;
+ return *iFetchedEntries[0];
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::DisplayErrorMsgInNoteDlgL
+// Display conflict error message.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::DisplayErrorMsgInNoteDlgL( TInt resourceId )
+ {
+ TRACE_ENTRY_POINT;
+
+ CAknNoteDialog *note = new(ELeave) CAknNoteDialog( CAknNoteDialog::EWarningTone,
+ CAknNoteDialog::ENoTimeout );
+ HBufC* buf = StringLoader::LoadLC( resourceId, iEikonEnv );
+ note->SetTextL( *buf );
+ note->ExecuteLD( R_CALEN_DB_CONFLICT_DIALOG );
+ CleanupStack::PopAndDestroy( buf );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::DisplayErrorMsgByRepeatTypeL
+// Display conflict error message.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::DispalyErrorMsgByRepeatTypeL()
+ {
+ TRACE_ENTRY_POINT;
+
+ TTimeIntervalDays dur = Edited().EndDateTime().DaysFrom( Edited().StartDateTime() );
+ CAknInformationNote* dialog = new (ELeave) CAknInformationNote();
+ TInt resourceId( -1 );
+ TBool toContinue( ETrue );
+ // to find total num of days entry span .
+ TInt numDaysEntrySpan = dur.Int() + 1 ;
+
+ switch( Edited().RepeatType() )
+ {
+ case ERepeatDaily:
+ case ERepeatWorkdays:
+ {
+ resourceId = R_QTN_CALE_INFO_NOTE_DURATION_TOO_LONG_FOR_DAILY;
+ }
+ break;
+ case ERepeatWeekly:
+ {
+ resourceId = R_QTN_CALE_INFO_NOTE_DURATION_TOO_LONG_FOR_WEEKLY;
+ }
+ break;
+ case ERepeatBiWeekly:
+ {
+ resourceId = R_QTN_CALE_INFO_NOTE_DURATION_TOO_LONG_FOR_BIWEEKLY;
+ }
+ break;
+ case ERepeatMonthly:
+ {
+ resourceId = R_QTN_CALE_INFO_NOTE_DURATION_TOO_LONG_FOR_MONTHLY;
+ }
+ break;
+ case ERepeatYearly:
+ {
+ resourceId = R_QTN_CALE_INFO_NOTE_DURATION_TOO_LONG_FOR_YEARLY;
+ }
+ break;
+ default:
+ toContinue = EFalse;
+ }
+ if( toContinue )
+ {
+ HBufC* buf = StringLoader::LoadLC( resourceId,numDaysEntrySpan, iEikonEnv );
+ dialog->ExecuteLD( *buf );
+ CleanupStack::PopAndDestroy( buf );
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy( dialog );
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::EntryStillExistsL
+// Checks the entry still exists in the database. If the entry has been
+// removed or modified, the appropriate action is returned.
+// -----------------------------------------------------------------------------
+//
+CCalenUnifiedEditor::TEntryExistenceStatus CCalenUnifiedEditor::EntryStillExistsL()
+ {
+ TRACE_ENTRY_POINT;
+ TEntryExistenceStatus status = EEntryOk;
+
+ // Check to see if the entry open in the editor still exists
+ if ( iLastDbChangeNotification >= iTimeStamp )
+ {
+ // The database was changed through another session while the editor was open.
+ // Search for our entry to check it still exists.
+
+ CCalEntry* dbEntry = NULL;
+ for(TInt i = 0 ;i < iCollectionIds.Count() ; i++)
+ {
+ //check the exsists in one of the calendars
+ PIM_TRAPD_HANDLE( ( dbEntry = iServices->EntryViewL(iCollectionIds[i])
+ ->FetchL( iOriginalCalEntry->LocalUidL() ) ) );
+ if(dbEntry)
+ {
+ break;
+ }
+ }
+
+ // I would have thought we could check for KErrNotFound here, but we just get a NULL
+ // entry returned if it doesn't exist anymore.
+ if ( !dbEntry )
+ {
+ // The entry we are editing has been deleted.
+ status = EEntryDeletedByAnotherProcess;
+ }
+ else
+ {
+ CleanupStack::PushL( dbEntry );
+ //Check the last modified time of the entry we retrieved from the database
+ if ( dbEntry->LastModifiedDateL().TimeUtcL() >= iTimeStamp )
+ {
+ // This entry has been modified in some way, but not by us.
+ // Abandon our changes
+ status = EEntryModifiedByAnotherProcess;
+ }
+ CleanupStack::PopAndDestroy( dbEntry );
+ }
+ }
+
+ TRACE_EXIT_POINT;
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::UpdateLocationInfoToFormL
+// Updates the user selected landmark details into current meeting editor form
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::UpdateLocationInfoToFormL()
+ {
+ TRACE_ENTRY_POINT;
+
+ // Get location details from context
+ MCalenContext& context = iServices->Context();
+ CPosLandmark* landmark = context.GetLandMark();
+ TBuf<ECalenAbsoluteMaxTextEditorLength> locationInfo;
+ GetEdwinText(locationInfo, ECalenEditorPlace);
+ if(landmark) // If user has selected location from Map
+ {
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ GetEdwinText(location, ECalenEditorPlace);
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue || isReplaceLocation)
+ {
+ isReplaceLocation = EFalse;
+ HandleEntryWithGeoValueEditionL(landmark);
+ delete geoValue;
+ }
+ else if(locationInfo.Length() && !isReplaceLocation)
+ {
+ HandleEntryWithLocationEditionL(landmark);
+ }
+ else // This is the new entry being created and nothing is there in location field
+ {
+ isReplaceLocation = EFalse;
+ StoreLocationDetailsToEntryL(landmark);
+ AddPictureL(0);
+ }
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleEntryWithGeoValueEditionL
+// Shows suery to the user to replace gthe exisitng saved address
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::HandleEntryWithGeoValueEditionL(CPosLandmark* landmark)
+ {
+ TRACE_ENTRY_POINT;
+
+ // User is tyring to update the location field of an entry which
+ // already has location text as well as geo coordinates
+ TPtrC locationName;
+ landmark->GetLandmarkName(locationName);
+ TInt userResponse = ShowLocationReplaceNoticeL(locationName);
+ if(userResponse)
+ {
+ StoreLocationDetailsToEntryL(landmark);
+ AddPictureL();
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HandleEntryWithLocationEditionL
+// Shows suery to the user to replace gthe exisitng saved address
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::HandleEntryWithLocationEditionL(CPosLandmark* landmark)
+ {
+ TRACE_ENTRY_POINT;
+
+ // User is tyring to update the location field of an entry which
+ // already has location text as well as geo coordinates
+ TBuf<ECalenAbsoluteMaxTextEditorLength> locationInfo;
+ GetEdwinText(locationInfo, ECalenEditorPlace);
+ TPtrC landmarkname;
+ landmark->GetLandmarkName(landmarkname);
+ RPointerArray<HBufC> locationStrings;
+ HBufC* oldLocation = HBufC::NewL(MaxTextEditorLength());
+ oldLocation->Des().Copy(locationInfo);
+
+ HBufC* oldNewLocation = HBufC::NewL(MaxTextEditorLength());
+ TBuf<2*ECalenAbsoluteMaxTextEditorLength> combLocation;
+ combLocation.Append(locationInfo);
+ combLocation.Append(KComma);
+ combLocation.Append(landmarkname);
+ oldNewLocation->Des().Copy(combLocation.Left(MaxTextEditorLength()));
+
+ HBufC* newLocation = HBufC::NewL(MaxTextEditorLength());
+ newLocation->Des().Copy(landmarkname);
+ locationStrings.Append(oldNewLocation);
+ locationStrings.Append(newLocation);
+ locationStrings.Append(oldLocation);
+ TInt userResponse = CCalenLocationUtil::ShowLocationAppendOrReplaceL(locationStrings);
+ locationStrings.ResetAndDestroy();
+ if(userResponse == KErrCancel)
+ {
+ return;
+ }
+ switch(userResponse)
+ {
+ case 0:
+ {
+ landmark->SetLandmarkNameL(combLocation.Left(MaxTextEditorLength()));
+ }
+ break;
+ case 1:
+ {
+ landmark->SetLandmarkNameL(landmarkname);
+ }
+ break;
+ case 2:
+ {
+ landmark->SetLandmarkNameL(locationInfo);
+ }
+ break;
+ default:
+ break;
+ }
+ StoreLocationDetailsToEntryL(landmark);
+ AddPictureL(0);
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::StoreLocationDetailsToEntryL
+// Stores landmark details and displays selected location details on the
+// currently shown editor form
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::StoreLocationDetailsToEntryL(CPosLandmark* landmark)
+ {
+ TRACE_ENTRY_POINT;
+
+ TLocality position;
+ landmark->GetPosition(position);
+
+ TBuf<ECalenAbsoluteMaxTextEditorLength> existingLocationInfo;
+ GetEdwinText(existingLocationInfo, ECalenEditorPlace);
+
+ //Store the geo coordinates
+ CCalGeoValue* geoValue = CCalGeoValue::NewL();
+ geoValue->SetLatLongL( position.Latitude(), position.Longitude() );
+ EditorDataHandler().Entry().SetGeoValueL( *geoValue );
+ delete geoValue;
+
+ TBuf<ECalenAbsoluteMaxTextEditorLength> locationDetails;
+ TPtrC landmarkname;
+ landmark->GetLandmarkName( landmarkname );
+ locationDetails.Append( landmarkname );
+
+ TPtrC landmarkDesc;
+ landmark->GetLandmarkDescription( landmarkDesc );
+ if( landmarkDesc.Size() )
+ {
+ locationDetails.Append( KComma );
+ locationDetails.Append( landmarkDesc );
+ }
+
+ Edited().SetLocationL( locationDetails.Left( MaxTextEditorLength()) );
+
+ TPtrC location = Edited().Location().Left( MaxTextEditorLength() );
+ EditorDataHandler().Entry().SetLocationL( location );
+
+ SetEdwinTextL(ECalenEditorPlace, &location);
+ if(existingLocationInfo.Length())
+ {
+ ShowAddressUpdatedNoticeL();
+ }
+
+ PreLayoutDynInitL();
+
+ TRACE_EXIT_POINT;
+ }
+
+// ----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ShowLocationReplaceNoticeL
+// Function to query user whether to replace or keep existing location details
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+TInt CCalenUnifiedEditor::ShowLocationReplaceNoticeL(TPtrC aLocationName)
+ {
+ TRACE_ENTRY_POINT;
+
+ CAknQueryDialog *dialog = CAknQueryDialog::NewL( );
+ CleanupStack::PushL( dialog );
+ TInt resID = R_CALEN_QTN_REPLACE_LOCATION;
+
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ TChar quote = '"';
+ location.Append(quote);
+ location.Append(aLocationName);
+ location.Append(quote);
+
+ CEikonEnv* eikEnv = CEikonEnv::Static();
+
+ HBufC* prompt = StringLoader::LoadLC( resID, location, eikEnv );
+
+ dialog->SetPromptL( *prompt );
+ CleanupStack::PopAndDestroy( prompt );
+
+ CleanupStack::Pop( dialog );
+
+ return dialog->ExecuteLD( R_CALEN_LOCATION_REPLACE_NOTE );
+
+ TRACE_EXIT_POINT;
+ }
+
+// ----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ShowAddressUpdatedNoticeL
+// Displays "Address Updated" transient notice
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::ShowAddressUpdatedNoticeL()
+ {
+ HBufC* buf = StringLoader::LoadLC( R_CALEN_QTN_ADDRESS_UPDATED, CEikonEnv::Static() );
+ CAknConfirmationNote* dialog = new( ELeave ) CAknConfirmationNote();
+ dialog->ExecuteLD(*buf);
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::CheckManualEditionOfLocationL
+// Checks if user has edited location field manually
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::CheckManualEditionOfLocationL()
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalEntry& entry = EditorDataHandler().Entry();
+ CCalGeoValue* geoValue = entry.GeoValueL();
+ if( !geoValue )
+ {
+ return;
+ }
+ delete geoValue;
+
+ TPtrC entryLocation = entry.LocationL();
+ TBuf<ECalenAbsoluteMaxTextEditorLength> location;
+ location.Copy(Edited().Location());
+
+ if( entryLocation != location )
+ {
+ // USer has manually edited the location field
+ TInt response = ShowLocationChangeNoticeL();
+ if( !response )
+ {
+ // Clear the geo coordinates for the entry
+ entry.ClearGeoValueL();
+ Edited().SetLocationL( location );
+ EditorDataHandler().Entry().SetLocationL(location);
+ SetEdwinTextL(ECalenEditorPlace, &location);
+ }
+ else
+ {
+ EditorDataHandler().Entry().SetLocationL(location);
+ }
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ShowLocationChangeNoticeL
+// Queries user whether to keep the exisiting coordianates or not
+// -----------------------------------------------------------------------------
+//
+TInt CCalenUnifiedEditor::ShowLocationChangeNoticeL()
+ {
+ TRACE_ENTRY_POINT;
+
+ CAknQueryDialog *dialog = CAknQueryDialog::NewL( );
+ CleanupStack::PushL( dialog );
+ TInt resID = R_CALEN_QTN_GEOVALUES_REMOVAL;
+
+ HBufC* prompt;
+ prompt = StringLoader::LoadLC( resID, iCoeEnv );
+ dialog->SetPromptL( *prompt );
+ CleanupStack::PopAndDestroy( prompt );
+ CleanupStack::Pop( dialog );
+
+ return dialog->ExecuteLD( R_CALEN_GEOVALUES_REMOVAL_NOTE );
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::UpdateAttachmentInfoToEditorL
+// Update attachment info to editor whenever an file is selected
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::UpdateAttachmentInfoToEditorL()
+ {
+ TRACE_ENTRY_POINT;
+ const TDesC& emptyText = KEmpty;
+ SetEdwinTextL(ECalenEditorAttachment, &emptyText);
+
+ TInt attachmentCount = iServices->GetAttachmentData()->NumberOfItems();
+ if( attachmentCount )
+ {
+ RPointerArray<CCalenAttachmentInfo> attachmentInfoList;
+ iServices->GetAttachmentData()->GetAttachmentListL(attachmentInfoList);
+
+ TInt attachmentLength(0);
+ for( TInt index =0; index<attachmentCount; index++ )
+ {
+ if(index>0)
+ {
+ attachmentLength++;
+ }
+ CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[index];
+ TParsePtrC fileNameParser( attachmentInfo->FileName() );
+ attachmentLength += fileNameParser.NameAndExt().Length();
+ }
+
+ // Additional space is for appending "; " after each attachment to separate multiple attachments
+ HBufC* attachmentNames = HBufC::NewLC( attachmentLength +
+ ( attachmentCount - 1 ) * KAttachmentSeparator.iTypeLength );
+ CleanupStack::Pop( attachmentNames );
+ TPtr ptr( attachmentNames->Des() );
+ for( TInt index=0; index<attachmentCount; index++ )
+ {
+ if( index>0 )
+ {
+ ptr.Append( KAttachmentSeparator );
+ }
+ CCalenAttachmentInfo* attachmentInfo = attachmentInfoList[index];
+ TParsePtrC fileNameParser( attachmentInfo->FileName()) ;
+ ptr.Append( fileNameParser.NameAndExt() );
+ }
+
+ SetUnderLineForAttachmentL( EUnderlineOn );
+ SetEdwinTextL( ECalenEditorAttachment, &ptr );
+ delete attachmentNames;
+
+ attachmentInfoList.Close();
+ UpdateFormL();
+ }
+
+ // Update the attachment cound in editedentryutil as attachment would have added or deleted
+ CheckForAttachmentsInEditorL();
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::SetUnderLineForAttachmentL
+// Sets the undeline for the attachment field's text
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetUnderLineForAttachmentL( TFontUnderline aUnderLine )
+ {
+ TRACE_ENTRY_POINT;
+
+ CEikRichTextEditor* attachmentControl = static_cast<CEikRichTextEditor*>(
+ Control( ECalenEditorAttachment ) );
+ TCharFormat charFormat;
+ TCharFormatMask charFormatMask;
+ charFormatMask.SetAttrib( EAttFontUnderline );
+ charFormat.iFontPresentation.iUnderline = aUnderLine;
+
+ attachmentControl->ApplyCharFormatL( charFormat,charFormatMask );
+ attachmentControl->HandleTextChangedL();
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::GetAttachmentNamesString
+// Merges individual attachment names into a single string
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::GetAttachmentNamesString( RPointerArray<HBufC>& aAttachmentNames,
+ HBufC& aAttachmentNamesString)
+ {
+ TRACE_ENTRY_POINT;
+ TInt attachmentCount = aAttachmentNames.Count();
+ TPtr ptr( aAttachmentNamesString.Des() );
+ for( TInt index=0; index<attachmentCount; index++ )
+ {
+ if( index>0 )
+ {
+ ptr.Append( KAttachmentSeparator );
+ }
+ ptr.Append( aAttachmentNames[index]->Des() );
+ }
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::CheckForAttachmentsInEditorL
+// Check for attachments in editor,if present save the attachment count which is
+// used while saving the attachments to the calentry
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::CheckForAttachmentsInEditorL()
+ {
+ TRACE_ENTRY_POINT;
+
+ TInt attachmentCount = iServices->GetAttachmentData()->NumberOfItems();
+ Edited().SetAttachmentCount( attachmentCount );
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::SetAttachmentNamesToEditorL
+// Set attachment names to the editor,if entry is already having the attachments
+// and is being opened in editor
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetAttachmentNamesToEditorL()
+ {
+ TRACE_ENTRY_POINT;
+ TInt attachmentCount = Edited().AttachmentCount();
+ if( attachmentCount )
+ {
+ RPointerArray<HBufC> attachmentNames;
+ Edited().AttachmentNamesL(attachmentNames);
+ TInt attachmentCount = attachmentNames.Count();
+ TInt attachmentLength(0);
+ for( TInt index =0; index<attachmentCount; index++ )
+ {
+ if(index>0)
+ {
+ attachmentLength++;
+ }
+
+ attachmentLength += attachmentNames[index]->Length();
+ // We need two extra spaces for adding "; " between multiple attachments
+ attachmentLength += KAttachmentSeparator.iTypeLength;
+ }
+
+ HBufC* attachmentNamesString = HBufC::NewLC( attachmentLength );
+ CleanupStack::Pop( attachmentNamesString );
+ GetAttachmentNamesString(attachmentNames, *attachmentNamesString);
+
+ SetUnderLineForAttachmentL( EUnderlineOn );
+ SetEdwinTextL( ECalenEditorAttachment, attachmentNamesString );
+
+ // Cleanup
+ delete attachmentNamesString;
+ attachmentNames.ResetAndDestroy();
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::EntryHasAttachments
+// check whether the entry has attachments or not
+// -----------------------------------------------------------------------------
+//
+TBool CCalenUnifiedEditor::EntryHasAttachments()
+ {
+ TRACE_ENTRY_POINT;
+ TBool attachmentExists(EFalse);
+ TInt attachmentCountFromModel = iServices->GetAttachmentData()->NumberOfItems();
+ if( Edited().AttachmentCount() || attachmentCountFromModel )
+ {
+ attachmentExists = ETrue;
+ }
+ TRACE_EXIT_POINT;
+
+ return attachmentExists;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenController::GetAllCollectionidsL
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::GetAllCollectionidsL(
+ RArray<TInt>& aCollectionIds)
+ {
+ TRACE_ENTRY_POINT
+ RPointerArray<CCalCalendarInfo> calendarInfoList;
+ CleanupClosePushL(calendarInfoList);
+ iServices->GetAllCalendarInfoL(calendarInfoList);
+
+ for(TInt index=0;index<calendarInfoList.Count();index++)
+ {
+ aCollectionIds.Append( iServices->SessionL(
+ calendarInfoList[index]->FileNameL() ).CollectionIdL() );
+ }
+
+ CleanupStack::PopAndDestroy(&calendarInfoList);
+ TRACE_EXIT_POINT
+ }
+// -----------------------------------------------------------------------------
+// From CEikDialog
+// We will hit this event each time a line has changed in the form
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::LineChangedL( TInt /* aControlId */ )
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalGeoValue* geoValue = iEditorDataHandler->Entry().GeoValueL();
+ if(geoValue)
+ {
+ AddPictureL();
+ delete geoValue;
+ }
+
+ SetMskFromResourceL();
+ TRACE_EXIT_POINT;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Update CBA with corresponding MSK button.
+// This function is e.g. called from HanleControlEvent()
+// Will issue HandleControlStateChangeL() call.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::SetMskFromResourceL()
+ {
+ TRACE_ENTRY_POINT;
+ CEikButtonGroupContainer& cba = ButtonGroupContainer ();
+ TInt resid=0;
+ TInt ctrlid=IdOfFocusControl();
+
+ switch( ctrlid )
+ {
+
+ // for these fields we use change button
+ case ECalenEditorReminder: /* fall through... */
+ case ECalenEditorRepeat: /* fall through... */
+
+ resid=R_CALEN_MSK_CHANGE_CBA;
+ break;
+ // for description field it is open
+ case ECalenEditorDescription:
+ // resid=R_CALEN_MSK_OPEN_CBA;
+ // break;
+ // for location field
+ case ECalenEditorPlace:
+ if(CCalenLocationUtil::IsMapProviderAvailableL())
+ {
+ resid = R_CALEN_MSK_FROMMAP_CBA;
+ }
+ else
+ {
+ resid=R_CALEN_MSK_EMPTY_CBA;
+ }
+ break;
+ // otherwise use empty MSK
+ case ECalenEditorSubject: /* fall through... */
+ case ECalenEditorReminderDate:
+ case ECalenEditorReminderTime: /* fall through... */
+ case ECalenEditorEndDate: /* fall through... */
+ case ECalenEditorEndTime:
+ case ECalenEditorDueDate:
+ case ECalenEditorStartDate:
+ case ECalenEditorStartTime:
+ case ECalenEditorBirthDayYear:
+ default:
+ resid=R_CALEN_MSK_EMPTY_CBA;
+ break;
+
+ case ECalenEditorRepeatUntil:
+ case ECalenEditorAllDayItem:
+ case ECalenEditorEventType:
+ case ECalenEditorDBName:
+ case ECalenEditorPriority:
+ resid=R_CALEN_MSK_CHANGE_CBA;
+
+ }
+
+
+ // set desired CBA
+ cba.SetCommandSetL(resid);
+ cba.DrawNow();
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::VerifyCollectionId
+// Verify if the collectionid exsists in the array of collecteids
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::VerifyCollectionIdL(const TCalCollectionId aColId)
+ {
+ TRACE_ENTRY_POINT
+ TInt errVal = KErrNotFound;
+ errVal = iCollectionIds.Find((TInt)aColId);
+ User::LeaveIfError(errVal);
+ TRACE_EXIT_POINT
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::ModifyDbField
+// modifies the DB filed in cenrep if user has edited it.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::ModifyDbField()
+ {
+ if(IsCreatingNewEntry())
+ {
+ RPointerArray<CCalCalendarInfo> calendarInfoList;
+ iServices->GetAllCalendarInfoL(calendarInfoList);
+ CleanupClosePushL( calendarInfoList );
+ TInt pos = iUnifiedEditorControl->GetCalendarIndexForEntryL();
+ TPtrC lastUsedCalendarName = calendarInfoList[pos]->FileNameL();
+ CleanupStack::PopAndDestroy( &calendarInfoList );
+
+ CRepository* cenRep = CRepository::NewLC(KCRUidCalendar);
+ User::LeaveIfError( cenRep->Set( KCalendarLastUsedCalendar, lastUsedCalendarName ) );
+ CleanupStack::PopAndDestroy( cenRep );
+ }
+ }
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::HideFieldsForEditSingleInstance
+// Hides Entry type and Calendar Field for exceptional entry/single
+// instance of recurrent entry.
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::HideFieldsForEditSingleInstance()
+ {
+ TRACE_ENTRY_POINT;
+
+ if( !IsCreatingNewEntry() )
+ {
+ if((CalenAgendaUtils::IsRepeatingL(*iOriginalCalEntry)
+ && iRepeatType == CalCommon::EThisOnly)
+ || iOriginalCalEntry->RecurrenceIdL().TimeUtcL() != Time::NullTTime())
+ {
+ //Hides Entry Type Filed
+ CCoeControl* entryTypeControl = ControlOrNull( ECalenEditorEventType );
+ if( entryTypeControl )
+ {
+ DeleteLine(ECalenEditorEventType);
+ }
+ //Hides All Day Event Field
+ CCoeControl* allDayEventControl = ControlOrNull( ECalenEditorAllDayItem );
+ if( allDayEventControl )
+ {
+ DeleteLine(ECalenEditorAllDayItem);
+ }
+ //Hides Calendar Field
+ CCoeControl* calendarControl = ControlOrNull( ECalenEditorDBName );
+ if( calendarControl )
+ {
+ DeleteLine(ECalenEditorDBName);
+ }
+ //Hides Repeat Field
+ CCoeControl* repeatControl = ControlOrNull( ECalenEditorRepeat );
+ if( repeatControl )
+ {
+ DeleteLine(ECalenEditorRepeat);
+ }
+ //Hides Repeatuntil Field
+ CCoeControl* repeatUntilControl = ControlOrNull( ECalenEditorRepeatUntil );
+ if( repeatUntilControl )
+ {
+ DeleteLine(ECalenEditorRepeatUntil);
+ }
+ }
+ }
+ UpdateFormL();
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenUnifiedEditor::AddPictureL
+// Adds Map icon onto the editors
+// -----------------------------------------------------------------------------
+//
+void CCalenUnifiedEditor::AddPictureL(TInt isNotFirstTime)
+ {
+ TRACE_ENTRY_POINT;
+
+ // Instantiate CMapIconPicture object 300x300 twips in size
+ CEikRichTextEditor* locationControl = static_cast<CEikRichTextEditor*>(Control(ECalenEditorPlace));
+
+ CRichText* text = locationControl->RichText();
+ if(isNotFirstTime)
+ {
+ TPtrC ptr = text->Read(0,text->DocumentLength());
+ TInt pos = ptr.Locate(TChar(CEditableText::EPictureCharacter));
+ if(pos != -1) // If picture found, delete it so that it cna be drawn at new place
+ {
+ TRAP_IGNORE(text->DeleteL(pos,1));
+ }
+ }
+
+ // Get the rect of the caption of ECalenEditorPlace control
+ CEikLabel* label = this->ControlCaption(ECalenEditorPlace);
+ TRect rect = label->Rect();
+
+ CMapsIconPicture* picture = new( ELeave )CMapsIconPicture(/* TSize( 300, 300 )*/ *iServices, rect );
+ CleanupStack::PushL(picture);
+ //Prepare the picture header, which will be inserted into the rich text
+ TPictureHeader header;
+ header.iPicture = TSwizzle<CPicture>(picture);
+
+ // Position where we insert picture is not valid as it always draws icon depending the rect we provide
+
+ text->InsertL(text->DocumentLength(), header);
+
+ locationControl->HandleTextChangedL();
+ CleanupStack::Pop(); // picture
+
+ Control(ECalenEditorPlace)->DrawNow();
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CMapsIconPicture::CMapsIconPicture
+// C++ Constructor
+// -----------------------------------------------------------------------------
+//
+CMapsIconPicture::CMapsIconPicture( MCalenServices& aServices, TRect aRect )
+: iServices( aServices ),
+ iRect( aRect )
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CMapsIconPicture::ExternalizeL
+// Pure virtual from CPicture, intentionally empty.
+// -----------------------------------------------------------------------------
+//
+void CMapsIconPicture::ExternalizeL( RWriteStream& /*aStream*/ ) const
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CMapsIconPicture::GetOriginalSizeInTwips
+// Convert size to twips
+// -----------------------------------------------------------------------------
+//
+void CMapsIconPicture::GetOriginalSizeInTwips( TSize & /* aSize */ ) const
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CMapsIconPicture::Draw
+// Draw funtion to draw the map icon
+// -----------------------------------------------------------------------------
+//
+void CMapsIconPicture::Draw( CGraphicsContext& aGc,
+ const TPoint& /* aTopLeft */,
+ const TRect& /* aClipRect */,
+ MGraphicsDeviceMap* /* aMap */) const
+ {
+ TRACE_ENTRY_POINT;
+
+ aGc.Reset();
+
+ // Create the icon
+ CGulIcon* icon = NULL;
+ PIM_TRAPD_HANDLE( icon = iServices.GetIconL( MCalenServices::ECalenMapIcon ) );
+
+ TAknLayoutRect icon_layout_rect;
+ icon_layout_rect.LayoutRect( iRect, AknLayoutScalable_Apps::field_cale_ev_pane_g1( 0 ).LayoutLine() );
+ TRect area = icon_layout_rect.Rect();
+ AknIconUtils::SetSize( icon->Bitmap(), area.Size() );
+
+ aGc.DrawBitmapMasked( area, icon->Bitmap(), area.Size(), icon->Mask(), ETrue );
+ delete icon;
+
+ TRACE_EXIT_POINT;
+ }
+// End of file
+