diff -r 000000000000 -r 72b543305e3a mobilemessaging/unieditor/application/src/UniEditorVCardOperation.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobilemessaging/unieditor/application/src/UniEditorVCardOperation.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,524 @@ +/* +* Copyright (c) 2006,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: CUniEditorVCardOperationn, operation for adding VCard into the message +* +*/ + + + +// ========== INCLUDE FILES ================================ + +#include +#include +#include +#include +#include + +#include "UniEditorLogging.h" +#include "UniEditorVCardOperation.h" +#include "UniEditorEnum.h" + +_LIT8( KVCardMiMeType, "text/X-vCard" ); +_LIT( KTempVCardFileName, "vCard.vcf" ); +_LIT( KTempVCardFileSuffix, ".vcf"); + +_LIT(KInvalidFileNameChars, "?*<>/\"|\\:"); +_LIT(KReplaceChar, "_"); + +// --------------------------------------------------------- +// CUniEditorVCardOperation::NewL +// +// Factory method. +// --------------------------------------------------------- +// +CUniEditorVCardOperation* CUniEditorVCardOperation::NewL( + MUniEditorOperationObserver& aObserver, + CUniEditorDocument& aDocument, + RFs& aFs ) + { + CUniEditorVCardOperation* self = new ( ELeave ) CUniEditorVCardOperation( + aObserver, + aDocument, + aFs ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::CUniEditorVCardOperation +// +// Constructor. +// --------------------------------------------------------- +// +CUniEditorVCardOperation::CUniEditorVCardOperation( + MUniEditorOperationObserver& aObserver, + CUniEditorDocument& aDocument, + RFs& aFs ) : + CUniEditorOperation( aObserver, aDocument, aFs, EUniEditorOperationVCard ), + iNewVCardAttaId( KMsvNullIndexEntryId ), + iAddedVCardCount( 0 ), + iCurrentContactIndex( -1 ) + { + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::CUniEditorVCardOperation +// +// Destructor. iContact, iContacts and iCheckNames must be deleted +// in this order! +// --------------------------------------------------------- +// +CUniEditorVCardOperation::~CUniEditorVCardOperation() + { + Cancel(); + + delete iContact; + delete iContacts; + delete iCheckNames; + delete iStoreContact; + delete iVCardEng; + delete iVCardExportOp; + delete iEditStore; + + iVCardStream.Close(); + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::ConstructL +// +// 2nd phase constructor. +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::ConstructL() + { + BaseConstructL(); + + iCheckNames = CMsgCheckNames::NewL(); + + iVCardEng = CVPbkVCardEng::NewL( iCheckNames->ContactMatcher().GetContactManager() ); + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::Start +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::Start() + { + iOperationState = EUniProcessVCardStart; + CompleteSelf( KErrNone ); + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::GetContactsL +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::GetContactsL() + { + ResetAll(); + + // Create a new empty array + iContacts = CVPbkContactLinkArray::NewL(); + + iCheckNames->FetchRecipientsL( *iContacts, CMsgCheckNames::EMsgTypeAll ); + + if ( iContacts->Count() > 0 ) + { + iOperationState = EUniProcessVCardExportNext; + CompleteSelf( KErrNone ); + } + else + { + iOperationState = EUniProcessVCardComplete; + CompleteSelf( KErrNone ); + } + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::ExportVCardAndAddAttachmentL +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::ExportVCardAndAddAttachmentL() + { + Reset(); + + // Initial value is -1, so we start to handle the contact in index 0. + iCurrentContactIndex++; + + if ( iCurrentContactIndex < iContacts->Count() ) + { + // Handle next contact. + iContact = const_cast( + &iContacts->At( iCurrentContactIndex ) )->CloneLC(); + CleanupStack::Pop(); // Cloned link. + + iOperationState = EUniProcessVCardCreatingEmptyVCardAttachment; + CompleteSelf( KErrNone ); + } + else + { + // No more contacts, so we can clean up and complete. + // Clean up is done, in order to get iContact deleted, before + // its contact manager is deleted. Bad design in virtual phonebook. + iOperationState = EUniProcessVCardComplete; + CompleteSelf( KErrNone ); + } + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::AddedVCardCount +// +// --------------------------------------------------------- +// +TInt CUniEditorVCardOperation::AddedVCardCount() + { + return iAddedVCardCount; + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::CreateEmptyVCardAttachmentL +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::CreateEmptyVCardAttachmentL() + { + iCheckNames->ContactMatcher().GetStoreContactL( *iContact, &iStoreContact ); + + // If this store contact is a group, then we don't add it to object list. + if ( !iStoreContact->Group() ) + { + MVPbkStoreContactFieldCollection& fieldCollection = iStoreContact->Fields(); + + HBufC* contactName = iCheckNames->ContactMatcher().ContactNameFormatterL().GetContactTitleL( fieldCollection, 0 ); + + // Form a name for the attachment. If contactName is NULL, then + // attachment is name vCard.vcf. + if ( contactName ) + { + // Reserve more space for filename to include .vcf + contactName = contactName->ReAllocL( + contactName->Length() + KTempVCardFileSuffix().Length() ); // ReAllocL deletes original + CleanupStack::PushL( contactName ); + + // Modify contact's name to be a file name. + TPtr contactFilePtr = contactName->Des(); + contactFilePtr.Append( KTempVCardFileSuffix ); + } + else + { + // Use hard coded filename vCard.vcf. + contactName = KTempVCardFileName().AllocLC(); + } + + // Remove illegal characters from file name. Phonebook allows characters + // to be inserted to contact's name, which are not allowed by Symbian file + // system. + TPtr contactNamePtr = contactName->Des(); // May contain illegal characters + HBufC* validName = HBufC::NewLC( contactName->Length() ); + TPtr validNamePtr = validName->Des(); // Does not contain illegal characters + + // Loop throuh characters and replace illegal characters with underscore. + for ( TInt i = 0; i < contactName->Length(); ++i ) + { + TChar ch = contactNamePtr[i]; + if ( KInvalidFileNameChars().Locate( ch ) == KErrNotFound ) + { + validNamePtr.Append( ch ); + } + else + { + validNamePtr.Append( KReplaceChar ); + } + } + validNamePtr.TrimAll(); + + // Create empty stored attachment to store. + RFile newVCardFile; + iEditStore = iDocument.Mtm().Entry().EditStoreL(); + MMsvAttachmentManagerSync& managerSync = iEditStore->AttachmentManagerExtensionsL(); + CMsvAttachment* attachment = CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); + CleanupStack::PushL( attachment ); + managerSync.CreateAttachmentL( validNamePtr, newVCardFile, attachment ); + CleanupStack::Pop( attachment); // ownership transferred + CleanupStack::PopAndDestroy( 2, contactName ); // validName, contactName + + // Store the id, it is used when attachment created above is saved to + // object list. + iNewVCardAttaId = attachment->Id(); + iVCardStream.Attach( newVCardFile ); + + // Call vCard engine to export a contact to a stored attachment. + // Engine will call VPbkSingleContactOperationComplete or + // VPbkSingleContactOperationFailed + iVCardExportOp = iVCardEng->ExportVCardL( iVCardStream, + *iContact, + *this); + SetPending(); + } + else + { + // Don't add group name as a vCard, results are not nice. + iOperationState = EUniProcessVCardExportNext; + CompleteSelf( KErrNone ); + } + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::DoCancelCleanup +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::DoCancelCleanup() + { + Reset(); + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::RunL +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::RunL() + { + PrintOperationAndState(); + if ( iStatus.Int() != KErrNone ) + { + SetError( iStatus.Int() ); + iOperationState = EUniProcessVCardError; + } + + switch( iOperationState ) + { + case EUniProcessVCardStart: + { + // Get contacts to export + GetContactsL(); + break; + } + case EUniProcessVCardExportNext: + { + // Start handling of single contact. + ExportVCardAndAddAttachmentL(); + break; + } + case EUniProcessVCardCreatingEmptyVCardAttachment: + { + // Create an empty attachment to message store. + CreateEmptyVCardAttachmentL(); + break; + } + case EUniProcessVCardComplete: + { + // All contacts handled, tell appUi that we are complete. + ReportEvent( EUniEditorOperationComplete ); + break; + } + case EUniProcessVCardCancel: + { + // Somebody cancelled us, tell appUi that we were cancelled. + ReportEvent( EUniEditorOperationCancel ); + break; + } + case EUniProcessVCardError: + { + Reset(); + iObserver.EditorOperationEvent( EUniEditorOperationVCard, + EUniEditorOperationError ); + break; + } + default: + { + // Huh, this can also be possible. + iObserver.EditorOperationEvent( EUniEditorOperationVCard, + EUniEditorOperationError ); + break; + } + } + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::VPbkSingleContactOperationComplete +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::VPbkSingleContactOperationComplete( MVPbkContactOperationBase& aOperation, + MVPbkStoreContact* /*aContact*/ ) + { + iLastError = KErrNone; + + if ( &aOperation == iVCardExportOp ) + { + TDataType type( KVCardMiMeType ); + + // Release and close stream. + TRAP_IGNORE( iVCardStream.CommitL() ); + iVCardStream.Close(); + + // Get attachment handle again, since iVCardStream.Attach() function + // call makes the original handle invalid. + MMsvAttachmentManager* manager = NULL; + TRAP_IGNORE( manager = &iEditStore->AttachmentManagerL() ); + + RFile storedVCard; + TRAPD( err, storedVCard = manager->GetAttachmentFileL( iNewVCardAttaId ) ); + + if ( err == KErrNone ) + { + // Add stored attachment to object list. + CMsgMediaInfo* media = NULL; + + TRAP_IGNORE( media = CMsgMediaInfo::NewL( storedVCard, + type, + EMsgMediaUnknown ) ); + + // Count the size of the message after current vCard is inserted. + TInt vCardSize = media->FileSize(); + TInt sizeAfterInsert = iDocument.MessageSize() + vCardSize; + + if ( sizeAfterInsert <= iDocument.MaxMessageSize() ) + { + // Must be committed and deleted since only one client can access + // entry in edit mode and AddStoredAttachmentL function want's to + // edit it too. + TRAP_IGNORE( iEditStore->CommitL() ); + + delete iEditStore; + iEditStore = NULL; + + TRAP_IGNORE( iDocument.DataModel()->AddStoredAttachmentL( iNewVCardAttaId, + media ) ); + media = NULL; // Not owned anymore + + // Increase success counter, used to show correct note + // when all contacts are handled. + iAddedVCardCount++; + + // Object is now saved to unieditor's object list. + } + else + { + // Delete created media info + delete media; + media = NULL; + + TRAP_IGNORE( + { + MMsvAttachmentManagerSync& managerSync = iEditStore->AttachmentManagerExtensionsL(); + managerSync.RemoveAttachmentL( CUniDataUtils::IndexPositionOfAttachmentL( *manager, + iNewVCardAttaId ) ); + iEditStore->CommitL(); + iNewVCardAttaId = KMsvNullIndexEntryId; + }); + + SetError( EUniInsertTooBig ); + + // Try whether next vCard fits to max message size. + } + + // Current contact handled, start next one. Whether there still + // exist unhandled contacts, it is decided elsewhere. + iOperationState = EUniProcessVCardExportNext; + CompleteOperation( KErrNone ); + + // Close temporary attachment handle. + storedVCard.Close(); + } + else + { + // Couldn't get a handle to a stored attachment, + // let's give up. + iOperationState = EUniProcessVCardError; + CompleteOperation( err ); + } + } + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::VPbkSingleContactOperationFailed +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::VPbkSingleContactOperationFailed( + MVPbkContactOperationBase& /*aOperation*/, TInt aError ) + { + iLastError = aError; + + SetError( iLastError ); + + Reset(); + + iOperationState = EUniProcessVCardError; + CompleteOperation( iLastError ); + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::Reset +// +// --------------------------------------------------------- +void CUniEditorVCardOperation::Reset() + { + delete iContact; + iContact = NULL; + + delete iStoreContact; + iStoreContact = NULL; + + delete iVCardExportOp; + iVCardExportOp = NULL; + + delete iEditStore; + iEditStore = NULL; + + iNewVCardAttaId = KMsvNullIndexEntryId; + iVCardStream.Close(); + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::ResetAll +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::ResetAll() + { + // First reset counters. + iCurrentContactIndex = -1; + iAddedVCardCount = 0; + + if ( iContacts ) + { + delete iContacts; + iContacts = NULL; + } + + Reset(); + + // Reset any previous errors, since we are started again. + ResetErrors(); + } + +// --------------------------------------------------------- +// CUniEditorVCardOperation::ReportEvent +// +// --------------------------------------------------------- +// +void CUniEditorVCardOperation::ReportEvent( TUniEditorOperationEvent aEvent ) + { + iObserver.EditorOperationEvent( EUniEditorOperationVCard, aEvent ); + } + +// EOF