--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/CommandsExtension/src/CPbk2vCardConverter.cpp Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,664 @@
+/*
+* 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 vCard converter.
+*
+*/
+
+
+#include "CPbk2vCardConverter.h"
+
+// Phonebook 2
+#include "Pbk2SendCmdUtils.h"
+#include <CPbk2AttachmentFile.h>
+#include <Pbk2Commands.rsg>
+#include <Pbk2CmdExtRes.rsg>
+#include <MPbk2ContactLinkIterator.h>
+
+// Virtual Phonebook
+#include <CVPbkVCardEng.h>
+#include <MVPbkStoreContact.h>
+#include <MPbk2ContactNameFormatter.h>
+#include <MVPbkContactOperationBase.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkContactFieldData.h>
+#include <CVPbkContactManager.h>
+#include <MVPbkFieldType.h>
+#include <TVPbkFieldTypeMapping.h>
+#include <MVPbkContactFieldTextData.h>
+#include <MVPbkContactFieldDateTimeData.h>
+#include <MVPbkContactFieldBinaryData.h>
+#include <MVPbkContactFieldUriData.h>
+#include <MVPbkContactLink.h>
+
+// System includes
+#include <barsread.h>
+#include <coemain.h>
+
+// Debugging headers
+#include <Pbk2Debug.h>
+
+/// Unnamed namespace for local functions
+namespace {
+
+// CONSTANTS
+_LIT(KPbk2vCardFileExtension, ".vcf");
+
+// LOCAL FUNCTIONS
+
+
+/**
+ * Creates an empty vCard file from the given contact.
+ *
+ * @param aFs File server session handle.
+ * @param aContact The contact.
+ * @param aNameFormatter Contact name formatter.
+ * @return Created vCard file.
+ */
+
+CPbk2AttachmentFile* CreateEmptyvCardFileL
+ ( RFs& aFs, const MVPbkStoreContact& aContact,
+ MPbk2ContactNameFormatter& aNameFormatter )
+ {
+ // Create the file name using contact's name
+ HBufC* name = aNameFormatter.GetContactTitleL
+ ( aContact.Fields(),
+ MPbk2ContactNameFormatter::EPreserveLeadingSpaces );
+ CleanupStack::PushL(name);
+ HBufC* fileNameBuf = HBufC::NewLC(
+ name->Length() + KPbk2vCardFileExtension().Length());
+ TPtr fileName = fileNameBuf->Des();
+ fileName = *name;
+ fileName.Append(KPbk2vCardFileExtension);
+
+ // Create attachment file object
+ CPbk2AttachmentFile* result = CPbk2AttachmentFile::NewL
+ (fileName, aFs, EFileWrite|EFileStream|EFileShareExclusive);
+
+ CleanupStack::PopAndDestroy(2); // fileNameBuf, name
+ return result;
+ }
+
+#ifdef _DEBUG
+enum TPanicCode
+ {
+ EPanicLogic_AddFieldToContactL = 1,
+ EPanicInvalidStorageType,
+ EPanicPostCond_PrepareContactL
+ };
+
+void Panic(TPanicCode aReason)
+ {
+ _LIT(KPanicText, "CPbk2vCardConverter");
+ User::Panic(KPanicText,aReason);
+ }
+#endif // _DEBUG
+
+
+} /// namespace
+
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::CPbk2vCardConverter
+// --------------------------------------------------------------------------
+//
+inline CPbk2vCardConverter::CPbk2vCardConverter
+ (RFs& aFs, CVPbkContactManager& aEngine, CVPbkVCardEng& aVCardEngine,
+ MPbk2ContactNameFormatter& aNameFormatter) :
+ CActive(EPriorityIdle),
+ iFs(aFs), iEngine(aEngine), iVCardEngine(aVCardEngine),
+ iNameFormatter(aNameFormatter), iField(NULL),
+ iObserver(NULL), iOpIndex(0), iFieldLevelOperation(EFalse),
+ iNextDriveTried(EFalse)
+ {
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::~CPbk2vCardConverter
+// --------------------------------------------------------------------------
+//
+CPbk2vCardConverter::~CPbk2vCardConverter()
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter, destructor (0x%x)"), this);
+ Cancel();
+ if (iVcardFiles)
+ {
+ iVcardFiles->ResetAndDestroy();
+ delete iVcardFiles;
+ }
+ delete iVCardFile;
+ delete iRetrieveOperation;
+ delete iVCardContact;
+ iFileWriteStream.Close();
+ delete iContactOperation;
+ iContacts.Reset(); // iContacts does not own its items
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::ConstructL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2vCardConverter::ConstructL()
+ {
+ CActiveScheduler::Add(this);
+ iVcardFiles = new(ELeave) CPbk2AttachmentFileArray(1);
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::CPbk2vCardConverter
+// --------------------------------------------------------------------------
+//
+CPbk2vCardConverter* CPbk2vCardConverter::NewL
+ ( RFs& aFs, CVPbkContactManager& aEngine,
+ CVPbkVCardEng& aVCardEngine,
+ MPbk2ContactNameFormatter& aNameFormatter )
+ {
+ CPbk2vCardConverter* self = new(ELeave) CPbk2vCardConverter
+ ( aFs,aEngine,aVCardEngine, aNameFormatter );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::ConvertContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::ConvertContactL
+ ( const TArray<MVPbkStoreContact*> aContacts,
+ const MVPbkBaseContactField* aField, TInt aDataToSend,
+ MPbk2vCardConverterObserver& aObserver )
+ {
+ iField = aField;
+ iFieldLevelOperation = ETrue;
+ ConvertContactsL(aContacts, aDataToSend, aObserver);
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::ConvertContactsL
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::ConvertContactsL
+ ( const TArray<MVPbkStoreContact*> aContacts,
+ TInt aDataToSend, MPbk2vCardConverterObserver& aObserver )
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::ConvertContactsL(0x%x)"), this);
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::ConvertContactsL, Contacts Count=%d"),
+ aContacts.Count());
+ Reset();
+ iObserver = &aObserver;
+ iDataToSend = aDataToSend;
+ for (TInt i = 0; i < aContacts.Count(); ++i)
+ {
+ iContacts.AppendL(aContacts[i]);
+ }
+
+ Start();
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::ConvertContactsL, end (0x%x)"), this);
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::ConvertContactsL
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::ConvertContactsL
+ ( MPbk2ContactLinkIterator& aIterator, TInt aDataToSend,
+ MPbk2vCardConverterObserver& aObserver )
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::ConvertContactsL, dataToSend=%d"), aDataToSend);
+ Reset();
+ iObserver = &aObserver;
+ iDataToSend = aDataToSend;
+ iIterator = &aIterator;
+ Start();
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::ConvertContactsL, end (0x%x)"), this);
+ }
+
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::FileNames
+// --------------------------------------------------------------------------
+//
+MDesC16Array& CPbk2vCardConverter::FileNames() const
+ {
+ return ( *iVcardFiles );
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::Reset
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::Reset()
+ {
+ iIterator = NULL;
+ iVcardFiles->ResetAndDestroy();
+ iDataToSend = ESendAllData;
+ if (!iFieldLevelOperation)
+ {
+ iField = NULL;
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::AttachmentFileArray
+// --------------------------------------------------------------------------
+//
+CPbk2AttachmentFileArray& CPbk2vCardConverter::AttachmentFileArray()
+ {
+ return *iVcardFiles;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::RunL
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::RunL()
+ {
+ if ( iIterator && iIterator->HasNext() )
+ {
+ HandleNextContactL( NULL );
+ }
+ else if (iOpIndex < iContacts.Count())
+ {
+ HandleNextContactL( iContacts[iOpIndex] );
+ ++iOpIndex;
+ }
+ else
+ {
+ iObserver->ConversionDone(iOpIndex);
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::DoCancel
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::DoCancel()
+ {
+ // Do nothing
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::RunError
+// --------------------------------------------------------------------------
+//
+TInt CPbk2vCardConverter::RunError(TInt aError)
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::RunError=%d"), aError);
+ Reset();
+ iObserver->ConversionError(aError);
+ return aError;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::VPbkSingleContactOperationComplete
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::VPbkSingleContactOperationComplete
+ ( MVPbkContactOperationBase& /*aOperation*/ ,
+ MVPbkStoreContact* aContact )
+ {
+ if ( iRetrieveOperation )
+ {
+ delete iRetrieveOperation;
+ iRetrieveOperation = NULL;
+ TRAPD( err, HandleNextContactL( aContact ) );
+ delete aContact;
+ aContact = NULL;
+ if ( err != KErrNone )
+ {
+ CCoeEnv::Static()->HandleError( err );
+ }
+ }
+ else
+ {
+ delete iContactOperation;
+ iContactOperation = NULL;
+
+ // Delete temp contact
+ delete iVCardContact;
+ iVCardContact = NULL;
+
+ FinalizeVCardExport();
+
+ IssueRequest();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::VPbkSingleContactOperationFailed
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::VPbkSingleContactOperationFailed
+ ( MVPbkContactOperationBase& /*aOperation*/, TInt aError )
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::VPbkSingleContactOperationFailed (0x%x)"), this);
+ if ( iRetrieveOperation )
+ {
+ delete iRetrieveOperation;
+ iRetrieveOperation = NULL;
+ }
+ else
+ {
+ delete iContactOperation;
+ iContactOperation = NULL;
+
+ iFileWriteStream.Close();
+
+ if ( iNextDriveTried )
+ {
+ delete iVCardFile;
+ iVCardFile = NULL;
+ RunError( aError );
+ }
+ else
+ {
+ TRAPD( err,
+ {
+ // Try to switch next drive if previous failed
+ iVCardFile->SwitchDriveL();
+ iFileWriteStream.Attach( iVCardFile->File() );
+ iContactOperation = iVCardEngine.ExportVCardL
+ ( iFileWriteStream, *iVCardContact, *this );
+ }); // TRAPD
+
+ if ( err != KErrNone )
+ {
+ RunError( aError );
+ }
+
+ iNextDriveTried = ETrue;
+ }
+ }
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::VPbkSingleContactOperationFailed, end"), this);
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::CreatevCardFileL
+// Creates a file containing vCard of aContact and attaches the file to
+// internal list of files.
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::CreatevCardFileL(MVPbkStoreContact* aContact)
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::CreatevCardFileL (0x%x)"), this);
+
+ // Check first, is the contact item empty
+ // If the contact is not empty, file it so it gets sent
+ if (!Pbk2SendCmdUtils::IsContactEmpty(aContact))
+ {
+ iVCardFile = CreateEmptyvCardFileL(iFs, *aContact, iNameFormatter);
+ // Create temp handle, so that iVCardFile stays valid until we close
+ // it. Stream will take care of closing tempHandle when closing stream
+ RFile tempHandle;
+ tempHandle.Duplicate( iVCardFile->File() );
+ iFileWriteStream.Attach( tempHandle );
+
+ iContactOperation =
+ iVCardEngine.ExportVCardL(iFileWriteStream, *aContact, *this);
+ }
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::CreatevCardFileL, end (0x%x)"), this);
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::PrepareContactL
+// --------------------------------------------------------------------------
+//
+MVPbkStoreContact* CPbk2vCardConverter::PrepareContactL
+ ( MVPbkStoreContact* aContact )
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::PrepareContactL (0x%x)"), this);
+ MVPbkStoreContact* vCardContact = NULL;
+ // Create a temporary contact
+ vCardContact = aContact->ParentStore().CreateNewContactLC();
+ // Copy currently focused field's data to a dummy contact
+ FillTemporaryContactL(*vCardContact, *aContact, *iField);
+
+ __ASSERT_DEBUG(vCardContact, Panic(EPanicPostCond_PrepareContactL));
+
+ CleanupStack::Pop(); // vCardContact
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::PrepareContactL, end (0x%x)"), this);
+ return vCardContact;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::FillTemporaryContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::FillTemporaryContactL
+ ( MVPbkStoreContact& aDestItem,
+ const MVPbkStoreContact& aSourceItem,
+ const MVPbkBaseContactField& aDataField ) const
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::FillTemporaryContactL (0x%x)"), this);
+ if (iDataToSend == ESendAllData)
+ {
+ TInt fieldCount = aSourceItem.Fields().FieldCount();
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::FillTemporaryContactL, fieldCount=%d"),
+ fieldCount);
+
+ const MVPbkStoreContactFieldCollection& fieldSet =
+ aSourceItem.Fields();
+ for (TInt i=0; i < fieldCount; ++i)
+ {
+ const MVPbkStoreContactField& field = fieldSet.FieldAt(i);
+ AddFieldToContactL(aDestItem, field);
+ }
+ }
+ else if (iDataToSend == ESendAllDataWithoutPicture)
+ {
+ TInt fieldCount = aSourceItem.Fields().FieldCount();
+ const MVPbkStoreContactFieldCollection& fieldSet =
+ aSourceItem.Fields();
+ const MVPbkFieldType& thumbnailFieldType =
+ Pbk2SendCmdUtils::ReadFieldTypeFromResL(
+ R_THUMBNAIL_FIELD_TYPE, iEngine.FieldTypes());
+ const MVPbkFieldType& imageFieldType =
+ Pbk2SendCmdUtils::ReadFieldTypeFromResL(
+ R_IMAGE_FIELD_TYPE, iEngine.FieldTypes());
+ for (TInt i=0; i < fieldCount; ++i)
+ {
+ const MVPbkStoreContactField& field = fieldSet.FieldAt(i);
+ // Do not add thumbnail or image
+ if (!Pbk2SendCmdUtils::IsFieldMatching(
+ field, thumbnailFieldType, iEngine.FieldTypes()) &&
+ !Pbk2SendCmdUtils::IsFieldMatching(
+ field, imageFieldType, iEngine.FieldTypes()))
+ {
+ AddFieldToContactL(aDestItem, field);
+ }
+ }
+ }
+ else // ESendCurrentItem
+ {
+ // Actual single data field
+ AddFieldToContactL(aDestItem, aDataField);
+
+ // According to specification lastname & firstname
+ // (when existing) must be added when sending single item
+ const MVPbkBaseContactField* lastName =
+ Pbk2SendCmdUtils::FindFieldL(
+ aSourceItem, R_LNAME_FIELD_TYPE, iEngine.FieldTypes());
+ if (lastName)
+ {
+ if (!lastName->FieldData().IsEmpty())
+ {
+ AddFieldToContactL(aDestItem, *lastName);
+ }
+ }
+
+ const MVPbkBaseContactField* firstName =
+ Pbk2SendCmdUtils::FindFieldL(
+ aSourceItem, R_FNAME_FIELD_TYPE, iEngine.FieldTypes());
+ if (firstName)
+ {
+ if (!firstName->FieldData().IsEmpty())
+ {
+ AddFieldToContactL(aDestItem, *firstName);
+ }
+ }
+ }
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::FillTemporaryContactL, end (0x%x)"), this);
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::AddFieldToContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::AddFieldToContactL
+ ( MVPbkStoreContact& aDestItem,
+ const MVPbkBaseContactField& aSourceField ) const
+ {
+ const MVPbkFieldType* fieldType = aSourceField.BestMatchingFieldType();
+ if ( fieldType )
+ {
+ MVPbkStoreContactField* dstField =
+ aDestItem.CreateFieldLC( *fieldType );
+
+ __ASSERT_DEBUG( dstField, Panic( EPanicLogic_AddFieldToContactL ) );
+
+ switch (dstField->FieldData().DataType())
+ {
+ case EVPbkFieldStorageTypeText:
+ {
+ TPtrC data = MVPbkContactFieldTextData::Cast(
+ aSourceField.FieldData()).Text();
+ MVPbkContactFieldTextData::Cast(dstField->FieldData())
+ .SetTextL(data);
+ break;
+ }
+ case EVPbkFieldStorageTypeUri:
+ {
+ TPtrC data = MVPbkContactFieldUriData::Cast(
+ aSourceField.FieldData()).Uri();
+ MVPbkContactFieldUriData::Cast(dstField->FieldData())
+ .SetUriL(data);
+ break;
+ }
+ case EVPbkFieldStorageTypeDateTime:
+ {
+ TTime time = MVPbkContactFieldDateTimeData::Cast(
+ aSourceField.FieldData()).DateTime();
+ MVPbkContactFieldDateTimeData::Cast(dstField->FieldData())
+ .SetDateTime(time);
+ break;
+ }
+ case EVPbkFieldStorageTypeBinary:
+ {
+ TPtrC8 data = MVPbkContactFieldBinaryData::Cast(
+ aSourceField.FieldData()).BinaryData();
+ MVPbkContactFieldBinaryData::Cast(dstField->FieldData())
+ .SetBinaryDataL(data);
+ break;
+ }
+ default:
+ {
+ __ASSERT_DEBUG(EFalse, Panic(EPanicInvalidStorageType));
+ break;
+ }
+ }
+ aDestItem.AddFieldL(dstField);
+ CleanupStack::Pop();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::Start
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::Start()
+ {
+ iOpIndex = 0;
+ IssueRequest();
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::HandleNextContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::HandleNextContactL( MVPbkStoreContact* aContact )
+ {
+ if ( aContact )
+ {
+ if (iVCardContact)
+ {
+ delete iVCardContact;
+ iVCardContact = NULL;
+ }
+ iVCardContact = PrepareContactL(aContact);
+ CreatevCardFileL(iVCardContact);
+ }
+ else
+ {
+ MVPbkContactLink* link = iIterator->NextL();
+ CleanupDeletePushL( link );
+ iRetrieveOperation = iEngine.RetrieveContactL( *link, *this );
+ CleanupStack::PopAndDestroy(); // link
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::IssueRequest
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::IssueRequest()
+ {
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ SetActive();
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2vCardConverter::FinalizeVCardExport
+// --------------------------------------------------------------------------
+//
+void CPbk2vCardConverter::FinalizeVCardExport()
+ {
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::FinalizeVCardExport (0x%x)"), this);
+ TRAPD( err,
+ {
+ // commit stream after exportvcard has completed
+ iFileWriteStream.CommitL();
+ iFileWriteStream.Close();
+ iVcardFiles->AppendL(iVCardFile); // Takes ownership
+ iVCardFile = NULL;
+ }); //TRAPD
+
+ if ( err != KErrNone )
+ {
+ RunError( err );
+ }
+
+ PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+ ("CPbk2vCardConverter::FinalizeVCardExport, end (0x%x)"), this);
+ }
+
+// End of File