diff -r 000000000000 -r e686773b3f54 phonebookui/Phonebook2/CommandsExtension/src/CPbk2vCardConverter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/CommandsExtension/src/CPbk2vCardConverter.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,663 @@ +/* +* 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 +#include +#include +#include + +// Virtual Phonebook +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// System includes +#include +#include + +// Debugging headers +#include + +/// 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 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 aContacts, + const MVPbkBaseContactField* aField, TInt aDataToSend, + MPbk2vCardConverterObserver& aObserver ) + { + iField = aField; + iFieldLevelOperation = ETrue; + ConvertContactsL(aContacts, aDataToSend, aObserver); + } + +// -------------------------------------------------------------------------- +// CPbk2vCardConverter::ConvertContactsL +// -------------------------------------------------------------------------- +// +void CPbk2vCardConverter::ConvertContactsL + ( const TArray 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