--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/UIControls/src/CPbk2AddItemManager.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,497 @@
+/*
+* Copyright (c) 2002-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: Manages adding new items to the contact
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "CPbk2AddItemManager.h"
+
+// Phonebook 2
+#include "MPbk2ContactEditorFieldArray.h"
+#include "MPbk2ContactEditorField.h"
+#include <CPbk2PresentationContact.h>
+#include <CPbk2PresentationContactField.h>
+#include <CPbk2PresentationContactFieldCollection.h>
+#include <CPbk2AddItemToContactDlg.h>
+#include <TPbk2AddItemWrapper.h>
+#include <MPbk2FieldProperty.h>
+#include <MPbk2FieldProperty2.h>
+#include <CPbk2FieldPropertyArray.h>
+#include <CPbk2StoreConfiguration.h>
+#include <CPbk2ContactRelocator.h>
+#include <CPbk2FieldGroupPropertyArray.h>
+#include <MPbk2ApplicationServices.h>
+#include <MPbk2AppUi.h>
+#include <MPbk2StoreValidityInformer.h>
+#include <CPbk2FieldPropertyGroup.h>
+#include <MPbk2ApplicationServices.h>
+
+// Virtual Phonebook
+#include <TVPbkContactStoreUriPtr.h>
+#include <VPbkContactStoreUris.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkContactStoreProperties.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <CVPbkContactManager.h>
+#include <MVPbkContactStoreList.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkFieldType.h>
+
+
+/// Unnamed namespace for local definitions
+namespace {
+
+#ifdef _DEBUG
+enum TPanicCode
+ {
+ EPanicPreCond_MakePhoneContactL = 1,
+ EPanicPreCond_RetryFieldsAdditionL
+ };
+#endif // _DEBUG
+
+#ifdef _DEBUG
+void Panic(TPanicCode aReason)
+ {
+ _LIT(KPanicText, "CPbk2AddItemManager");
+ User::Panic(KPanicText, aReason);
+ }
+#endif // _DEBUG
+
+/**
+ * Checks is the store valid.
+ *
+ * @param aInformer Store validity informer.
+ * @param aStoreUri URI of the store to inspect.
+ * @return ETrue if store is valid.
+ */
+TBool IsValidStoreL
+ ( MPbk2StoreValidityInformer& aInformer, TVPbkContactStoreUriPtr aStoreUri )
+ {
+ TBool isValid = EFalse;
+ CVPbkContactStoreUriArray* currentlyValidStores =
+ aInformer.CurrentlyValidStoresL();
+ isValid = currentlyValidStores->IsIncluded( aStoreUri );
+ delete currentlyValidStores;
+
+ return isValid;
+ }
+
+} /// namespace
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::CPbk2AddItemManager
+// --------------------------------------------------------------------------
+//
+CPbk2AddItemManager::CPbk2AddItemManager
+ (CPbk2PresentationContact& aContact,
+ MPbk2ContactEditorFieldArray& aFieldArray,
+ TPbk2ContactEditorParams& aParams,
+ MPbk2ApplicationServices* aAppServices ) :
+ iContact(&aContact),
+ iFieldArray(&aFieldArray),
+ iParams(aParams),
+ iAppServices( aAppServices ),
+ iProperties(&aContact.PresentationFields().FieldProperties() )
+ {
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::~CPbk2AddItemManager
+// --------------------------------------------------------------------------
+//
+CPbk2AddItemManager::~CPbk2AddItemManager()
+ {
+ delete iTemporaryPresentationContact;
+ delete iTemporaryStoreContact;
+ delete iGroupProperties;
+ delete iXSpName;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2AddItemManager* CPbk2AddItemManager::NewL
+ ( CPbk2PresentationContact& aContact,
+ MPbk2ContactEditorFieldArray& aFieldArray,
+ TPbk2ContactEditorParams& aParams,
+ MPbk2ApplicationServices* aAppServices )
+ {
+ CPbk2AddItemManager* self =
+ new ( ELeave ) CPbk2AddItemManager( aContact, aFieldArray, aParams, aAppServices );
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::AddFieldsL
+// --------------------------------------------------------------------------
+//
+CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::AddFieldsL
+ (TInt& aFieldTypeResId, TPtrC& aFieldTypeXspName )
+ {
+ CArrayPtr<const MPbk2FieldProperty>* propArray =
+ iContact->AvailableFieldsToAddL();
+ CleanupStack::PushL(propArray);
+
+ CPbk2ContactRelocator* contactRelocator = CPbk2ContactRelocator::NewL();
+ CleanupStack::PushL( contactRelocator );
+
+ if (!contactRelocator->IsPhoneMemoryContact( *iContact ) &&
+ contactRelocator->IsPhoneMemoryInConfigurationL() &&
+ IsValidStoreL ( Phonebook2::Pbk2AppUi()->ApplicationServices().
+ StoreValidityInformer(), VPbkContactStoreUris::DefaultCntDbUri() ) )
+ {
+ // Expand the property array with phone memory field types
+ AddPhoneMemoryFieldTypesL(*propArray);
+ }
+
+ CleanupStack::PopAndDestroy( contactRelocator );
+
+
+ // Create group properties
+ if ( iGroupProperties )
+ {
+ delete iGroupProperties;
+ iGroupProperties = NULL;
+ }
+
+ iGroupProperties = CPbk2FieldGroupPropertyArray::NewL( *iProperties );
+
+ TReturnValue ret = DoAddFieldsL(*propArray, aFieldTypeResId, aFieldTypeXspName);
+
+ CleanupStack::PopAndDestroy(propArray);
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::AddFieldsToUiAndContactL
+// --------------------------------------------------------------------------
+//
+inline CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::AddFieldsToUiAndContactL(
+ const TPbk2AddItemWrapper& aWrapper)
+ {
+ TReturnValue ret;
+ TInt controlId = KErrUnknown;
+ const TInt count = aWrapper.PropertyCount();
+ for (TInt i = 0; i < count; ++i)
+ {
+ const MPbk2FieldProperty& prop = aWrapper.PropertyAt(i);
+
+
+ MPbk2FieldProperty2* fieldPropertyExtension =
+ reinterpret_cast<MPbk2FieldProperty2*>(
+ const_cast<MPbk2FieldProperty&>( prop ).
+ FieldPropertyExtension(
+ KMPbk2FieldPropertyExtension2Uid ) );
+ User::LeaveIfNull( fieldPropertyExtension );
+
+ TInt tmpId = iFieldArray->AddNewFieldL( prop.FieldType(),
+ fieldPropertyExtension->XSpName() );
+ if (controlId == KErrUnknown)
+ {
+ controlId = tmpId;
+ }
+ }
+
+ if( aWrapper.Group() )
+ {
+ ret.iGruopId = aWrapper.Group()->GroupId();
+ }
+
+ ret.iControlId = controlId;
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::RunDialogAndAddFieldsL
+// --------------------------------------------------------------------------
+//
+inline CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::RunDialogAndAddFieldsL
+ ( RArray<TPbk2AddItemWrapper>& aWrappers,
+ TInt& aFieldTypeResId,
+ TPtrC& aFieldTypeXspName )
+ {
+ TReturnValue ret;
+ ret.iControlId = KErrUnknown;
+ TInt selectionIndex( KErrNotFound );
+
+ if (aWrappers.Count() > 0)
+ {
+ if ( aFieldTypeResId != KErrNotFound )
+ {
+ // Make a conversion from ResId to selection
+ TInt wrapCount( aWrappers.Count() );
+ for ( TInt i(0); i < wrapCount && selectionIndex == KErrNotFound; ++i)
+ {
+ TPbk2AddItemWrapper* wrapper = &aWrappers[i];
+ TInt propCount( wrapper->PropertyCount() );
+ for ( TInt j(0); j < propCount && selectionIndex == KErrNotFound; ++j )
+ {
+ const MPbk2FieldProperty& prop = wrapper->PropertyAt(j);
+ MPbk2FieldProperty2* fieldPropertyExtension =
+ reinterpret_cast<MPbk2FieldProperty2*>(
+ const_cast<MPbk2FieldProperty&>( prop ).
+ FieldPropertyExtension(
+ KMPbk2FieldPropertyExtension2Uid ) );
+ User::LeaveIfNull( fieldPropertyExtension );
+ if ( (aFieldTypeResId == prop.FieldType().FieldTypeResId() ) &&
+ !aFieldTypeXspName.CompareF(fieldPropertyExtension->XSpName()) )
+ {
+ selectionIndex = i;
+ }
+ }
+ }
+ if ( selectionIndex == KErrNotFound )
+ {
+ // Field cannot be added to current contact
+ // propably it already exist and this field type cannot be
+ // more than once in one contact
+ ret.iControlId = KErrAlreadyExists;
+ }
+ }
+
+ if( ret.iControlId == KErrUnknown )
+ {
+ if ( selectionIndex == KErrNotFound )
+ {
+ CPbk2AddItemToContactDlg* dlg = CPbk2AddItemToContactDlg::NewL( iAppServices );
+ TPbk2AddItemDialogParams params(NULL, 0, selectionIndex);
+ selectionIndex = dlg->ExecuteLD(aWrappers, ¶ms);
+ }
+
+ if (selectionIndex != KErrCancel)
+ {
+ TPbk2AddItemWrapper* wrapper = &aWrappers[selectionIndex];
+ MPbk2FieldProperty2* fieldPropertyExtension =
+ reinterpret_cast<MPbk2FieldProperty2*>(
+ const_cast<MPbk2FieldProperty&>( wrapper->PropertyAt(0) ).
+ FieldPropertyExtension(
+ KMPbk2FieldPropertyExtension2Uid ) );
+ User::LeaveIfNull( fieldPropertyExtension );
+
+ aFieldTypeResId = wrapper->PropertyAt(0).FieldType().FieldTypeResId();
+ aFieldTypeXspName.Set(fieldPropertyExtension->XSpName());
+ delete iXSpName;
+ iXSpName = NULL;
+ if (aFieldTypeXspName != KNullDesC)
+ {
+ iXSpName = fieldPropertyExtension->XSpName().AllocL();
+ }
+ aFieldTypeXspName.Set(iXSpName ? *iXSpName : KNullDesC());
+ TRAPD(err, ret = AddFieldsToUiAndContactL(*wrapper));
+
+ if (err == KErrNotSupported)
+ {
+ // KErrNotSupported means that the current
+ // contact does not support the selected detail.
+ // When receiving this error code the caller
+ // may choose to relocate the contact and try again.
+ ret.iControlId = KErrNotSupported;
+ }
+ else
+ {
+ User::LeaveIfError(err);
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::AddPhoneMemoryFieldTypesL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2AddItemManager::AddPhoneMemoryFieldTypesL
+ (CArrayPtr<const MPbk2FieldProperty>& aProperties)
+ {
+ // Make a duplicate phone contact instance out of the current contact
+ MakePhoneContactL(*iContact);
+
+ // Get available fields to add to the phone contact
+ CArrayPtr<const MPbk2FieldProperty>* phonePropArray =
+ iTemporaryPresentationContact->AvailableFieldsToAddL();
+ CleanupStack::PushL(phonePropArray);
+
+ // Append new properties to the old array
+ TInt currentPropertyCount = aProperties.Count();
+ TInt phonePropertyCount = phonePropArray->Count();
+ for (TInt i=0; i<phonePropertyCount; ++i)
+ {
+ TBool found = EFalse;
+ const MPbk2FieldProperty* phoneProp = phonePropArray->At(i);
+ for (TInt j=0; j<currentPropertyCount; ++j)
+ {
+ const MPbk2FieldProperty* prop = aProperties.At(j);
+ if (prop->IsSame(*phoneProp))
+ {
+ found = ETrue;
+ break;
+ }
+ }
+ // Append the property only if not found already
+ if ( !found && iParams.iActiveView == TPbk2ContactEditorParams::EEditorView )
+ {
+ aProperties.AppendL(phoneProp);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(phonePropArray);
+
+ // Switch properties member to reference the properties of
+ // the temporary contact
+ iProperties = &iTemporaryPresentationContact->PresentationFields().
+ FieldProperties();
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::DoAddFieldsL
+// --------------------------------------------------------------------------
+//
+inline CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::DoAddFieldsL
+ (CArrayPtr<const MPbk2FieldProperty>& aProperties,
+ TInt& aFieldTypeResId,
+ TPtrC& aFieldTypeXspName )
+ {
+ RArray<TPbk2AddItemWrapper> wrappers;
+ CleanupClosePushL(wrappers);
+
+ RPointerArray<const CPbk2FieldPropertyGroup> addedGroups;
+ CleanupClosePushL(addedGroups);
+
+ const CPbk2FieldPropertyGroup* address = NULL;
+ TInt countAddr = 0;
+ const TInt count = aProperties.Count();
+ for (TInt i = 0; i < count; ++i)
+ {
+ const MPbk2FieldProperty& prop = *(aProperties)[i];
+ const CPbk2FieldPropertyGroup* group =
+ iGroupProperties->FindGroupForProperty(prop);
+
+ TPbk2FieldGroupId propGroup = EPbk2FieldGroupIdNone;
+ if( group )
+ {
+ propGroup = group->GroupId();
+ }
+
+ if ( propGroup != EPbk2FieldGroupIdNone )
+ {
+ if( addedGroups.Find(group) == KErrNotFound )
+ {
+ addedGroups.AppendL(group);
+ if (iContact->PresentationFields().ContainsFieldFromGroup(
+ *group))
+ {
+ if( propGroup != EPbk2FieldGroupIdPostalAddress &&
+ propGroup != EPbk2FieldGroupIdHomeAddress &&
+ propGroup != EPbk2FieldGroupIdCompanyAddress ||
+ aFieldTypeResId > 0 )
+ {
+ // Item belongs to the group but there are already
+ // items from the same group in the contact
+ wrappers.AppendL(TPbk2AddItemWrapper(prop));
+ }
+ }
+ else
+ {
+ // Add the whole group of fields
+ wrappers.AppendL(TPbk2AddItemWrapper(*group));
+ }
+ }
+ }
+ else
+ {
+ // Item doesn't belong to group
+ wrappers.AppendL(TPbk2AddItemWrapper(prop));
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); // addedGroups
+
+ TReturnValue ret = RunDialogAndAddFieldsL(wrappers, aFieldTypeResId,
+ aFieldTypeXspName);
+ CleanupStack::PopAndDestroy(); // wrappers
+
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::IsFieldAdditionPossibleL
+// --------------------------------------------------------------------------
+//
+inline TBool CPbk2AddItemManager::IsFieldAdditionPossibleL
+ (const CPbk2PresentationContact& aContact,
+ const MPbk2FieldProperty& aProperty)
+ {
+ TBool ret = EFalse;
+ // To be able to add field requires that the property must fit
+ // either into phone memory contact or into the current
+ // memory contact
+ if ((aContact.IsFieldAdditionPossibleL(aProperty.FieldType())) &&
+ (aProperty.Flags() & KPbk2FieldFlagUserCanAddField))
+ {
+ ret = ETrue;
+ }
+
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CPbk2AddItemManager::MakePhoneContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2AddItemManager::MakePhoneContactL
+ (const CPbk2PresentationContact& aContact)
+ {
+ // Get phone memory contact store
+ MVPbkContactStore* phoneStore =
+ Phonebook2::Pbk2AppUi()->ApplicationServices().ContactManager().
+ ContactStoresL().Find
+ (VPbkContactStoreUris::DefaultCntDbUri());
+
+ __ASSERT_DEBUG(phoneStore,
+ Panic(EPanicPreCond_MakePhoneContactL));
+
+ // Create a temporary contact to phone memory store
+ iTemporaryStoreContact = phoneStore->CreateNewContactLC();
+ CleanupStack::Pop(); // CreateNewContactLC
+
+ // Make a presentation contact out of it
+ iTemporaryPresentationContact = CPbk2PresentationContact::NewL
+ (*iTemporaryStoreContact,
+ Phonebook2::Pbk2AppUi()->ApplicationServices().FieldProperties());
+
+ // Add the fields of the current store contact in to it
+ const TInt count(aContact.Fields().FieldCount());
+ for (TInt i = 0; i<count; ++i)
+ {
+ CPbk2PresentationContactField& field =
+ aContact.PresentationFields().At(i);
+
+ if (iTemporaryPresentationContact->IsFieldAdditionPossibleL
+ (field.FieldProperty().FieldType()))
+ {
+ MVPbkStoreContactField* newField =
+ iTemporaryPresentationContact->CreateFieldLC(
+ field.FieldProperty().FieldType());
+ iTemporaryPresentationContact->AddFieldL(newField);
+ CleanupStack::Pop(); // newField
+ }
+ }
+ }
+
+// End of File