diff -r 000000000000 -r 72b543305e3a mobilemessaging/postcard/postcardsrc/PostcardOperationOpen.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobilemessaging/postcard/postcardsrc/PostcardOperationOpen.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,986 @@ +/* +* Copyright (c) 2005 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: +* CPostcardOperationOpen +* +*/ + + + +// ========== INCLUDE FILES ================================ + +#include +#include +#include // TDataType +#include // CGulIcon +#include // For TDocumentStorage + +#include +#include +#include +#include // for CMmsMediaResolver +#include +#include +#include + +#include +#include +#include +#include +#include + +#include // AttachmentManager +#include // AttachmentManagerSync +#include // MimeHeaders +#include + +#include // VCardPropertyValue +#include +#include +#include // CContactTextField + +#include // for StringLoader + +#include // for Postcard resources +#include "PostcardLaf.h" +#include "PostcardUtils.h" +#include "Postcard.hrh" +#include "PostcardOperationOpen.h" +#include "PostcardRecipientWrapper.h" +#include "PostcardContact.h" +#include "PostcardPrivateCRKeys.h" // cenrep keys +#include "PostcardCenRep.h" + +// ========== EXTERNAL DATA STRUCTURES ===================== + +// ========== EXTERNAL FUNCTION PROTOTYPES ================= + +// ========== CONSTANTS ==================================== + +// ========== MACROS ======================================= + +// ========== LOCAL CONSTANTS AND MACROS =================== + +// This was "FN" in 3.0-3.1 but OMA says it should be "N". Accept +// both when opening and be compatible with both. +_LIT8(KPostcardVCardName, "N"); +_LIT8(KPostcardVCardNameFN, "FN"); +_LIT8(KPostcardVCardAddr, "ADR"); + +// ========== MODULE DATA STRUCTURES ======================= + +// ========== LOCAL FUNCTION PROTOTYPES ==================== + +// ========== LOCAL FUNCTIONS ============================== + +// ========== MEMBER FUNCTIONS ============================= + +// --------------------------------------------------------- +// CPostcardOperationOpen::NewL +// --------------------------------------------------------- +CPostcardOperationOpen* CPostcardOperationOpen::NewL( + MPostcardOperationObserver& aObserver, + CPostcardDocument& aDocument, + CPostcardAppUi& aAppUi, + RFs& aFs ) + { + CPostcardOperationOpen* self = + new ( ELeave ) CPostcardOperationOpen( aObserver, aDocument, aAppUi, aFs ); + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::CPostcardOperationOpen +// --------------------------------------------------------- +CPostcardOperationOpen::CPostcardOperationOpen( + MPostcardOperationObserver& aObserver, + CPostcardDocument& aDocument, + CPostcardAppUi& aAppUi, + RFs& aFs ) : + CPostcardOperation( aObserver, aDocument, aAppUi, aFs ), + iSpecialFormat( aAppUi.CenRep().GetString( KPocaKeyServiceSpecialFormat ) ), + iSeparatorChar( aAppUi.CenRep().GetString( KPocaKeyServiceSeparator ) ) + { + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::CPostcardOperationOpen +// --------------------------------------------------------- +CPostcardOperationOpen::~CPostcardOperationOpen( ) + { + if( iEditFile ) + { + iEditFile->Close(); + delete iEditFile; + } + delete iImageInfo; + delete iImageProcessor; + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::Start +// --------------------------------------------------------- +void CPostcardOperationOpen::Start( TInt /*aArgument*/ ) + { + ToState( EPostcardOpenInitializing ); + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::Launch +// --------------------------------------------------------- +void CPostcardOperationOpen::DoLaunchStepL() + { + iFlags &= ~EPostcardOpenRequestActive; + switch ( iLaunchState ) + { + case EPostcardOpenInitializing: + { + InitL( ); + iDocument.InitializeL( iFs ); + ToState( EPostcardOpenCheckAttas ); + break; + } + case EPostcardOpenCheckAttas: + { + if( !CheckAttasL( ) ) + { // If there was error, this has been completed already + ToState( EPostcardOpenHandleImage ); + } + else + { + iLaunchState = EPostcardOpenError; + } + break; + } + case EPostcardOpenHandleImage: + { + DoHandleImageL( ); + break; + } + case EPostcardOpenProcessImage: + { + DoStartProcessImageL( ); + break; + } + case EPostcardOpenHandleText: + { + DoHandleTextL( ); + break; + } + case EPostcardOpenHandleRecipient: + { + DoHandleRecipientL( ); + ToState( EPostcardOpenFinished ); + break; + } + case EPostcardOpenFinished: + { + UnInitL( ); + iObserver.PostcardOperationEvent( + EPostcardOperationOpen, + EPostcardOperationComplete ); + break; + } + default: + UnInitL( ); + iObserver.PostcardOperationEvent( + EPostcardOperationOpen, + EPostcardOperationError ); + break; + } + } + +// --------------------------------------------------------- +// DoHandleL +// --------------------------------------------------------- +void CPostcardOperationOpen::DoHandleImageL( ) + { + if ( iImage != 0 ) + { + if( iDocument.MessageType( ) == EPostcardSendAs ) + { // SendAs -> Lets see what's inside + RFile imageFile = iManager->GetAttachmentFileL( iImage ); + CleanupClosePushL( imageFile ); + iImageInfo = iDocument.MediaResolver()->CreateMediaInfoL( imageFile ); + iDocument.MediaResolver()->ParseInfoDetailsL( iImageInfo, imageFile ); + + // Lets first check if the file seems to be ok for inserting + if( iImageInfo->Protection( ) ) + { + CleanupStack::PopAndDestroy( &imageFile ); // imageFile + ToErrorState( R_POSTCARD_CANNOT_SEND_PROTECTED ); + return; + } + if( iImageInfo->Corrupt( ) ) + { + // Corrupt is set to only supported media types + CleanupStack::PopAndDestroy( &imageFile ); // imageFile + ToErrorState( R_POSTCARD_OBJECT_CORRUPTED ); + return; + } + else if ( !iDocument.IsImage( iImageInfo->MimeType( ) ) ) + { + CleanupStack::PopAndDestroy( &imageFile ); // imageFile + ToErrorState( R_POSTCARD_FORMAT_NOT_SUPPORTED ); + return; + } + else if ( iImageInfo->MediaType() != EMsgMediaImage ) + { + CleanupStack::PopAndDestroy( &imageFile ); // imageFile + ToErrorState( R_POSTCARD_FORMAT_NOT_SUPPORTED ); + return; + } + else if ( static_cast(iImageInfo)->IsAnimation( ) ) + { + CleanupStack::PopAndDestroy( &imageFile ); // imageFile + ToErrorState( R_POSTCARD_FORMAT_NOT_SUPPORTED ); + return; + } + + TSize dimensions = static_cast(iImageInfo)->Dimensions( ); + TInt imageWidth = dimensions.iWidth>dimensions.iHeight?dimensions.iWidth:dimensions.iHeight; + TInt imageHeight = dimensions.iWidth>dimensions.iHeight?dimensions.iHeight:dimensions.iWidth; + + TSize maxSize = iDocument.MaxImageDimensions( ); + + // OK, it seems to be pretty ok, now lets see what we can do + if( ( iImageInfo->MimeType( ).CompareF( KMsgMimeImagePng ) == 0 ) + || ( ( imageWidth > maxSize.iWidth || imageHeight > maxSize.iHeight ) + && iImageInfo->FileSize( ) > iDocument.MaxImageSize( ) ) ) + { // This is PNG or it's a too wide JPEG file + iEditFile = new ( ELeave ) RFile; + CMsvAttachment* attachment = CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); + CleanupStack::PushL( attachment ); + attachment->SetAttachmentNameL( KPostcardFilenameScaled ); + iManager->CreateAttachmentL( KPostcardFilenameScaled, *iEditFile, attachment, iStatus ); + iFlags |= EPostcardOpenRequestActive; + CleanupStack::Pop( attachment ); // attachment + iEditAtta = attachment; + iLaunchState = EPostcardOpenProcessImage; + SetActive(); + CleanupStack::PopAndDestroy( &imageFile ); // imagefile + return; + } + else if( iImageInfo->FileSize( ) > iDocument.MaxImageSize( ) ) + { // Image is too big, but not too wide -> create empty attachment for now + iEditFile = new ( ELeave ) RFile; + CMsvAttachment* attachment = CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); + CleanupStack::PushL( attachment ); + attachment->SetAttachmentNameL( KPostcardFilenameCompressed ); + iManager->CreateAttachmentL( KPostcardFilenameCompressed, *iEditFile, attachment, iStatus ); + iFlags |= EPostcardOpenRequestActive; + CleanupStack::Pop( attachment ); // attachment + iEditAtta = attachment; + iLaunchState = EPostcardOpenProcessImage; + SetActive(); + CleanupStack::PopAndDestroy( &imageFile ); // imagefile + return; + } + else + { // OK, the file is ok, we just need to update the MsvHeaders + DoUpdateSendasAttachmentL( iImageInfo->MimeType( ) ); + } + CleanupStack::PopAndDestroy( ); // imagefile + } + // Either this is not sendas or the image did not need conversion or compression + RFile imageFile = iManager->GetAttachmentFileL( iImage ); + CleanupClosePushL( imageFile ); + + // Scale image to bitmap to be drawn on the screen + iSourceImage = IHLImageFactory::OpenFileImageL( imageFile ); + iDestinationBitmap = IHLBitmap::CreateL(); + iImageHandler = IHLViewerFactory::CreateImageViewerL( PostcardLaf::Image( ).Size( ), + *iSourceImage, + *iDestinationBitmap, + *this, + TUint32( 0 ) ); + User::LeaveIfError( iImageHandler->SetSourceRectPosition( TPoint( 0, 0 ) ) ); + + CleanupStack::PopAndDestroy( &imageFile ); // imageFile + } + else + { + ToState( EPostcardOpenHandleText ); + } + } + +// --------------------------------------------------------- +// DoStartProcessImageL +// --------------------------------------------------------- +void CPostcardOperationOpen::DoStartProcessImageL( ) + { + RFile sourceFile = iManager->GetAttachmentFileL( iImage ); + CleanupClosePushL( sourceFile ); + if( !iImageProcessor ) + { + iImageProcessor = new (ELeave) CUniImageProcessor( this ); + } + TSize maxDimensions = iDocument.MaxImageDimensions( ); + + TSize origDimensions = static_cast(iImageInfo)->Dimensions( ); + + if( origDimensions.iWidth < origDimensions.iHeight ) + { // It's portrait so swap max dimensions + origDimensions = maxDimensions; + maxDimensions.iWidth = origDimensions.iHeight; + maxDimensions.iHeight = origDimensions.iWidth; + } + + iImageProcessor->ProcessImageL( sourceFile, + *iEditFile, + maxDimensions, + KMsgMimeImageJpeg, + ETrue, + iDocument.MaxImageSize( ) ); + CleanupStack::PopAndDestroy(); // sourceFile + } + +// --------------------------------------------------------- +// DoUpdateSendasAttachmentL +// --------------------------------------------------------- +void CPostcardOperationOpen::DoUpdateSendasAttachmentL( const TDataType& aMimeType ) + { + CMsvMimeHeaders* headers = CMsvMimeHeaders::NewLC( ); + if( aMimeType.Des8( ).CompareF( KMsgMimeImageGif ) == 0 ) + { // Image is gif + headers->SetContentLocationL( KPostcardFilenameNoOpGif); + } + else + { + headers->SetContentLocationL( KPostcardFilenameNoOp ); + } + headers->SetContentTypeL( aMimeType.Des8( ) ); + + // As this function is called only when in SendAs + // there's certainly just one attachment so we index it directly + CMsvAttachment* attachment = iManager->GetAttachmentInfoL( 0 ); + CleanupStack::PushL( attachment ); + headers->StoreL( *attachment ); + attachment->SetMimeTypeL( aMimeType.Des8( ) ); + iStore->AttachmentManagerExtensionsL( ).ModifyAttachmentInfoL( attachment ); + CleanupStack::Pop( attachment ); + + CleanupStack::PopAndDestroy( headers ); + + iStore->Commit( ); + // Lets check again (to get right AttachmentIds) + CheckAttasL( ); + } + +// --------------------------------------------------------- +// ImageProcessingReady +// --------------------------------------------------------- +void CPostcardOperationOpen::ImageProcessingReady( TSize aBitmapSize, TInt aFileSize, TBool /*aCompressed*/ ) + { + if( iEditFile ) + { + iEditFile->Close(); + delete iEditFile; + iEditFile = NULL; + } + + TBool imageFits = EFalse; + TSize maxDimensions = iDocument.MaxImageDimensions( ); + if( aBitmapSize.iWidth <= maxDimensions.iWidth && + aBitmapSize.iHeight <= maxDimensions.iHeight ) + { + imageFits = ETrue; + } + else if( aBitmapSize.iWidth <= maxDimensions.iHeight && + aBitmapSize.iHeight <= maxDimensions.iWidth ) + { + imageFits = ETrue; + } + + if( !imageFits || aFileSize > iDocument.MaxImageSize( ) ) + { // The process was not successful + ToErrorState( R_POSTCARD_PROCESS_NOT_SUCCESSFUL ); + return; + } + + // Call this to start scaling to screen (deletes the previous image etc..) + TRAPD( err, StartScalingToScreenL( ) ); + if( err ) + { + ToErrorState( R_POSTCARD_FORMAT_NOT_SUPPORTED ); + } + } + +// --------------------------------------------------------- +// StartScalingToScreenL +// --------------------------------------------------------- +void CPostcardOperationOpen::StartScalingToScreenL( ) + { + TInt oldImage = TMsvIdToIndexL( iImage ); + iStore->AttachmentManagerExtensionsL( ).RemoveAttachmentL( oldImage ); + iStore->Commit( ); + + DoUpdateSendasAttachmentL( iImageInfo->MimeType( ) ); + + // Lets add headers + RFile imageFile = iManager->GetAttachmentFileL( iImage ); + CleanupClosePushL( imageFile ); + + iSourceImage = IHLImageFactory::OpenFileImageL( imageFile ); + iDestinationBitmap = IHLBitmap::CreateL(); + + iImageHandler = IHLViewerFactory::CreateImageViewerL( PostcardLaf::Image( ).Size( ), + *iSourceImage, + *iDestinationBitmap, + *this, + TUint32( 0 ) ); + User::LeaveIfError( iImageHandler->SetSourceRectPosition( TPoint( 0, 0 ) ) ); + + CleanupStack::PopAndDestroy( &imageFile ); // imageFile + } + +// --------------------------------------------------------- +// ViewerBitmapChangedL +// --------------------------------------------------------- +void CPostcardOperationOpen::ViewerBitmapChangedL() + { + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; + CFbsBitmap* mask = NULL; + bitmap->Duplicate( iDestinationBitmap->Bitmap().Handle( ) ); + + if ( iDestinationBitmap->HasMask() ) + { + mask = new (ELeave) CFbsBitmap; + mask->Duplicate( iDestinationBitmap->Mask().Handle( ) ); + } + + delete iDestinationBitmap; + iDestinationBitmap = NULL; + + delete iSourceImage; + iSourceImage = NULL; + + delete iImageHandler; + iImageHandler = NULL; + + iLaunchState = EPostcardOpenHandleText; + + CGulIcon* icon = NULL; + TRAPD( err, icon = CGulIcon::NewL( bitmap, mask ) ); + + if( err ) + { // Lets nullify it if there was an error + icon = NULL; + } + + iAppUi.SetImage( icon ); + + CompleteSelf( KErrNone ); + + } + +// --------------------------------------------------------- +// ViewerError +// --------------------------------------------------------- +void CPostcardOperationOpen::ViewerError( TInt /*aError*/ ) + { + ToErrorState( R_POSTCARD_FORMAT_NOT_SUPPORTED ); + } + +// --------------------------------------------------------- +// DoHandleTextL +// --------------------------------------------------------- +void CPostcardOperationOpen::DoHandleTextL( ) + { +/* if ( iText != 0 ) + { // Lets externalize the text itself + RFile file = iManager->GetAttachmentFileL( iText ); + + CMmsTextInfo* info = static_cast(iDocument.MediaResolver()->ResolveFileTransferInfoL( file )); + CleanupStack::PushL( info ); + TUint attaCharset = info->CharacterSet(); + CleanupStack::PopAndDestroy( info ); + RFileReadStream input_stream( file ); + + CPlainText::TImportExportParam param; + param.iForeignEncoding = attaCharset; //charconvCharsetID; + param.iOrganisation = CPlainText::EOrganiseByParagraph; + CPlainText::TImportExportResult result; + TRAPD( error, text->ImportTextL( 0, input_stream, param, result) ); + input_stream.Close( ); + file.Close( ); + } +*/ + + TPostcardMsgType type = iDocument.MessageType( ); + if( iText > 0 && type == EPostcardSendAs ) + { // If type is SendAs and file is from Phonebook -> Handle this case first + CMsvAttachment* atta = iManager->GetAttachmentInfoL( iText ); + CleanupStack::PushL( atta ); + if( atta->AttachmentName( ).Find( _L("X-Nokia-PhonebookId_") ) != -1 ) + { + // All right, it was from Phonebook + RFile file = iManager->GetAttachmentFileL( iText ); + CleanupClosePushL( file ); + + CPostcardContact* contact = CPostcardContact::NewL( iFs ); + CleanupStack::PushL( contact ); + contact->FetchContactL( file ); + DoHandlePhonebookSendAsL( *contact ); + CleanupStack::PopAndDestroy( 3, atta ); // contact, file, atta + + ToState( EPostcardOpenFinished ); + return; + } + // Ok, it was not from Phonebook, so lets continue normally.. + CleanupStack::PopAndDestroy( atta ); + } + + CPlainText* text = CPlainText::NewL( CEditableText::ESegmentedStorage, KPostcardDefaultGreetingSegment ); + CleanupStack::PushL( text ); + + if ( iText > 0 ) + { // Lets externalize the text itself + RFile file = iManager->GetAttachmentFileL( iText ); + CleanupClosePushL( file ); + + CMsvAttachment* atta = iManager->GetAttachmentInfoL( iText ); + CleanupStack::PushL( atta ); + + CMsvMimeHeaders* msvMime = CMsvMimeHeaders::NewLC(); + msvMime->RestoreL( *atta ); + + TUint attaCharset = msvMime->MimeCharset( ); // only charset needed + + CleanupStack::PopAndDestroy( 2, atta ); // mime, atta + + if( attaCharset == 0 ) + { + //assume US-ASCII - mandated by RFC 2046 + attaCharset = KMmsUsAscii; + } + + TUint finalCharset = iDocument.TextUtils()->MibIdToCharconvIdL( attaCharset ); + + RFileReadStream input_stream( file ); + + CPlainText::TImportExportParam param; + param.iForeignEncoding = finalCharset; + param.iOrganisation = CPlainText::EOrganiseByParagraph; + CPlainText::TImportExportResult result; + TRAP_IGNORE( text->ImportTextL( 0, input_stream, param, result) ); + input_stream.Close( ); + CleanupStack::PopAndDestroy( &file ); // file + } + + if( type == EPostcardSendAs ) + { + // Otherwise there's no text or text is just text + CleanupStack::Pop( text ); + iAppUi.SetTextL( *text ); // AppUI takes the ownership + ToState( EPostcardOpenHandleRecipient ); + return; + } + else if( type == EPostcardForward || + type == EPostcardEdit || + type == EPostcardSent || + type == EPostcardDraft ) + { + // The recipient might be added into the greeting text only when the entry + // is opened from Sent folder or is forwarded or edited + if( iSpecialFormat.Length( ) > 0 && text->DocumentLength( ) > 0 && iRecipient == 0 ) + { // if special send format is defined and there's no separate recipient attachment + TPtrC16 textBuf ( text->Read( 0 ) ); + if( textBuf.Find( iSeparatorChar ) != KErrNotFound ) + { // There are separators -> this msg has been sent + // lets dig the recipient info from the text + DoHandleSpecialFormatOpenL( *text ); + CleanupStack::PopAndDestroy( text ); + ToState( EPostcardOpenFinished ); + return; + } + else + { + // There are no separators -> we can normally continue + // and use "text" as the real greeting text + } + } + } + CleanupStack::Pop( text ); + iAppUi.SetTextL( *text ); // AppUI takes the ownership + ToState( EPostcardOpenHandleRecipient ); + } + +// --------------------------------------------------------- +// DoHandleRecipientL +// --------------------------------------------------------- +void CPostcardOperationOpen::DoHandleRecipientL( ) + { + CContactCard* card = CContactCard::NewLC(); + + if( iRecipient != 0 ) + { + TPostcardMsgType type = iDocument.MessageType( ); + + if( type == EPostcardForward ) + { // We are opening a forward entry -> delete VCard + TInt oldImage = TMsvIdToIndexL( iRecipient ); + iStore->AttachmentManagerExtensionsL( ).RemoveAttachmentL( oldImage ); + iCommit = ETrue; + } + else + { + ParseRecipientL( *card ); + } + } + CleanupStack::Pop( card ); + iAppUi.SetRecipientL( *card ); //ownership moves.. the function does not leave before card is set as a member + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::ParseRecipientL +// --------------------------------------------------------- +void CPostcardOperationOpen::ParseRecipientL( CContactCard& aContactCard ) + { + RFile file = iManager->GetAttachmentFileL( iRecipient ); + CleanupClosePushL( file ); + + CParserVCard* parser = CParserVCard::NewL(); + CleanupStack::PushL(parser); + + RFileReadStream vCardStream( file ); + vCardStream.PushL(); + MStreamBuf* buf = vCardStream.Source(); + if( !buf ) + { + User::Leave( KErrGeneral ); + } + + parser->InternalizeL(vCardStream); + + vCardStream.Close(); + vCardStream.Pop(); + + // Does not take ownership + CArrayPtr* arr = parser->ArrayOfProperties(EFalse); + for( TInt a = 0; a < arr->Count( ); a++ ) + { + CParserProperty* prop = arr->At( a ); + TPtrC8 propName = prop->Name(); + CParserPropertyValue *propValue = prop->Value(); + if( propValue ) + { + if( propValue->Uid().iUid == KVersitPropertyCDesCArrayUid ) + { + CParserPropertyValueCDesCArray* arrayProperty = + reinterpret_cast( propValue ); + CDesCArray* values = arrayProperty->Value(); + if( propName.Compare( KPostcardVCardName ) == 0 ) + { + TPostcardUtils::AddContactFieldL( aContactCard, + TPostcardUtils::ContactItemNameFromId( EPostcardAddressName ), + values->MdcaPoint( 0 ) ); + } + else if( propName.Compare( KPostcardVCardAddr ) == 0 ) + { + // This is the order items are read from the VCard store + static const TInt indexToId[] = + { + 0, // PO Box in the array will be ignored + EPostcardAddressInfo, EPostcardAddressStreet, + EPostcardAddressCity, EPostcardAddressState, + EPostcardAddressZip, EPostcardAddressCountry + }; + const TInt KNumIds = + sizeof( indexToId ) / sizeof( indexToId[0] ); + TPostcardMsgType type = iDocument.MessageType(); + // Skip PO Box at beginning of the array + for (TInt i = 1; i < values->Count() && i < KNumIds; i++) + { + TPtrC value = values->MdcaPoint(i); + // If viewing a sent postcard, all available fields are + // initialized. Otherwise the field is initialized if + // it's visible in address dialog (max. length is not zero). + if( value.Length() && + ( type == EPostcardSent || iAppUi.MaxTextLength( indexToId[i] ) ) ) + { + TPostcardUtils::AddContactFieldL( aContactCard, + TPostcardUtils::ContactItemNameFromId( indexToId[i] ), + value ); + } + } + } + } + else if( propValue->Uid().iUid == KVersitPropertyHBufCUid ) + { + // Postcard before S60 3.2 release used FN (full name) property. + // Since 3.2, N property is used + if( propName.Compare( KPostcardVCardNameFN ) == 0 ) + { + TPostcardUtils::AddContactFieldL( aContactCard, + TPostcardUtils::ContactItemNameFromId( EPostcardAddressName ), + static_cast( propValue )->Value() ); + } + } + } + } + CleanupStack::PopAndDestroy( 2, &file ); // file, parser + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::ConstructL +// --------------------------------------------------------- +void CPostcardOperationOpen::ConstructL( ) + { + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::DoCancel +// --------------------------------------------------------- +void CPostcardOperationOpen::DoCancel( ) + { + if( iManager ) + { + if( iFlags & EPostcardOpenRequestActive ) + { + iManager->CancelRequest(); + } + } + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::RunL +// --------------------------------------------------------- +void CPostcardOperationOpen::RunL( ) + { + DoLaunchStepL( ); + } + +// --------------------------------------------------------- +// RunError +// --------------------------------------------------------- +TInt CPostcardOperationOpen::RunError( TInt aError ) + { + iLaunchState = -1; + SetError( aError ); + iObserver.PostcardOperationEvent( + EPostcardOperationOpen, + EPostcardOperationError ); + return KErrNone; + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::DoHandlePhonebookSendAsL +// --------------------------------------------------------- +void CPostcardOperationOpen::DoHandlePhonebookSendAsL( CPostcardContact& aContact ) + { + CPostcardRecipientWrapper* recWrapper = + CPostcardRecipientWrapper::NewL( iDocument, iAppUi, aContact ); + CleanupStack::PushL( recWrapper ); + + // First remove wait note so that the dialog can be shown + iAppUi.RemoveWaitNote( ); + + // Location asking is done in recipientWrapper + CPostcardContact::TLocation location; + TBool hasLocation = recWrapper->AskLocationL( location ); + CleanupStack::PopAndDestroy( recWrapper ); + + iAppUi.ShowWaitNoteL( R_POSTCARD_WAIT_OPENING, EFalse ); + + if ( !hasLocation ) + { + // Contact not found or cancel selected.. + CContactCard* card = CContactCard::NewL(); + // Ownership moves.. + // The function does not leave before card is set as a member + iAppUi.SetRecipientL( *card ); + CPlainText* emptyText = CPlainText::NewL( + CEditableText::ESegmentedStorage, KPostcardDefaultGreetingSegment ); + // Ownership moves.. + // The function does not leave before card is set as a member + iAppUi.SetTextL( *emptyText ); + } + else + { + // Otherwise location now tells the chosen location + + CContactCard* card = CContactCard::NewLC(); + UpdateContactCardL( *card, aContact, location ); + + CleanupStack::Pop( card ); // card + // Ownership moves.. + // The function does not leave before card is set as a member + iAppUi.SetRecipientL( *card ); + iDocument.SetChanged( EPostcardRecipient ); + iCommit = ETrue; // Remove the original atta way as it's just a phonebook atta + MMsvAttachmentManagerSync& managerSync = iStore->AttachmentManagerExtensionsL(); + TInt textIndex = TMsvIdToIndexL( iText ); + managerSync.RemoveAttachmentL( textIndex ); + iText = 0; + CPlainText* emptyText = CPlainText::NewL( + CEditableText::ESegmentedStorage, KPostcardDefaultGreetingSegment ); + // Ownership moves.. + // The function does not leave before card is set as a member + iAppUi.SetTextL( *emptyText ); + } + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::UpdateContactCardL +// --------------------------------------------------------- +void CPostcardOperationOpen::UpdateContactCardL( CContactCard& aCard, + CPostcardContact& aContact, CPostcardContact::TLocation aLocation ) + { + + // Get contact name, combined last and first name + HBufC* contactName = aContact.GetNameLC(); + if ( contactName->Length() ) + { + // Create a new CContactCard field + AddContactCardFieldL( aCard, *contactName, EPostcardAddressName ); + } + CleanupStack::PopAndDestroy( contactName ); // contactName + + // Handle rest of the address fields + for( TInt i = EPostcardAddressInfo; i <= EPostcardAddressCountry; i++) + { + // Initialize address field only if it's visible to user + // (max. length is not zero) + if ( iAppUi.MaxTextLength( i ) ) + { + HBufC* fieldText = aContact.GetAddressFieldLC( aLocation, + CPostcardContact::ControlIdToAddrField( i ) ); + if ( fieldText->Length() ) + { + // Create a new CContactCard field + AddContactCardFieldL( aCard, *fieldText, i ); + } + CleanupStack::PopAndDestroy( fieldText ); // fieldText + } + } + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::AddContactCardFieldL +// --------------------------------------------------------- +void CPostcardOperationOpen::AddContactCardFieldL( CContactCard& aCard, + const TPtrC& aText, TInt aFieldSelect ) + { + TPostcardUtils::AddContactFieldL(aCard, + TPostcardUtils::ContactItemNameFromId( aFieldSelect ), + aText); + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::ParseSpecialFormatTextL +// --------------------------------------------------------- +void CPostcardOperationOpen::ParseSpecialFormatTextL( CPlainText& aText, + CContactCard& aCard, CPlainText& aGreeting ) + { + TPtrC format( iSpecialFormat ); + TPtrC srcText( aText.Read( 0 , aText.DocumentLength() ) ); + + const TInt KTagLen = 3; + + // Find tags from format and parse source text accordingly + TInt tag; + TInt position = TPostcardUtils::NextTag( format, tag ); + // Eat prefix and tag from format. Assume the format has at least one tag. + format.Set( format.Right( format.Length() - position - KTagLen ) ); + // Eat prefix from source text + srcText.Set( srcText.Right( srcText.Length() - position ) ); + while( position != KErrNotFound ) + { + TInt newTag; + position = TPostcardUtils::NextTag( format, newTag ); + TPtrC text; + if ( position != KErrNotFound ) + { + // Separator string from previous tag to this one. This cannot + // be empty, otherwise text fields cannot be separated from each other. + TPtrC separator( format.Left( position ) ); + TInt separatorPos = srcText.Find( separator ); + TInt srcLen = srcText.Length() - position - separatorPos; + if ( separatorPos == KErrNotFound || srcLen < 0 ) + { + // Unexpected. Cannot parse. + return; + } + text.Set( srcText.Left( separatorPos ) ); + // Eat separator and tag from format + format.Set( format.Right( format.Length() - position - KTagLen ) ); + // Eat text and separator from source + srcText.Set( srcText.Right( srcLen ) ); + } + else + { + // No new tags. Text is source string minus postfix + text.Set( srcText.Left( srcText.Length() - format.Length() ) ); + } + if ( text.Length() ) + { + if ( tag == 0 ) + { + aGreeting.InsertL( 0, text ); + } + else + { + if ( iDocument.MessageType() != EPostcardForward ) + { // Add the fields only when not in Forward mode + TPostcardUtils::AddContactFieldL(aCard, + TPostcardUtils::ContactItemNameFromTag( tag ), + text); + } + } + } + tag = newTag; + } + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::DoHandleSpecialFormatOpenL +// --------------------------------------------------------- +void CPostcardOperationOpen::DoHandleSpecialFormatOpenL( CPlainText& aText ) + { + CContactCard* newCard = CContactCard::NewLC(); // New ContactCard + CPlainText* newText = CPlainText::NewL( CEditableText::ESegmentedStorage, KPostcardDefaultGreetingSegment ); // New PlainText for greeting text + CleanupStack::PushL( newText ); + + ParseSpecialFormatTextL( aText, *newCard, *newText ); + + CleanupStack::Pop(); // newText + iAppUi.SetTextL( *newText ); // AppUI takes the ownership + CleanupStack::Pop(); // newCard + iAppUi.SetRecipientL( *newCard ); + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::ToState +// --------------------------------------------------------- +void CPostcardOperationOpen::ToState( TPostcardOpenState aState ) + { + iLaunchState = aState; + CompleteSelf( KErrNone ); + } + +// --------------------------------------------------------- +// CPostcardOperationOpen::ToErrorState +// --------------------------------------------------------- +void CPostcardOperationOpen::ToErrorState( TInt aResourceId ) + { + SetError( aResourceId ); + iLaunchState = EPostcardOpenError; + CompleteSelf( KErrCancel ); + } + +// EOF