--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mobilemessaging/postcard/postcardsrc/PostcardContact.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,436 @@
+/*
+* Copyright (c) 2006 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:
+* Postcard application's interface to contacts (Virtual Phonebook
+* and Phonebook2).
+*
+*/
+
+
+
+// INCLUDE FILES
+
+#include <s32file.h>
+#include <aknenv.h>
+#include <AiwServiceHandler.h>
+#include <AiwContactSelectionDataTypes.h>
+#include <CPbk2StoreConfiguration.h>
+#include <VPbkContactStoreUris.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <TVPbkContactStoreUriPtr.h>
+#include <CVPbkContactLinkArray.h>
+#include <TVPbkFieldVersitProperty.h>
+#include <MVPbkStoreContact.h>
+#include <contactmatcher.h>
+#include <akninputblock.h>
+
+#include <Postcard.rsg>
+#include "PostcardContact.h"
+#include "PostcardPanic.h"
+
+// ================= Static Constant Data ===================
+
+// Table to convert from TLocation to virtual phonebook field type parameter
+const TVPbkFieldTypeParameter CPostcardContact::iLocToFieldTypeParam[] =
+ {
+ EVPbkVersitParamPREF,
+ EVPbkVersitParamHOME,
+ EVPbkVersitParamWORK
+ };
+
+// Table to convert from TAddressField to virtual phonebook subfield type
+const TVPbkSubFieldType CPostcardContact::iAddrFieldToSubFieldType[] =
+ {
+ EVPbkVersitSubFieldStreet,
+ EVPbkVersitSubFieldExtendedAddress,
+ EVPbkVersitSubFieldPostalCode,
+ EVPbkVersitSubFieldLocality,
+ EVPbkVersitSubFieldRegion,
+ EVPbkVersitSubFieldCountry
+ };
+
+// Table to convert from TPostcardControls to TAddressField
+const CPostcardContact::TAddressField CPostcardContact::iControlIdToAddrField[] =
+ {
+ CPostcardContact::EAddressFieldExtendedAddress,
+ CPostcardContact::EAddressFieldStreet,
+ CPostcardContact::EAddressFieldPostalCode,
+ CPostcardContact::EAddressFieldLocality,
+ CPostcardContact::EAddressFieldRegion,
+ CPostcardContact::EAddressFieldCountry
+ };
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// Two-phased constructor
+// ---------------------------------------------------------
+CPostcardContact* CPostcardContact::NewL( RFs& aFs )
+ {
+ CPostcardContact* self = new (ELeave) CPostcardContact( aFs );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------
+// Default destructor
+// ---------------------------------------------------------
+CPostcardContact::~CPostcardContact()
+ {
+ delete iStoreContact;
+ delete iContactMatcher;
+ delete iUriArray;
+ delete iAiwServiceHandler;
+ }
+
+// ---------------------------------------------------------
+// CPostcardContact
+// ---------------------------------------------------------
+CPostcardContact::CPostcardContact( RFs& aFs ) : iFs( aFs )
+ {
+ }
+
+
+// ---------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------
+void CPostcardContact::ConstructL( )
+ {
+#ifdef __WINS__
+ // Use default contact database store
+ iUriArray = CVPbkContactStoreUriArray::NewL();
+ TVPbkContactStoreUriPtr uriPtr(VPbkContactStoreUris::DefaultCntDbUri());
+ iUriArray->AppendL(uriPtr);
+#else
+ // Get store configuration from phonebook2
+ CPbk2StoreConfiguration* storeConfiguration =
+ CPbk2StoreConfiguration::NewL();
+ CleanupStack::PushL(storeConfiguration);
+
+ iUriArray = storeConfiguration->CurrentConfigurationL();
+ CleanupStack::PopAndDestroy( storeConfiguration ); // storeConfiguration
+#endif
+
+ // Create contact matcher
+ iContactMatcher = CContactMatcher::NewL( &iFs );
+ iContactMatcher->OpenStoreL(*iUriArray);
+
+ iShutdown = EFalse;
+ }
+
+// ---------------------------------------------------------
+// HasLocationL
+// ---------------------------------------------------------
+TBool CPostcardContact::HasLocationL(TLocation aLocation) const
+ {
+ // A small buffer to see if the contact has any fields
+ // defined for the location aLocation
+ const TInt KBufLen = 8;
+ TBuf<KBufLen> contactString;
+
+ GetContactStringL(contactString, aLocation);
+ return contactString.Length() > 0;
+ }
+
+// ---------------------------------------------------------
+// GetContactStringL
+// ---------------------------------------------------------
+void CPostcardContact::GetContactStringL(TDes& aBuffer,
+ TLocation aAddressLocation) const
+ {
+ static const TAddressField addrFields[] =
+ {
+ EAddressFieldStreet,
+ EAddressFieldExtendedAddress,
+ EAddressFieldPostalCode,
+ EAddressFieldLocality,
+ EAddressFieldRegion,
+ EAddressFieldCountry
+ };
+ const TInt KNumAddrFields = sizeof(addrFields) / sizeof(addrFields[0]);
+
+ _LIT(KPostcardAddressSelectionSeparator, ", ");
+ TPtrC fieldSeparator(KPostcardAddressSelectionSeparator);
+
+ aBuffer.Zero();
+ TInt bufferRemaining = aBuffer.MaxLength();
+
+ // Read address fields from the contact. Add field to buffer if there
+ // is space for the separator and at least one more character.
+ for(TInt i = 0; i < KNumAddrFields && bufferRemaining > fieldSeparator.Length(); i++)
+ {
+ HBufC* fieldText = GetAddressFieldLC(aAddressLocation, addrFields[i]);
+ if (fieldText->Length() > 0)
+ {
+ // Add the separator if this is not the first non-empty field
+ if (aBuffer.Length() > 0)
+ {
+ aBuffer.Append(fieldSeparator);
+ bufferRemaining -= fieldSeparator.Length();
+ }
+
+ if (bufferRemaining > fieldText->Length())
+ {
+ aBuffer.Append(*fieldText);
+ }
+ else
+ {
+ aBuffer.Append(fieldText->Left(bufferRemaining));
+ }
+ bufferRemaining = aBuffer.MaxLength() - aBuffer.Length();
+ }
+ CleanupStack::PopAndDestroy( fieldText ); // fieldText
+ }
+ }
+
+// ---------------------------------------------------------
+// GetAddressFieldLC
+// ---------------------------------------------------------
+HBufC* CPostcardContact::GetAddressFieldLC(TLocation aLocation,
+ TAddressField aAddressField) const
+ {
+ return GetContactFieldLC(EVPbkVersitNameADR,
+ AddrFieldToSubFieldType(aAddressField),
+ LocToFieldTypeParam(aLocation));
+ }
+
+// ---------------------------------------------------------
+// FetchContactL
+// ---------------------------------------------------------
+void CPostcardContact::FetchContactL()
+ {
+ // Fetch contact from Phonebook using AIW
+
+ if (!iAiwServiceHandler)
+ {
+ // Create AIW service handler
+ iAiwServiceHandler = CAiwServiceHandler::NewL();
+ iAiwServiceHandler->AttachL(R_POSTCARD_SINGLE_ENTRY_FETCH_INTEREST);
+ }
+
+
+ // A new contact is selected. Delete contact in case FetchContactL()
+ // was called before.
+ delete iStoreContact;
+ iStoreContact = NULL;
+
+ CAiwGenericParamList& inList = iAiwServiceHandler->InParamListL();
+ InitAiwContactFetchParamL( inList );
+
+ iAiwServiceHandler->ExecuteServiceCmdL( KAiwCmdSelect, inList,
+ iAiwServiceHandler->OutParamListL(), 0, this);
+
+ // Assign an input blocker, which will call cancel to phonebook
+ // e.g. if Postcard is closed via FSW.
+ CAknInputBlock* inputBlock = CAknInputBlock::NewCancelHandlerLC( this );
+
+ iActSchedWait.Start(); // wait ExecuteServiceCmdL() to complete
+
+ CleanupStack::PopAndDestroy( inputBlock );
+
+ if ( iShutdown )
+ {
+ // This leave will be catched in AppUi's DoEditAddressL function.
+ User::Leave( KLeaveExit );
+ }
+ }
+
+// ---------------------------------------------------------
+// FetchContactL
+// ---------------------------------------------------------
+void CPostcardContact::FetchContactL(RFile& aFile)
+ {
+ __ASSERT_DEBUG( !iStoreContact, Panic(EPostcardPanicCoding));
+
+ // Using streams would be more elegant but Phonebook2 impletes it this
+ // way. Writes the descriptor to a file directly without a length.
+ TInt fileSize;
+ User::LeaveIfError( aFile.Size( fileSize ) );
+ HBufC8* buf = HBufC8::NewLC( fileSize );
+ TPtr8 ptr = buf->Des();
+ User::LeaveIfError( aFile.Read( ptr ) );
+ CVPbkContactLinkArray* linkArray = CVPbkContactLinkArray::NewLC(
+ *buf, iContactMatcher->GetContactStoresL());
+ if( linkArray->Count() == 0 )
+ {
+ User::Leave( KErrNotFound );
+ }
+ iContactMatcher->GetStoreContactL( linkArray->At( 0 ), &iStoreContact );
+ CleanupStack::PopAndDestroy( 2, buf ); // linkArray, buf
+ }
+
+// ---------------------------------------------------------
+// HandleNotifyL
+// ---------------------------------------------------------
+TInt CPostcardContact::HandleNotifyL(TInt /*aCmdId*/, TInt aEventId,
+ CAiwGenericParamList& aEventParamList,
+ const CAiwGenericParamList& /*aInParamList*/)
+ {
+
+ switch(aEventId)
+ {
+ case KAiwEventOutParamCheck: // fall through
+ case KAiwEventQueryExit:// fall through
+ // It is always ok for us to exit. Edited postcard will be
+ // saved to drafts.
+ return ETrue;
+
+ case KAiwEventCompleted:
+ // Fetch completed with or without a contact
+ TRAP_IGNORE(HandleAiwEventCompletedL(aEventParamList));
+ // Leave in HandleAiwEventCompletedL() is not progated further.
+ // After that the Postcard wouldn't respond to UI events. Even when
+ // AsyncStop() is called. Maybe Phonebook cannot handle a leave
+ // from here properly.
+
+ // Fallthrough
+ case KAiwEventCanceled:
+ // Fetch was cancelled by user or red key pressed
+ // Fallthrough
+ case KAiwEventError:
+ // Fetch is complete, there was an error
+ if (iActSchedWait.IsStarted())
+ {
+ // End nested active scheduler loop
+ iActSchedWait.AsyncStop();
+ }
+ break;
+ default:
+ Panic(EPostcardPanicAiwEvent);
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// HandleAiwEventCompleted
+// ---------------------------------------------------------
+void CPostcardContact::HandleAiwEventCompletedL(
+ CAiwGenericParamList& aEventParamList)
+ {
+ // Single item fetch. The result should be a contact link array with
+ // 1 contact links and one contact field.
+ __ASSERT_ALWAYS(aEventParamList.Count() == 2,
+ Panic(EPostcardPanicAiwEventParam));
+ const TAiwGenericParam& param = aEventParamList[0];
+ __ASSERT_ALWAYS(param.SemanticId() == EGenericParamContactLinkArray,
+ Panic(EPostcardPanicAiwEventParam));
+ __ASSERT_DEBUG(param.Value().TypeId() == EVariantTypeDesC8,
+ Panic(EPostcardPanicAiwEventParam));
+ TPtrC8 contactLinks = param.Value().AsData();
+ CVPbkContactLinkArray* linkArray = CVPbkContactLinkArray::NewLC(
+ contactLinks, iContactMatcher->GetContactStoresL() );
+ TInt linkCount = linkArray->Count();
+ __ASSERT_DEBUG(linkCount <= 1, Panic(EPostcardPanicAiwEventParam));
+ if (linkCount) // user selected a contact
+ {
+ iContactMatcher->GetStoreContactL( linkArray->At( 0 ), &iStoreContact );
+ }
+ CleanupStack::PopAndDestroy( linkArray ); // linkArray
+ }
+
+// ---------------------------------------------------------
+// InitAiwContactFetchParamL
+// ---------------------------------------------------------
+void CPostcardContact::InitAiwContactFetchParamL(
+ CAiwGenericParamList& aParamList ) const
+ {
+ TAiwGenericParam param( EGenericParamContactSelectionData );
+ TAiwSingleEntrySelectionDataV1 selectionData;
+ param.Value().Set( TAiwSingleEntrySelectionDataV1Pckg( selectionData ) );
+ aParamList.AppendL( param );
+
+ param.Reset();
+ param.SetSemanticId( EGenericParamContactStoreUriArray );
+ param.Value().Set( *iUriArray->PackLC() );
+ aParamList.AppendL( param );
+ CleanupStack::PopAndDestroy(); // packed uriArray
+ }
+
+// ---------------------------------------------------------
+// GetNameLC()
+// ---------------------------------------------------------
+HBufC* CPostcardContact::GetNameLC() const
+ {
+ // GetNameL() returns NULL if the contact has no name defined
+ HBufC* nameText = iContactMatcher->GetNameL(iStoreContact->Fields());
+ if (nameText)
+ {
+ CleanupStack::PushL(nameText);
+ }
+ else
+ {
+ nameText = HBufC::NewLC(0);
+ }
+ return nameText;
+ }
+
+// ---------------------------------------------------------
+// GetContactFieldLC
+// ---------------------------------------------------------
+HBufC* CPostcardContact::GetContactFieldLC(TVPbkFieldTypeName aFieldType,
+ TVPbkSubFieldType aSubFieldType,
+ TVPbkFieldTypeParameter aFieldTypeParameter) const
+ {
+ TVPbkFieldVersitProperty prop;
+
+ prop.SetName(aFieldType);
+ prop.SetSubField(aSubFieldType);
+
+ TVPbkFieldTypeParameters fieldTypeParameters;
+ fieldTypeParameters.Add(aFieldTypeParameter);
+ prop.SetParameters(fieldTypeParameters);
+
+ // Doesn't take ownership
+ const MVPbkFieldType* fieldType =
+ iContactMatcher->FieldTypes().FindMatch(prop, 0);
+
+ if (fieldType)
+ {
+ TPtrC src =
+ iContactMatcher->GetFieldDataTextL(*iStoreContact, *fieldType);
+ HBufC *data = HBufC::NewLC(src.Length());
+ *data = src;
+ data->Des().Trim();
+ return data;
+ }
+ else
+ {
+ return HBufC::NewLC(0);
+ }
+ }
+
+// ---------------------------------------------------------
+// AknInputBlockCancel
+// ---------------------------------------------------------
+void CPostcardContact::AknInputBlockCancel()
+ {
+ if ( iActSchedWait.IsStarted() )
+ {
+ // Cancels currently outstanding AIW request to phonebook.
+ TRAPD( error, iAiwServiceHandler->ExecuteServiceCmdL( KAiwCmdSelect,
+ iAiwServiceHandler->InParamListL(),
+ iAiwServiceHandler->OutParamListL(),
+ KAiwOptCancel,
+ this ) );
+ if ( error == KErrNone )
+ {
+ iShutdown = ETrue;
+ }
+ }
+ }
+
+// End of File