mobilemessaging/unieditor/application/src/UniEditorVCardOperation.cpp
changeset 0 72b543305e3a
--- /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