--- /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 <MsgMediaInfo.h>
+#include <contactmatcher.h>
+#include <msgtextutils.h>
+#include <MsgMediaResolver.h>
+#include <MPbk2ContactNameFormatter.h>
+
+#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<MVPbkContactLink *>(
+ &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