diff -r 000000000000 -r e686773b3f54 phonebookui/Phonebook2/CommandsExtension/src/CPbk2SendMessageCmd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/CommandsExtension/src/CPbk2SendMessageCmd.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,814 @@ +/* +* Copyright (c) 2005-2007 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: Phonebook 2 send message command. +* +*/ + + +// INCLUDE FILES +#include "CPbk2SendMessageCmd.h" + +// Phonebook 2 +#include "MPbk2ProcessDecorator.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Virtual Phonebook +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// System includes +#include +#include +#include +#include +#include +#include +#include +#include + +// Debugging headers +#include + +/// Unnamed namespace for local definitions +namespace { + +const TInt KDefaultTitleFormat = MPbk2ContactNameFormatter::EUseSeparator; +const TInt KGranularity( 4 ); + +#ifdef _DEBUG + +enum TPanicCode + { + EPanicUnknownMedia = 1, + ERunL_InvalidState, + EPanicLogic, + EPanicNullPointer + }; + +void Panic( TPanicCode aReason ) + { + _LIT( KPanicText, "CPbk2SendMessageCmd" ); + User::Panic( KPanicText, aReason ); + } +#endif //_DEBUG + +} /// namespace + + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::CPbk2SendMessageCmd +// -------------------------------------------------------------------------- +// +CPbk2SendMessageCmd::CPbk2SendMessageCmd( + MPbk2ContactUiControl& aUiControl ) : + CActive( EPriorityIdle ), + iUiControl( &aUiControl ), + iRecipientCount( 0 ), + iFocusedFieldIndex( aUiControl.FocusedFieldIndex() ) + { + CActiveScheduler::Add( this ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::~CPbk2SendMessageCmd +// -------------------------------------------------------------------------- +// +CPbk2SendMessageCmd::~CPbk2SendMessageCmd() + { + Cancel(); + if( iUiControl ) + { + iUiControl->RegisterCommand( NULL ); + } + + delete iAttachmentFile; + delete iMessageData; + delete iSelectedContacts; + + delete iMtmFilter; + delete iRetrieveOperation; + delete iStoreContact; + delete iSendUi; + Release( iAppServices ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::NewL +// -------------------------------------------------------------------------- +// +CPbk2SendMessageCmd* CPbk2SendMessageCmd::NewL( + MPbk2ContactUiControl& aUiControl ) + { + CPbk2SendMessageCmd* self = + new ( ELeave ) CPbk2SendMessageCmd( aUiControl ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); // self + return self; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::ConstructL +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::ConstructL() + { + CPbk2DriveSpaceCheck* driveSpaceCheck = CPbk2DriveSpaceCheck::NewL + ( CCoeEnv::Static()->FsSession() ); + CleanupStack::PushL( driveSpaceCheck ); + // check FFS situation + driveSpaceCheck->DriveSpaceCheckL(); + CleanupStack::PopAndDestroy( driveSpaceCheck ); + + iSendUi = CSendUi::NewL(); + iAppServices = CPbk2ApplicationServices::InstanceL(); + + iFieldPropertyArray = &(iAppServices->FieldProperties()); + + iMtmFilter = new ( ELeave ) CArrayFixFlat( KGranularity ); + iSendingCapabilities.iFlags = TSendingCapabilities::ESupportsEditor; + iSelectedContacts = iUiControl->SelectedContactsOrFocusedContactL(); + __ASSERT_DEBUG(iSelectedContacts, Panic(EPanicNullPointer)); + iMessageData = CMessageData::NewL(); + iUiControl->RegisterCommand( this ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::ExecuteLD +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::ExecuteLD() + { + iCurrentContactLinkIndex = 0; + iState = EShowWriteQuery; + IssueRequest(); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::AddObserver +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::AddObserver( MPbk2CommandObserver& aObserver) + { + iCommandObserver = &aObserver; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::ResetUiControl +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::ResetUiControl( + MPbk2ContactUiControl& aUiControl) + { + if (iUiControl == &aUiControl) + { + iUiControl = NULL; + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::SetMtmUid +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::SetMtmUid( TUid aUid ) + { + iMtmUid = aUid; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::RunL +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::RunL() + { + switch (iState) + { + case ERetrieving: + { + if ( iSelectedContacts->Count() == iCurrentContactLinkIndex ) + { + iState = EStarting; + IssueRequest(); + } + else + { + RetrieveContactL( iSelectedContacts->At( + iCurrentContactLinkIndex ) ); + iCurrentContactLinkIndex++; + } + break; + } + + case EShowWriteQuery: + { + // No need to query message type if it's already known + if( iMtmUid == KNullUid ) + { + iMtmUid = ShowWriteQueryL(); + } + + if ( iMtmUid == KNullUid ) + { + IssueStopRequest( KErrCancel ); + } + else + { + iState = ERetrieving; + IssueRequest(); + } + break; + } + + case EResolveURL: + { + ResolveUrlL(); + break; + } + + case EStarting: + { + DoSendMessageL(); + break; + } + + case EStopping: + { + ProcessDismissed( KErrNone ); + break; + } + + default: + { + __ASSERT_DEBUG( EFalse, Panic( ERunL_InvalidState ) ); + break; + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::DoCancel +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::DoCancel() + { + // Do nothing + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::RunError +// -------------------------------------------------------------------------- +// +TInt CPbk2SendMessageCmd::RunError( TInt aError ) + { + return FilterErrors( aError ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::VPbkSingleContactOperationComplete +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::VPbkSingleContactOperationComplete + ( MVPbkContactOperationBase& /*aOperation*/, + MVPbkStoreContact* aContact ) + { + delete iRetrieveOperation; + iRetrieveOperation = NULL; + + // We now have a store contact + delete iStoreContact; + iStoreContact = aContact; + + iState = EResolveURL; + IssueRequest(); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::VPbkSingleContactOperationFailed +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::VPbkSingleContactOperationFailed + ( MVPbkContactOperationBase& /*aOperation*/, TInt aError ) + { + delete iRetrieveOperation; + iRetrieveOperation = NULL; + + // We cannot get the contact, so we have to + // fail. We cannot continue, since this operation + // was executed only in case of one contact. + ProcessDismissed( aError ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::ShowWriteQueryL +// -------------------------------------------------------------------------- +// +TUid CPbk2SendMessageCmd::ShowWriteQueryL() + { + if ( iSelectedContacts->Count() > 1 ) + { + iMtmFilter->AppendL(KSenduiMtmPostcardUid); // hide postcard + } + TUid uid = iSendUi->ShowTypedQueryL( CSendUi::EWriteMenu, NULL, + iSendingCapabilities, iMtmFilter ); + return uid; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::RetrieveContactL +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::RetrieveContactL + ( const MVPbkContactLink& aContactLink ) + { + // Retrieve the actual store contact from the given link + iRetrieveOperation = iAppServices-> + ContactManager().RetrieveContactL( aContactLink, *this ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::DoSendMessageL +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::DoSendMessageL() + { + PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING + ("CPbk2SendMessageCmd::DoSendMessageL() start") ); + + iSendUi->CreateAndSendMessageL( iMtmUid, iMessageData ); + + iState = EStopping; + IssueRequest(); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::ResolveUrlL +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::ResolveUrlL() + { + if ( iMtmUid == KSenduiMtmPostcardUid ) + { + // Send post card + SendPostCardL(); + iState = EStarting; + IssueRequest(); + } + else + { + TUid techTypeUid = iSendUi->TechnologyType( iMtmUid ); + + RVPbkContactFieldDefaultPriorities defaults; + CleanupClosePushL( defaults ); + + // Prepare address select + TInt resourceId = PrepareAddressSelectL( defaults, techTypeUid ); + + if ( resourceId > KErrNotFound ) + { + MVPbkStoreContactField* selectedField = + SelectFieldL( resourceId, defaults ); + + if ( !selectedField ) + { + CPbk2AppUiBase& appUi = static_cast&> + ( *CEikonEnv::Static()->EikAppUi() ); + + if ( appUi.IsForeground() ) + { + if ( iSelectedContacts->Count() == iCurrentContactLinkIndex + && iRecipientCount == 0 ) + { + // This is the last contact and there are + // no recipients, stop + IssueStopRequest( KErrNone ); + } + else + { + // If this is not the last contact or if there are + // recipients, go on + iState = ERetrieving; + IssueRequest(); + } + } + else + { + // If appUi is not in the foreground, + // It means Phonebook2 has hidden itself in background. + // All active commands should be stopped so that names list view is to be activated + // and no other views will be shown when re-entering Phonebook2 + IssueStopRequest( KErrNone ); + } + } + else + { + CleanupDeletePushL( selectedField ); + SetAddressFromFieldL( *selectedField ); + CleanupStack::PopAndDestroy(); // selectedField + + iState = ERetrieving; + IssueRequest(); + } + } + + CleanupStack::PopAndDestroy(); // defaults + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::PrepareAddressSelectL +// -------------------------------------------------------------------------- +// +inline TInt CPbk2SendMessageCmd::PrepareAddressSelectL + ( RVPbkContactFieldDefaultPriorities& aPriorities, + TUid aTechType ) + { + // Precondition + __ASSERT_DEBUG( iMtmUid != KNullUid, Panic( EPanicUnknownMedia) ); + + TInt resourceId = KErrNotFound; + + // SMS + if ( iMtmUid == KSenduiMtmSmsUid || + aTechType == KSenduiTechnologySmsUid ) + { + if ( FeatureManager::FeatureSupported( KFeatureIdEmailOverSms ) ) + { + resourceId = R_PBK2_EMAIL_OVER_SMS_ADDRESS_SELECT; + User::LeaveIfError( aPriorities.Append + ( EVPbkDefaultTypeEmailOverSms ) ); + } + else + { + resourceId = R_PBK2_PHONE_NUMBER_SELECT; + User::LeaveIfError( aPriorities.Append( EVPbkDefaultTypeSms ) ); + } + } + // MMS & Audio message + // Audio Messaging uses same address select as MMS for now + else if ( iMtmUid == KSenduiMtmMmsUid || + iMtmUid == KSenduiMtmAudioMessageUid || + aTechType == KSenduiTechnologyMmsUid ) + { + resourceId = R_PBK2_MMS_ADDRESS_SELECT; + User::LeaveIfError( aPriorities.Append( EVPbkDefaultTypeMms ) ); + } + // E-mail + else if ( iMtmUid == KSenduiMtmSmtpUid || + aTechType == KSenduiTechnologyMailUid ) + { + resourceId = R_PBK2_EMAIL_ADDRESS_SELECT; + User::LeaveIfError( aPriorities.Append( EVPbkDefaultTypeEmail ) ); + } + // Unified message + else if ( iMtmUid == KSenduiMtmUniMessageUid ) + { + if ( FeatureManager::FeatureSupported( KFeatureIdMMS ) ) + { + if (iAppServices->LocallyVariatedFeatureEnabled( + EVPbkLVShowEmailInSendMsg )) + { + resourceId = R_PBK2_UNIFIED_EDITOR_MMS_ADDRESS_SELECT; + } + else + { + resourceId = R_PBK2_UNIFIED_EDITOR_PHONE_NUMBER_SELECT; + } + User::LeaveIfError( aPriorities.Append( EVPbkDefaultTypeMms ) ); + } + + if ( FeatureManager::FeatureSupported + ( KFeatureIdEmailOverSms ) ) + { + if ( resourceId == KErrNotFound ) + { + resourceId = + R_PBK2_UNIFIED_EDITOR_EMAIL_OVER_SMS_ADDRESS_SELECT; + } + // Include SMS default always in unified message, + // in addition unified message has MMS default included + // with higher priority + User::LeaveIfError( aPriorities.Append + ( EVPbkDefaultTypeEmailOverSms ) ); + } + else + { + if ( resourceId == KErrNotFound ) + { + resourceId = R_PBK2_UNIFIED_EDITOR_PHONE_NUMBER_SELECT; + } + // Include SMS default always in unified message, + // in addition it has MMS default included with higher priority + User::LeaveIfError( aPriorities.Append( EVPbkDefaultTypeSms ) ); + } + } + + // Postcondition + __ASSERT_DEBUG( resourceId != KErrNotFound, Panic( EPanicLogic) ); + + return resourceId; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::SetAddressFromFieldL +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::SetAddressFromFieldL + ( MVPbkStoreContactField& aField ) + { + HBufC* address = MVPbkContactFieldTextData::Cast( aField.FieldData()). + Text().AllocL(); + CleanupStack::PushL( address ); + + if ( address && address->Des().Length() > 0 ) + { + HBufC* nameBuffer = iAppServices->NameFormatter(). + GetContactTitleL( + static_cast( + iStoreContact->Fields() ), + KDefaultTitleFormat); + CleanupStack::PushL( nameBuffer ); + const TDesC& unnamed = iAppServices->NameFormatter().UnnamedText(); + if ( unnamed == ( *nameBuffer ) ) + { + iMessageData->AppendToAddressL( *address ); + } + else + { + iMessageData->AppendToAddressL( *address, *nameBuffer ); + } + ++iRecipientCount; + CleanupStack::PopAndDestroy(); // nameBuffer + } + CleanupStack::PopAndDestroy( address ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::ProcessDismissed +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::ProcessDismissed( TInt aCancelCode ) + { + if ( iAttachmentFile ) + { + // No error checking, exiting Phonebook would + // be too much for this error + CCoeEnv::Static()->FsSession().Delete( iAttachmentFile->FileName() ); + } + + if ( aCancelCode != KErrCancel && iUiControl) + { + TRAPD( err, + iUiControl->ResetFindL(); + // Keep focus in contact + if ( iStoreContact ) + { + if ( iFocusedFieldIndex != KErrNotFound ) + { + iUiControl->SetFocusedFieldIndex( iFocusedFieldIndex ); + } + iUiControl->SetFocusedContactL( *iStoreContact ); + } + TUid titlePaneUid; + titlePaneUid.iUid = EEikStatusPaneUidTitle; + CEikStatusPane *statusPane = ((CAknAppUi*)CEikonEnv::Static()->EikAppUi())->StatusPane(); + CEikStatusPaneBase::TPaneCapabilities subPane = + statusPane->PaneCapabilities(titlePaneUid); + + if (subPane.IsPresent()&&subPane.IsAppOwned()) + { + CAknTitlePane* titlePane = + (CAknTitlePane *)statusPane->ControlL(titlePaneUid); + HBufC* titlePaneText = StringLoader::LoadLC(R_QTN_PHOB_TITLE); + titlePane->SetTextL(*titlePaneText); + + CleanupStack::PopAndDestroy(titlePaneText); + } + ); // TRAPD + iUiControl->UpdateAfterCommandExecution(); + if (err != KErrNone) + { + CCoeEnv::Static()->HandleError(err); + } + } + + // Notify command owner that the command has finished + if (iCommandObserver) + { + iCommandObserver->CommandFinished( *this ); + } + + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::FilterErrors +// -------------------------------------------------------------------------- +// +TInt CPbk2SendMessageCmd::FilterErrors( TInt aErrorCode ) + { + PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING + ( "CPbk2SendMessageCmd::FilterErrors(%d) start" ), aErrorCode ); + + TInt result = aErrorCode; + switch (aErrorCode) + { + case KErrNotFound: // FALLTHROUGH + case KErrInUse: + { + // Ignore these errors + // KErrNotFound means that somebody got the contact first + // KErrInUse means that the contact is open + result = KErrNone; + break; + } + + default: // Something more serious happened -> give up + { + Cancel(); + ProcessDismissed( aErrorCode ); + break; + } + } + + PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING + ( "CPbk2SendMessageCmd::FilterErrors(%d) end" ), result ); + + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::IssueRequest +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::IssueRequest() + { + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + SetActive(); + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::IssueStopRequest +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::IssueStopRequest( TInt aErrorCode ) + { + iState = EStopping; + + if ( aErrorCode != KErrNone ) + { + ProcessDismissed( aErrorCode ); + } + + if (!IsActive()) + { + IssueRequest(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::ToStoreFieldIndexL +// -------------------------------------------------------------------------- +// +TInt CPbk2SendMessageCmd::ToStoreFieldIndexL( TInt aPresIndex ) + { + TInt index( KErrNotFound ); + CPbk2PresentationContact* presentationContact = + CPbk2PresentationContact::NewL( + *iStoreContact, iAppServices->FieldProperties() ); + CleanupStack::PushL( presentationContact ); + + index = presentationContact->PresentationFields().StoreIndexOfField + ( aPresIndex ); + + CleanupStack::PopAndDestroy( presentationContact ); + + return index; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::SelectFieldL +// -------------------------------------------------------------------------- +// +MVPbkStoreContactField* CPbk2SendMessageCmd::SelectFieldL( + TUint aResourceId, + RVPbkContactFieldDefaultPriorities& aPriorities ) + { + TResourceReader resReader; + CCoeEnv::Static()->CreateResourceReaderLC( resReader, aResourceId ); + + TPbk2AddressSelectParams params + ( *iStoreContact, + iAppServices->ContactManager(), + iAppServices->NameFormatter(), + *iFieldPropertyArray, resReader ); + + // Set focused field if we are in contact info + TInt fieldIndex = KErrNotFound; + if (iUiControl) + { + fieldIndex = iUiControl->FocusedFieldIndex(); + } + MVPbkStoreContactField* focusedField = NULL; + if ( fieldIndex != KErrNotFound ) + { + focusedField = iStoreContact->Fields().FieldAtLC + ( ToStoreFieldIndexL( fieldIndex ) ); + } + else + { + // We are in names list and we should use the default value + // directly if available + params.SetUseDefaultDirectly( ETrue ); + } + + params.SetFocusedField( focusedField ); + params.SetDefaultPriorities( aPriorities ); + + params.iCommMethod = VPbkFieldTypeSelectorFactory::EUniEditorSelector; + CVPbkFieldTypeSelector* actionTypeSelector = + VPbkFieldTypeSelectorFactory::BuildContactActionTypeSelectorL( + VPbkFieldTypeSelectorFactory::EUniEditorSelector, + Phonebook2::Pbk2AppUi()->ApplicationServices().ContactManager().FieldTypes()); + + CleanupStack::PushL( actionTypeSelector ); + + // Run address select + CPbk2AddressSelect* addressSelect = CPbk2AddressSelect::NewL( + params, + *actionTypeSelector, + NULL, + NULL ); + + MVPbkStoreContactField* selectedField = addressSelect->ExecuteLD(); + + if ( focusedField ) + { + CleanupStack::PopAndDestroy(); // focusedField + } + CleanupStack::PopAndDestroy( 2 ); // actionTypeSelector, resReader + + return selectedField; + } + +// -------------------------------------------------------------------------- +// CPbk2SendMessageCmd::SendPostCardL +// -------------------------------------------------------------------------- +// +void CPbk2SendMessageCmd::SendPostCardL() + { + // Create attachment file object + delete iAttachmentFile; + iAttachmentFile = NULL; + HBufC* attFileName = StringLoader::LoadLC + ( R_PBK2_POSTCARD_WRITE_ATTACHMENT_TAG ); + iAttachmentFile = CPbk2AttachmentFile::NewL + ( *attFileName, CCoeEnv::Static()->FsSession(), + EFileWrite|EFileShareAny ); + CleanupStack::PopAndDestroy( attFileName ); + + HBufC8* buf = iSelectedContacts->PackLC(); + iAttachmentFile->File().Write( *buf ); + CleanupStack::PopAndDestroy( buf ); + + iMessageData->AppendAttachmentL( iAttachmentFile->FileName() ); + iAttachmentFile->Release(); + } + +// End of File