diff -r 5b6f26637ad3 -r f4a778e096c2 phonebookui/Phonebook2/CommandsExtension/src/CPbk2SendContactCmd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/CommandsExtension/src/CPbk2SendContactCmd.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,1335 @@ +/* +* 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 contact command. +* +*/ + + +#include "CPbk2SendContactCmd.h" + +// Phonebook 2 +#include "Pbk2SendCmdUtils.h" +#include "CPbk2vCardConverter.h" +#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 +#include +#include +#include +#include + +// Debugging headers +#include + +/// Unnamed namespace for local definitions +namespace { + +const TUint KNoMenu = 0; +const TInt KGranularity( 4 ); + +struct TPbk2SelectionMapping + { + /// Maps to first selection + TPbk2SendvCardChoiceItemEnumerations iStSelection; + /// Maps to second selection + TPbk2SendvCardChoiceItemEnumerations iNdSelection; + /// Maps to third selection + TPbk2SendvCardChoiceItemEnumerations iRdSelection; + //// Resource id + TInt iResId; + }; + +enum TSelection + { + ESelectionLast = -1 + }; + +/// Maps listbox index selections to 'sending selected detail' +/// menu selections If command not supported selection is ECancel. +static const TPbk2SelectionMapping SelectionMapping[] = + { + {ESendCurrentItem, ESendAllData, ECancel, + R_PBK2_CONTACTINFO_SEND_OPTIONS}, + {ESendCurrentItem, ESendAllDataWithoutPicture, ESendAllData, + R_PBK2_CONTACTINFO_SEND_OPTIONS_SMS_THUMBNAIL}, + {ESendAllDataWithoutPicture, ESendAllData, ECancel, + R_PBK2_CONTACTINFO_SEND_OPTIONS_SMS_THUMBNAIL_NO_FIELD}, + {ESendAllDataWithoutPicture, ESendAllData, ECancel, + R_PHONEBOOK2_SEND_OPTIONS}, + {ECancel, ECancel, ECancel, ESelectionLast} + }; + + +/// Represents the different listbox index selections. +enum TPbk2ListBoxSelections + { + EFirstSelection = 0, + ESecondSelection, + EThirdSelection + }; + +#if 0 // Not used in ECE +/** + Function checks if the focused field is one of these fields. + + - Prefix + - Suffix + - Firstname + JAPANESE.PRONOUNCIATION{ + - FirstnameReading + }JAPANESE.PRONOUNCIATION + - Middle name + - Lastname + JAPANESE.PRONOUNCIATION{ + - Last name Reading + }JAPANESE.PRONOUNCIATION + - Ringing tone + CALL.OBJECT.DISPLAY{ + - Image + }CALL.OBJECT.DISPLAY + CALL.OBJECT.DISPLAY{ + - Text for call + }CALL.OBJECT.DISPLAY + - Synchronization +*/ +TBool IsNameOrPropertyField( const MVPbkBaseContactField& aField ) + { + TBool res ( EFalse ); + const MVPbkFieldType* fieldType = aField.BestMatchingFieldType(); + if ( fieldType ) + { + TInt resId( fieldType->FieldTypeResId() ); + if ( resId == R_VPBK_FIELD_TYPE_PREFIX || + resId == R_VPBK_FIELD_TYPE_SUFFIX || + resId == R_VPBK_FIELD_TYPE_FIRSTNAME || + resId == R_VPBK_FIELD_TYPE_FIRSTNAMEREADING || + resId == R_VPBK_FIELD_TYPE_MIDDLENAME || + resId == R_VPBK_FIELD_TYPE_LASTNAME || + resId == R_VPBK_FIELD_TYPE_LASTNAMEREADING || + resId == R_VPBK_FIELD_TYPE_RINGTONE || + resId == R_VPBK_FIELD_TYPE_CALLEROBJIMG || + resId == R_VPBK_FIELD_TYPE_CALLEROBJTEXT || + resId == R_VPBK_FIELD_TYPE_SYNCCLASS ) + { + res = ETrue; + } + } + return res; + } +#endif // 0 + +#ifdef _DEBUG + +enum TPanicCode + { + EPanicPreCond_SendvCardsL = 1, + EPanicLogic_CmdSendContactDataL, + EPanicLogic_MapSelection, + EPanicLogic_ConversionDone, + EPanicLogic_ReadFileTypeL, + ERunL_OOB, + EPanicPreCond_ErrArgument, + EResetFindResult + }; + +void Panic(TPanicCode aReason) + { + _LIT(KPanicText, "CPbk2SendContactCmd"); + User::Panic(KPanicText,aReason); + } + +#endif // _DEBUG + + +/** + * Helper class for sending the vCard(s) in async callback. + */ +NONSHARABLE_CLASS(CVCardSender) : public CIdle + { + public: // Constructor + + /** + * Creates a new instance of this object. + * + * @param aPriority Desired priority. + */ + static CVCardSender* NewL( + TInt aPriority ); + + private: // From CIdle + void RunL(); + TInt RunError( + TInt aError ); + + private: // Implementation + CVCardSender( + TInt aPriority ); + }; + +// -------------------------------------------------------------------------- +// CVCardSender::CVCardSender +// -------------------------------------------------------------------------- +// +inline CVCardSender::CVCardSender( TInt aPriority ): + CIdle( aPriority ) + { + CActiveScheduler::Add( this ); + } + +// -------------------------------------------------------------------------- +// CVCardSender::NewL +// -------------------------------------------------------------------------- +// +CVCardSender* CVCardSender::NewL( TInt aPriority ) + { + return new ( ELeave ) CVCardSender( aPriority ); + } + +// -------------------------------------------------------------------------- +// CVCardSender::RunL +// -------------------------------------------------------------------------- +// +void CVCardSender::RunL() + { + CIdle::RunL(); + // Destroy self. + // If RunL (the callback) leaves RunError will handle the deletion. + delete this; + } + +// -------------------------------------------------------------------------- +// CVCardSender::RunError +// -------------------------------------------------------------------------- +// +TInt CVCardSender::RunError( TInt aError) + { + delete this; + // Forward all errors to the active scheduler + return aError; + } + +/** + * Creates a rich text object and packages contents of a file to it. + * The file's data is not converted in any way except that characters + * are widened to 16 bits. + * + * @param aEikEnv EIKON environment. + * @param aFileName Name of the file to convert. + * @return A new rich text object with file's contents. + * The returned object is also left on top of the cleanup stack. + */ +CRichText* CreateRichTextFromFileLC + (CEikonEnv& aEikEnv, const TDesC& aFileName) + { + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CreateRichTextFromFileLC (%S)"), &aFileName); + // Common allocation granularity and buffer size for rich text and + // file reading + const TInt KBufSize = CEditableText::EDefaultTextGranularity; + + // Create a rich text object with default formatting + CRichText* richText = CRichText::NewL( + aEikEnv.SystemParaFormatLayerL(), + aEikEnv.SystemCharFormatLayerL(), + CEditableText::ESegmentedStorage, + KBufSize // Allocation granularity + ); + CleanupStack::PushL(richText); + + // Open the file for reading + RFile file; + User::LeaveIfError(file.Open + (aEikEnv.FsSession(), aFileName, + EFileRead|EFileStream|EFileShareReadersOnly)); + CleanupClosePushL(file); + + // Create two buffers: 8-bit for reading from file and 16-bit for + // converting to 16-bit format + HBufC8* buf8 = HBufC8::NewLC(KBufSize); + TPtr8 ptr8 = buf8->Des(); + HBufC16* buf16 = HBufC16::NewLC(ptr8.MaxLength()); + TPtr16 ptr16 = buf16->Des(); + + // Read, convert and append to rich text until the file ends + for (TInt err = file.Read(ptr8); + ptr8.Length() > 0; + err = file.Read(ptr8)) + { + User::LeaveIfError(err); + ptr16.Copy(ptr8); + richText->InsertL(richText->DocumentLength(), ptr16); + } + + // Cleanup and return + CleanupStack::PopAndDestroy(3); // buf16, buf8, file + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CreateRichTextFromFileLC, end")); + return richText; + } + +} /// namespace + +/** + * Sending parameters. + */ +class TPbk2SendingParams + { + public: // Construction and destruction + + /** + * Constructor. + * + * @param aMtmFilter MTM filter + * @param aCapabilities Sending capabilities. + */ + TPbk2SendingParams( + CArrayFixFlat* aMtmFilter, + TSendingCapabilities aCapabilities ); + + public: // Data + /// Ref: MTM filter + CArrayFixFlat* iMtmFilter; + /// Own: Sending capabilities + TSendingCapabilities iCapabilities; + }; + +// -------------------------------------------------------------------------- +// TPbk2SendingParams::TPbk2SendingParams +// -------------------------------------------------------------------------- +// +inline TPbk2SendingParams::TPbk2SendingParams + ( CArrayFixFlat* aMtmFilter, + TSendingCapabilities aCapabilities ) : + iMtmFilter( aMtmFilter ), iCapabilities( aCapabilities ) + { + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::CPbk2SendContactCmd +// -------------------------------------------------------------------------- +// +inline CPbk2SendContactCmd::CPbk2SendContactCmd( + MPbk2ContactUiControl& aUiControl ) : + CActive(EPriorityIdle), + iUiControl(&aUiControl) + { + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::~CPbk2SendContactCmd +// -------------------------------------------------------------------------- +// +CPbk2SendContactCmd::~CPbk2SendContactCmd() + { + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CPbk2SendContactCmd, destructor (0x%x)"), this); + Cancel(); + if( iUiControl ) + { + iUiControl->RegisterCommand( NULL ); + } + + delete iWaiter; + delete iSelectedContacts; + delete iConverter; + delete iVCardSender; + delete iVCardEngine; + iStoreContacts.ResetAndDestroy(); + iStoreContacts.Close(); + delete iRetrieveOperation; + delete iDecorator; + delete iCntIterator; + delete iSendUi; + Release( iAppServices ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::NewL +// -------------------------------------------------------------------------- +// +CPbk2SendContactCmd* CPbk2SendContactCmd::NewL + (MPbk2ContactUiControl& aUiControl) + { + CPbk2SendContactCmd* self = new (ELeave)CPbk2SendContactCmd(aUiControl); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ConstructL +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ConstructL() + { + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CPbk2SendContactCmd::ConstructL(0x%x)"), this); + CActiveScheduler::Add(this); + CPbk2DriveSpaceCheck* driveSpaceCheck = CPbk2DriveSpaceCheck::NewL + ( CCoeEnv::Static()->FsSession() ); + CleanupStack::PushL( driveSpaceCheck ); + // check FFS situation + driveSpaceCheck->DriveSpaceCheckL(); + CleanupStack::PopAndDestroy( driveSpaceCheck ); + iEikEnv = CEikonEnv::Static(); + iAppServices = CPbk2ApplicationServices::InstanceL(); + iVCardEngine = CVPbkVCardEng::NewL( iAppServices->ContactManager() ); + iConverter = CPbk2vCardConverter::NewL( + iEikEnv->FsSession(), + iAppServices->ContactManager(), + *iVCardEngine, + iAppServices->NameFormatter() ); + iVCardSender = CVCardSender::NewL(CActive::EPriorityIdle); + iSendUi = CSendUi::NewL(); + + if( iUiControl ) + { + // Use iterator to make sure that OOM situation does not occur + // if multiple contacts selected. + iCntIterator = iUiControl->SelectedContactsIteratorL(); + if ( !iCntIterator ) + { + // If no iterator, there is no selected contacts. + // Only one contact is returned. + iSelectedContacts = iUiControl->SelectedContactsOrFocusedContactL(); + } + iFocusedField = iUiControl->FocusedField(); + iUiControl->RegisterCommand( this ); + } + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CPbk2SendContactCmd::ConstructL, end")); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ExecuteLD +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ExecuteLD() + { + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CPbk2SendContactCmd::ExecuteLD(0x%x)"), this); + + CleanupStack::PushL(this); + + iCurrentContactLinkIndex = 0; + iState = EShowingSendQuery; + IssueRequest(); + + CleanupStack::Pop(this); + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CPbk2SendContactCmd::ExecuteLD, end"), this); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::AddObserver +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::AddObserver(MPbk2CommandObserver& aObserver) + { + iCommandObserver = &aObserver; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ResetUiControl +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ResetUiControl( + MPbk2ContactUiControl& aUiControl) + { + if (iUiControl == & aUiControl) + { + iUiControl = NULL; + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::RunL +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::RunL() + { + switch (iState) + { + case EShowingSendQuery: + { + iMtmUid = ShowSendQueryL(); + if (iMtmUid == KNullUid) + { + iState = ECancelling; + } + else + { + iState = ERetrievingContact; + } + IssueRequest(); + break; + } + + case ERetrievingContact: + { + if ( iSelectedContacts ) + { + __ASSERT_DEBUG( iSelectedContacts->Count() > + iCurrentContactLinkIndex, Panic( ERunL_OOB ) ); + RetrieveContactL(iSelectedContacts->At + (iCurrentContactLinkIndex)); + } + else + { + iState = ESelectingSentData; + IssueRequest(); + } + break; + } + + case ESelectingSentData: + { + TInt selection(ESendAllData); + if ( iSelectedContacts ) + { + // If there is only one contact or launched in info view + // do the data selection + selection = SelectSentDataL(); + } + ConvertContactL(selection); + break; + } + + case EStopping: + { + ProcessDone(KErrNone); + break; + } + + case ECancelling: + { + ProcessDone( KErrCancel ); + break; + } + case EReleaseResource: + { + CPbk2AttachmentFileArray& fileArray = iConverter->AttachmentFileArray(); + TInt count = fileArray.Count(); + TInt deleteIndex = count -1; + CPbk2AttachmentFile * file = fileArray.At(deleteIndex); + fileArray.Delete(deleteIndex); + delete file; + + if ( count > 1) + { + IssueRequest(); + } + else + { + iWaiter->AsyncStop(); + } + break; + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::RunError +// -------------------------------------------------------------------------- +// +TInt CPbk2SendContactCmd::RunError(TInt aError) + { + if( iWaiter && iWaiter->IsStarted() ) + iWaiter->AsyncStop(); + + return FilterErrors(aError); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::DoCancel +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::DoCancel() + { + if( iWaiter && iWaiter->IsStarted() ) + iWaiter->AsyncStop(); + + delete iRetrieveOperation; + iRetrieveOperation = NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ConversionDone +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ConversionDone( TInt PBK2_DEBUG_ONLY( aCount ) ) + { + PBK2_DEBUG_PRINT + ( PBK2_DEBUG_STRING( "CPbk2SendContactCmd::ConversionDone(0x%x)" ), + this ); + + __ASSERT_DEBUG( iStoreContacts.Count() == aCount, + Panic( EPanicLogic_ConversionDone ) ); + + // Decorator will call processdismissed which will continue + // contact send + iDecorator->ProcessStopped(); + + PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING + ( "CPbk2SendContactCmd::ConversionDone(0x%x), end" ), this ); + + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ConversionError +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ConversionError(TInt aError) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::ConversionError(%d)"), aError); + + // Report the failure to the user + CCoeEnv::Static()->HandleError( aError ); + + // iDecorator calls processdismissed + iDecorator->ProcessStopped(); + iState = EStopping; + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::ConversionError(0x%x), end"), this); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::VPbkSingleContactOperationComplete +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::VPbkSingleContactOperationComplete( + MVPbkContactOperationBase& aOperation, MVPbkStoreContact* aContact) + { + if (&aOperation == iRetrieveOperation) + { + delete iRetrieveOperation; + iRetrieveOperation = NULL; + + // We now have a store contact + TInt error = iStoreContacts.Append(aContact); + if ( error == KErrNone ) + { + ++iCurrentContactLinkIndex; + if (iSelectedContacts->Count() == iCurrentContactLinkIndex) + { + iCurrentContactLinkIndex = 0; + iState = ESelectingSentData; + } + else + { + iState = ERetrievingContact; + } + + IssueRequest(); + } + else + { + ProcessDone( error ); + } + } + else + { + IssueStopRequest(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::VPbkSingleContactOperationFailed +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::VPbkSingleContactOperationFailed( + MVPbkContactOperationBase& aOperation, TInt aError) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::VPbkSingleContactOperationFailed (%d)"), aError); + if (&aOperation == iRetrieveOperation) + { + 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. + ProcessDone(aError); + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::SendvCardsLD +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::SendvCardsLD() + { + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CPbk2SendContactCmd::SendvCardsLD(0x%x)"), this); + // Relinquish ownership, iVCardSender takes care of it self + iVCardSender = NULL; + + CMessageData* messageData = CMessageData::NewL(); + CleanupStack::PushL( messageData ); + + if (iConverter->FileNames().MdcaCount() > 0 && + !iUnderDestruction) + { + TSendingCapabilities caps; + User::LeaveIfError( + iSendUi->ServiceCapabilitiesL( iMtmUid, caps ) ); + if (caps.iFlags & TSendingCapabilities::ESupportsAttachments) + { + // Not sending through SMS, just pass the attachments + __ASSERT_DEBUG(iConverter->FileNames().MdcaCount()>=1, + Panic(EPanicPreCond_SendvCardsL)); + + //Fill message data + const TInt count( iConverter->FileNames().MdcaCount()); + for( TInt i( 0 ); i < count; ++i ) + { + messageData->AppendAttachmentHandleL( + iConverter->AttachmentFileArray().FileHandleAt( i ) ); + } + SendMsgUsingSendUI(messageData); + } + else if (caps.iFlags & TSendingCapabilities::ESupportsBodyText) + { + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("SendvCardsLD, KSenduiMtmSmsUid")); + // Sending through SMS -> there should be only one vCard + // attachment. Package the attachment to a rich text object and + // send it as the message body. + __ASSERT_DEBUG(iConverter->FileNames().MdcaCount()==1, + Panic(EPanicPreCond_SendvCardsL)); + + // Copy the one and only attachment into a rich text object + CRichText* msgBody = CreateRichTextFromFileLC + (*iEikEnv, iConverter->FileNames().MdcaPoint(0)); + + messageData->SetBodyTextL( msgBody ); + SendMsgUsingSendUI(messageData); + + CleanupStack::PopAndDestroy(msgBody); + } + else + { + User::Leave( KErrNotSupported ); + } + } + + CleanupStack::PopAndDestroy(); //messageData + + ProcessDone(KErrNone); + PBK2_DEBUG_PRINT + (PBK2_DEBUG_STRING("CPbk2SendContactCmd::SendvCardsLD, end"), this); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::SendvCardsLD +// -------------------------------------------------------------------------- +// +TInt CPbk2SendContactCmd::SendvCardsLD(TAny* aThis) + { + __ASSERT_DEBUG( aThis, Panic(EPanicPreCond_ErrArgument) ); + + CPbk2SendContactCmd* self = static_cast(aThis); + self->SendvCardsLD(); + + return EFalse; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::AnyThumbnailsL +// -------------------------------------------------------------------------- +// +TBool CPbk2SendContactCmd::AnyThumbnailsL() const + { + TInt cntCount(iStoreContacts.Count()); + + for (TInt i=0; i < cntCount; ++i) + { + MVPbkStoreContact* contact = (iStoreContacts)[i]; + const MVPbkBaseContactField* field = + Pbk2SendCmdUtils::FindFieldL( + *contact, + R_THUMBNAIL_FIELD_TYPE, + iAppServices->ContactManager().FieldTypes()); + + if (field) + { + // We can exit the loop as soon as a thumbnail + // is found + return ETrue; + } + } + return EFalse; + } + +#if 0 +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::SelectionListL +// -------------------------------------------------------------------------- +// +TInt CPbk2SendContactCmd::SelectionListL() const + { + TInt ret( KNoMenu ); + TBool supportsFieldType( ETrue ); + TBool nameOrPropertyField( EFalse ); + + // Check is the sending media SMS and does the contact + // have a thumbnail + TBool smsAndThumbnail( EFalse ); + if ( ( iMtmUid == KSenduiMtmSmsUid ) && AnyThumbnailsL() ) + { + smsAndThumbnail = ETrue; + } + + // If focused field is supplied, the command object was + // launched from contact info view and that requires + // we have to check is the field supported by vCard spec + if ( iFocusedField ) + { + if ( iAppServices && ( !iVCardEngine->SupportsFieldType( + *Pbk2SendCmdUtils::FieldType( + *iFocusedField, + iAppServices->ContactManager().FieldTypes() ) ) ) ) + { + supportsFieldType = EFalse; + } + } + + // Now check the cases when the menu needs to be shown + // There are two main branches depending on which view + // this command object was launched from + if ( iFocusedField ) + { + // Command object was launched from contact info view. + + if ( !smsAndThumbnail ) + { + // When there is no thumbnail involved the selection + // menu is shown only if we are over vCard supported + // field and the focus is not in the name or property field. + nameOrPropertyField = IsNameOrPropertyField( *iFocusedField ); + if ( supportsFieldType && !nameOrPropertyField ) + { + ret = R_PBK2_CONTACTINFO_SEND_OPTIONS; + } + } + else + { + // Thumbnail is involved, the selection menu depends + // on whether we are over vCard supported field or not + if ( supportsFieldType ) + { + ret = R_PBK2_CONTACTINFO_SEND_OPTIONS_SMS_THUMBNAIL; + } + else + { + ret = R_PBK2_CONTACTINFO_SEND_OPTIONS_SMS_THUMBNAIL_NO_FIELD; + } + } + } + else + { + // Command object was launched from contact list view, + // the menu is shown only in case there is thumbnail + // involded and the sending media is SMS + if ( smsAndThumbnail ) + { + ret = R_PHONEBOOK2_SEND_OPTIONS; + } + } + + return ret; + } +#endif + +#if 1 +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::SelectionListL +// -------------------------------------------------------------------------- +// +TInt CPbk2SendContactCmd::SelectionListL() const + { + TInt ret( KNoMenu ); + + // Show the query if contact has a thumbnail. + if ( AnyThumbnailsL() ) + { + ret = R_PHONEBOOK2_SEND_OPTIONS; + } + + return ret; + } +#endif + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::MapSelection +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::MapSelection(TInt& aSelection, TInt aShownMenu) + { + for (TInt i = 0; SelectionMapping[i].iResId != ESelectionLast; ++i) + { + if (SelectionMapping[i].iResId == aShownMenu) + { + TInt selection(KErrNotFound); + switch(aSelection) + { + case 0: + { + selection = SelectionMapping[i].iStSelection; + break; + } + case 1: + { + selection = SelectionMapping[i].iNdSelection; + break; + } + case 2: + { + selection = SelectionMapping[i].iRdSelection; + break; + } + default: + { + __ASSERT_DEBUG(EFalse, Panic(EPanicLogic_MapSelection)); + } + } + + if (selection == ECancel) + { + __ASSERT_DEBUG(EFalse, Panic(EPanicLogic_MapSelection)); + } + + aSelection = selection; + return; + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::SelectSentDataL +// -------------------------------------------------------------------------- +// +TInt CPbk2SendContactCmd::SelectSentDataL() + { + TInt selectionIndex(ESendAllData); + + // Get the resource id of the menu to be shown + TInt resourceId = SelectionListL(); + + if (resourceId) + { + // Create a list box + CEikColumnListBox* listBox = static_cast + (EikControlFactory::CreateByTypeL + (EAknCtSinglePopupMenuListBox).iControl); + CleanupStack::PushL(listBox); + + // Create a popup list + CAknPopupList* popupList = CAknPopupList::NewL + (listBox, R_AVKON_SOFTKEYS_OK_CANCEL__OK, + AknPopupLayouts::EMenuGraphicWindow); + CleanupStack::PushL(popupList); + + HBufC* headingText= CCoeEnv::Static()->AllocReadResourceLC + (R_PBK2_BUSINESSCARD_SEND_HEADING); + popupList->SetTitleL(*headingText); + CleanupStack::PopAndDestroy(); // headingText + + // Init list box + listBox->SetContainerWindowL(*popupList); + + TResourceReader resReader; + CCoeEnv::Static()->CreateResourceReaderLC(resReader, resourceId); + listBox->ConstructFromResourceL(resReader); + CleanupStack::PopAndDestroy(); // resReader + + listBox->CreateScrollBarFrameL(ETrue); + listBox->ScrollBarFrame()->SetScrollBarVisibilityL + (CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto); + + CleanupStack::Pop(); // popupList + + // Show popuplist dialog + TInt res = popupList->ExecuteLD(); + if (res) + { + selectionIndex = listBox->CurrentItemIndex(); + + // We have to remap the selection index since + // several different listbox configurations + MapSelection(selectionIndex, resourceId); + } + else + { + selectionIndex = ECancel; + } + CleanupStack::PopAndDestroy(); // listBox + } + + return selectionIndex; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ShowSendQueryL +// -------------------------------------------------------------------------- +// +TUid CPbk2SendContactCmd::ShowSendQueryL() + { + /// Sending params + TPbk2SendingParams params = CreateParamsLC(); + + TUid uid = iSendUi->ShowSendQueryL( NULL, params.iCapabilities, params.iMtmFilter ); + + CleanupStack::PopAndDestroy(); // mtmfilter + return uid; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ProcessDone +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ProcessDone(TInt aCancelCode) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::ProcessDone (%d)"), aCancelCode); + if ( aCancelCode != KErrCancel && iUiControl ) + { + // Ignore possible errors in clearing find box contents in release + // builds; just assert in debug builds. Showing an error here might + // signal to the user that there was some problem in the send contact + // command completion. + TInt err( KErrNone ); + TRAP( err, iUiControl->ResetFindL() ); + __ASSERT_DEBUG( err == KErrNone, Panic( EResetFindResult ) ); + + iUiControl->UpdateAfterCommandExecution(); + } + + if ( iCommandObserver ) + { + // Notify command owner that the command has finished + iCommandObserver->CommandFinished(*this); + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ProcessDismissed +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ProcessDismissed( TInt aCancelCode ) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::ProcessDismissed (%d)"), aCancelCode); + if (aCancelCode == EAknSoftkeyCancel) + { + ProcessDone( KErrCancel ); + } + else if ( iState == EStopping ) + { + IssueStopRequest(); + } + else + { + // Cancel first any outstanding requests + iVCardSender->Cancel(); + iVCardSender->Start( TCallBack( &CPbk2SendContactCmd::SendvCardsLD, + this ) ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::CreateParamsLC +// -------------------------------------------------------------------------- +// +TPbk2SendingParams CPbk2SendContactCmd::CreateParamsLC() + { + // Construct the MTM filter + CArrayFixFlat* mtmFilter = + new(ELeave) CArrayFixFlat(KGranularity); + CleanupStack::PushL(mtmFilter); + + mtmFilter->AppendL(KSenduiMtmPostcardUid); // hide postcard + mtmFilter->AppendL( KSenduiMtmAudioMessageUid ); // hide audio message + mtmFilter->AppendL( KMmsDirectUpload ); // hide upload + + // Check must we disable SMS menuitem + if ( iSendUi->CanSendBioMessage( KMsgBioUidVCard ) ) + { + mtmFilter->AppendL(KSenduiMtmSmsUid); // hide SMS + } + + // If there are items more than one, hide items + if ( IsMoreThanOneContact() ) + { + mtmFilter->AppendL(KSenduiMtmSmsUid); // hide SMS + } + else if (!FeatureManager::FeatureSupported(KFeatureIdMMS)) + { + // Hide MMS if not supported + mtmFilter->AppendL(KSenduiMtmMmsUid); + } + + // Hide Email if not supported + if (!FeatureManager::FeatureSupported(KFeatureIdEmailUi)) + { + mtmFilter->AppendL(KSenduiMtmSmtpUid); + mtmFilter->AppendL(KSenduiMtmImap4Uid); + mtmFilter->AppendL(KSenduiMtmPop3Uid); + mtmFilter->AppendL(KSenduiMtmSyncMLEmailUid); + } + + TSendingCapabilities capabilities = TSendingCapabilities(); + capabilities.iFlags = TSendingCapabilities::ESupportsBioSending; + capabilities.iFlags |= TSendingCapabilities::ESupportsAttachments; + return TPbk2SendingParams( mtmFilter, capabilities ); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ConvertContactL +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ConvertContactL(TInt aSelectionIndex) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::ConvertContactL(0x%x)"), this); + + delete iDecorator; + iDecorator = NULL; + + if (aSelectionIndex != ECancel) + { + // Start wait note if user continues. If it cancels then don't + // create decorator because it causes a panic in CActive destructor + // of this instance. + iDecorator = Pbk2ProcessDecoratorFactory::CreateWaitNoteDecoratorL( + R_QTN_SM_WAIT_BUSINESS_CARD, ETrue ); + iDecorator->SetObserver( *this ); + // wait note doesn't care about amount + iDecorator->ProcessStartedL( 0 ); + + if ( iFocusedField ) + { + iConverter->ConvertContactL( + iStoreContacts.Array(), iFocusedField, + aSelectionIndex, *this); + } + else if ( iCntIterator ) + { + iConverter->ConvertContactsL( + *iCntIterator, aSelectionIndex, *this ); + } + else + { + // iContacts validity is checked in function entry + iConverter->ConvertContactsL( + iStoreContacts.Array(), aSelectionIndex, *this); + } + } + else + { + IssueStopRequest(); + } + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::ConvertContactL(0x%x), end"), this); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::RetrieveContactL +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::RetrieveContactL(const MVPbkContactLink& aLink) + { + iRetrieveOperation = iAppServices->ContactManager(). + RetrieveContactL(aLink, *this); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::FilterErrors +// -------------------------------------------------------------------------- +// +TInt CPbk2SendContactCmd::FilterErrors(TInt aErrorCode) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::FilterErrors(%d) start"), aErrorCode); + + TInt result = aErrorCode; + switch (aErrorCode) + { + case KErrNotFound: // FALLTHROUGH + case KErrInUse: // FALLTHROUGH + { + // 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(); + ProcessDone(aErrorCode); + break; + } + } + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::FilterErrors(%d) end"), result); + + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::IssueRequest +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::IssueRequest() + { + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + SetActive(); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::IssueStopRequest +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::IssueStopRequest() + { + iState = EStopping; + if (!IsActive()) + { + IssueRequest(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::SendMsgUsingSendUI +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::SendMsgUsingSendUI(CMessageData* aMsgData) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::SendMsgUsingSendUI(0x%x), start"), this); + + // Send the message using Send Ui + TRAPD(error, iSendUi->CreateAndSendMessageL( iMtmUid, aMsgData, KMsgBioUidVCard)); + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::SendMsgUsingSendUI(%d), error"), error); + + if (error != KErrNone) + { + FilterErrors(error); + } + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2SendContactCmd::SendMsgUsingSendUI(0x%x), end"), this); + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::IsMoreThanOneContact +// -------------------------------------------------------------------------- +// +TBool CPbk2SendContactCmd::IsMoreThanOneContact() + { + TBool result = EFalse; + if ( iCntIterator ) + { + result = ETrue; + } + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::CommandExtension +// -------------------------------------------------------------------------- +// +TAny* CPbk2SendContactCmd::CommandExtension(TUid aExtensionUid ) + { + if( aExtensionUid == TUid::Uid(MPbk2ResourceReleaseUID) ) + { + return static_cast(this); + } + else + { + return NULL; + } + } + +// -------------------------------------------------------------------------- +// CPbk2SendContactCmd::ReleaseResource +// -------------------------------------------------------------------------- +// +void CPbk2SendContactCmd::ReleaseResource() + { + Cancel(); + if (iConverter) + { + iConverter->Cancel(); + CPbk2AttachmentFileArray& fileArray = iConverter->AttachmentFileArray(); + if (fileArray.Count() > 0) + { + if ( !iWaiter ) + { + TInt err( KErrNone ); + TRAP( err,iWaiter = new (ELeave) CActiveSchedulerWait()); + if ( err != KErrNone ) + { + fileArray.ResetAndDestroy(); + return; + } + } + + iState = EReleaseResource; + IssueRequest(); + iWaiter->Start(); + } + } + } + +// End of File