/*
* 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: Phonebook 2 contact editor field array.
*
*/
#include "CPbk2ContactEditorFieldArray.h"
// Phonebook 2
#include "CPbk2ReadingFieldEditorVisitor.h"
#include "CPbk2IconInfoContainer.h"
#include "Pbk2ContactEditorFieldFactory.h"
#include "MPbk2ContactEditorField.h"
#include "MPbk2ContactEditorUiBuilder.h"
#include <pbk2commonui.rsg>
#include <CPbk2PresentationContact.h>
#include <CPbk2PresentationContactFieldCollection.h>
#include <CPbk2PresentationContactField.h>
#include <MPbk2FieldProperty.h>
#include <pbk2uicontrols.rsg>
#include <MPbk2AppUi.h>
#include <CPbk2ServiceManager.h>
#include "TPbk2ContactEditorParams.h"
#include <MPbk2ApplicationServices.h>
#include "CPbk2IconInfo.h"
#include <AknsUtils.h>
#include <aknlayoutscalable_avkon.cdl.h>
#include "CPbk2UIFieldArray.h"
#include "CPbk2UIField.h"
#include "Pbk2UIFieldProperty.hrh"
#include "Pbk2AddressTools.h"
#include <MPbk2ApplicationServices2.h>
// Virtual Phonebook
#include <MVPbkContactStore.h>
#include <MVPbkContactStoreProperties.h>
#include <CVPbkFieldTypeSelector.h>
#include <vpbkeng.rsg>
#include <MVPbkFieldType.h>
#include <VPbkFieldType.hrh>
#include <TVPbkFieldVersitProperty.h>
#include <MVPbkContactFieldData.h>
#include <MVPbkContactFieldTextData.h>
// System includes
#include <barsread.h>
#include <coemain.h>
#include <AknUtils.h>
#include <StringLoader.h>
/// Unnamed namespace for local definitions
namespace {
_LIT( KPbk2UIControlsResFile, "Pbk2UIControls.rsc" );
#ifdef _DEBUG
enum TPanicCode
{
EPanicInvariant_CountMismatch = 1,
EPanicInvariant_FieldNotFound,
EPanicInvariant_NotEditableFieldFound,
EPanic_AddNewFieldL_OOB,
EPanic_GetUiFieldIndex_OOB
};
void Panic(TInt aReason)
{
_LIT(KPanicText, "CPbk2ContactEditorFieldArray");
User::Panic(KPanicText, aReason);
}
#endif // _DEBUG
/**
* Finds property of given type from given contact.
*
* @param aFieldType Field type to search for.
* @param aContact The contact in question.
* @return Field property if any.
*/
const MPbk2FieldProperty* FindProperty
( const MVPbkFieldType& aType,
const CPbk2PresentationContact& aContact )
{
CArrayPtr<const MPbk2FieldProperty>* props=
aContact.AvailableFieldsToAddL();
CleanupStack::PushL( props );
TInt count( props->Count() );
const MPbk2FieldProperty* property = NULL;
for ( TInt i = 0; i < count && !property; ++i )
{
if ( props->At( i )->FieldType().IsSame( aType ) )
{
property = props->At( i );
}
}
CleanupStack::PopAndDestroy( props );
return property;
}
/**
* Returns maximum number of fields of given type in given contact.
*
* @param aType Field type in question.
* @param aContact Contact in question.
* @return Maximum number of fields.
*/
TInt MaxNumberOfFieldL
( const MVPbkFieldType& aType,
const CPbk2PresentationContact& aContact )
{
// Get the store limits
TInt res = aContact.MaxNumberOfFieldL(aType);
// If store has no limits or the number is bigger than one
// -> check the UI limits
const TInt oneFieldInContact = 1;
if (res > oneFieldInContact || res == KVPbkStoreContactUnlimitedNumber)
{
const MPbk2FieldProperty* prop = FindProperty( aType, aContact );
if (prop && prop->Multiplicity() == EPbk2FieldMultiplicityOne)
{
res = oneFieldInContact;
}
}
return res;
}
/**
* Returns current amount of fields of given type in given contact.
*
* @param aType Field type in question.
* @param aContact Contact in question.
* @return Amount of fields.
*/
TInt CurrentAmountOfFieldTypeInContact
( const MVPbkFieldType& aType,
const CPbk2PresentationContact& aContact )
{
const TInt maxMatchPriority = aContact.ContactStore().
StoreProperties().SupportedFields().MaxMatchPriority();
const TInt count = aContact.PresentationFields().FieldCount();
TInt res = 0;
for ( TInt i = 0; i < count; ++i )
{
const MVPbkStoreContactField& field =
aContact.PresentationFields().FieldAt(i);
const MVPbkFieldType* type = NULL;
for ( TInt j = 0; j < maxMatchPriority && !type; ++j )
{
type = field.MatchFieldType(j);
}
if ( (aType.IsSame( *type ) ) )
{
++res;
}
}
return res;
}
/**
* Checks is field addition possible.
*
* @param aType Field type to add.
* @param aContact Contact in question.
* @return ETrue if field addition is possible.
*/
TBool IsFieldAdditionPossibleL
( const MVPbkFieldType& aType,
const CPbk2PresentationContact& aContact )
{
TInt max = MaxNumberOfFieldL(aType, aContact);
if (max == KVPbkStoreContactUnlimitedNumber)
{
return ETrue;
}
else
{
TInt cur = CurrentAmountOfFieldTypeInContact( aType, aContact );
return cur < max;
}
}
} /// namespace
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::CPbk2ContactEditorFieldArray
// --------------------------------------------------------------------------
//
inline CPbk2ContactEditorFieldArray::CPbk2ContactEditorFieldArray
( CPbk2PresentationContact& aContact,
MPbk2ContactEditorUiBuilder& aUiBuilder,
CPbk2ContactEditorFieldFactory& aFieldFactory,
MPbk2ApplicationServices* aAppServices ) :
iContact( aContact ),
iUiBuilder( aUiBuilder ),
iFieldFactory(aFieldFactory),
iAppServices( aAppServices )
{
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::~CPbk2ContactEditorFieldArray
// --------------------------------------------------------------------------
//
CPbk2ContactEditorFieldArray::~CPbk2ContactEditorFieldArray()
{
iFieldArray.ResetAndDestroy();
delete iIconInfoContainer;
delete iReadingFieldBinder;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::NewL
// --------------------------------------------------------------------------
//
CPbk2ContactEditorFieldArray* CPbk2ContactEditorFieldArray::NewL
( CVPbkContactManager& aContactManager,
CPbk2PresentationContact& aContact,
MPbk2ContactEditorUiBuilder& aUiBuilder,
CPbk2ContactEditorFieldFactory& aFieldFactory )
{
CPbk2ContactEditorFieldArray* self =
new ( ELeave ) CPbk2ContactEditorFieldArray
( aContact, aUiBuilder, aFieldFactory );
CleanupStack::PushL( self );
self->ConstructL( aContactManager );
CleanupStack::Pop( self );
return self;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::NewL
// --------------------------------------------------------------------------
//
CPbk2ContactEditorFieldArray* CPbk2ContactEditorFieldArray::NewL
( CVPbkContactManager& aContactManager,
CPbk2PresentationContact& aContact,
MPbk2ContactEditorUiBuilder& aUiBuilder,
CPbk2ContactEditorFieldFactory& aFieldFactory,
MPbk2ApplicationServices* aAppServices )
{
CPbk2ContactEditorFieldArray* self =
new ( ELeave ) CPbk2ContactEditorFieldArray
( aContact, aUiBuilder, aFieldFactory,aAppServices );
CleanupStack::PushL( self );
self->ConstructL( aContactManager );
CleanupStack::Pop( self );
return self;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::ConstructL
// --------------------------------------------------------------------------
//
inline void CPbk2ContactEditorFieldArray::ConstructL
( CVPbkContactManager& aContactManager )
{
iIconInfoContainer = CPbk2IconInfoContainer::NewL
( R_PBK2_ICON_INFO_ARRAY );
//Calculate preferred size for xsp service icons
TRect mainPane;
AknLayoutUtils::LayoutMetricsRect(
AknLayoutUtils::EMainPane, mainPane );
TAknLayoutRect listLayoutRect;
listLayoutRect.LayoutRect(
mainPane,
AknLayoutScalable_Avkon::list_single_graphic_pane_g2(0).LayoutLine() );
TSize size(listLayoutRect.Rect().Size());
/*
* Use iAppServices if provided. This is to enable editor use outside from pbk2 context
*/
MPbk2ApplicationServices2* servicesExtension = NULL;
if( iAppServices )
{
// Add xsp service icons
servicesExtension =
reinterpret_cast<MPbk2ApplicationServices2*>
( iAppServices->MPbk2ApplicationServicesExtension(
KMPbk2ApplicationServicesExtension2Uid ) );
}
else
{
// Add xsp service icons
servicesExtension =
reinterpret_cast<MPbk2ApplicationServices2*>
( Phonebook2::Pbk2AppUi()->ApplicationServices().
MPbk2ApplicationServicesExtension(
KMPbk2ApplicationServicesExtension2Uid ) );
}
CPbk2ServiceManager& servMan = servicesExtension->ServiceManager();
const CPbk2ServiceManager::RServicesArray& services = servMan.Services();
TUid uid;
uid.iUid = KPbk2ServManId;
for ( TInt i = 0; i < services.Count(); i++ )
{
const CPbk2ServiceManager::TService& service = services[i];
if ( service.iBitmapId && service.iBitmap )
{
AknIconUtils::SetSize(
services[i].iBitmap,
size );
AknIconUtils::SetSize(
services[i].iMask,
size );
TPbk2IconId id = TPbk2IconId( uid, services[i].iBitmapId );
CPbk2IconInfo* info = CPbk2IconInfo::NewLC(
id, services[i].iBitmap, services[i].iMask, size );
iIconInfoContainer->AppendIconL(info);
CleanupStack::Pop(info);
}
}
iReadingFieldBinder = CPbk2ReadingFieldEditorVisitor::NewL
( aContactManager );
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::CreateFieldsFromContactL
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::CreateFieldsFromContactL(TPbk2ContactEditorParams& aParams)
{
__TEST_INVARIANT;
iParams = aParams;
RArray<TPbk2FieldGroupId> addedGroups;
CleanupClosePushL(addedGroups);
CPbk2UIFieldArray* uiArray = CPbk2UIFieldArray::NewL(
KPbk2UIControlsResFile, CCoeEnv::Static()->FsSession(), iFieldFactory);
CleanupStack::PushL(uiArray);
TInt nextFreePos = 0;
CreateUIFieldL(*uiArray, EPbk2FieldGroupIdNone, EPbk2FieldOrderTop, nextFreePos);
const TInt count = iContact.PresentationFields().FieldCount();
for (TInt i = 0; i < count; ++i)
{
CPbk2PresentationContactField& contactField =
iContact.PresentationFields().At(i);
if ( contactField.IsEditable() )
{
if( IsFieldPartOfAddress(contactField) )
{
if( Pbk2AddressTools::MapViewTypeToAddress(iParams.iActiveView) ==
contactField.FieldProperty().GroupId() )
{
MPbk2ContactEditorField* field =
iFieldFactory.CreateFieldLC( contactField, nextFreePos++, *iIconInfoContainer );
iFieldArray.AppendL( CPbk2ContactEditorArrayItem::NewL( field ) );
CleanupStack::Pop();
}
else if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView )
{
if( addedGroups.Find(contactField.FieldProperty().GroupId()) == KErrNotFound )
{
CreateUIFieldL(
*uiArray,
contactField.FieldProperty().GroupId(),
(TPbk2FieldOrder)Pbk2AddressTools::MapAddressToOrdering(contactField.FieldProperty().GroupId()),
nextFreePos );
addedGroups.AppendL(contactField.FieldProperty().GroupId());
}
}
}
else if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView )
{
MPbk2ContactEditorField* field =
iFieldFactory.CreateFieldLC( contactField, nextFreePos, *iIconInfoContainer );
if ( field )
{
nextFreePos++;
iFieldArray.AppendL( CPbk2ContactEditorArrayItem::NewL( field ) );
CleanupStack::Pop();
}
}
}
}
CreateUIFieldL(*uiArray, EPbk2FieldGroupIdNone, EPbk2FieldOrderBottom, nextFreePos);
AcceptL(*iReadingFieldBinder);
CleanupStack::PopAndDestroy(uiArray);
CleanupStack::PopAndDestroy(&addedGroups);
__TEST_INVARIANT;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::CreateUIFieldL
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::CreateUIFieldL(
CPbk2UIFieldArray& aFieldsArr,
TPbk2FieldGroupId aAddressGroup,
TPbk2FieldOrder aOrder,
TInt& aNextFreePos )
{
if( aOrder == EPbk2FieldOrderUndefinied )
{
return;
}
for(TInt idx = 0; idx < aFieldsArr.Count(); idx++)
{
MPbk2UIField& field = aFieldsArr.At(idx);
if( field.Order() == aOrder )
{
if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView &&
field.CtrlType() == EPbk2FieldCtrlTypeExtAssignFromMapsEditor )
{
continue;
}
RBuf text;
TBool textAlloc = EFalse;
if( aAddressGroup == EPbk2FieldGroupIdPostalAddress ||
aAddressGroup == EPbk2FieldGroupIdHomeAddress ||
aAddressGroup == EPbk2FieldGroupIdCompanyAddress )
{
Pbk2AddressTools::GetAddressPreviewLC( iContact.StoreContact(), aAddressGroup, text );
textAlloc = ETrue;
}
MPbk2ContactEditorUIField* cefield =
iFieldFactory.CreateFieldLC(field, aNextFreePos, iUiBuilder, text, *iIconInfoContainer);
if( cefield )
{
aFieldsArr.RemoveAt(idx);
iFieldArray.AppendL(CPbk2ContactEditorArrayItem::NewL(cefield));
CleanupStack::Pop(cefield);
aNextFreePos++;
}
if ( textAlloc )
{
CleanupStack::PopAndDestroy(); //text
}
else
{
text.Close();
}
break;
}
}
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::UpdateControlsL
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::UpdateControlsL()
{
const TInt count = iFieldArray.Count();
for(TInt i = 0; i < count; ++i)
{
if( iFieldArray[i]->ContactEditorUIField() &&
iFieldArray[i]->ContactEditorUIField()->UIField()->CtrlType() !=
EPbk2FieldCtrlTypeExtAssignFromMapsEditor )
{
RBuf text;
Pbk2AddressTools::GetAddressPreviewLC( iContact.StoreContact(),
Pbk2AddressTools::MapCtrlTypeToAddress(
iFieldArray[i]->ContactEditorUIField()->UIField()->CtrlType()), text );
iFieldArray[i]->ContactEditorUIField()->SetControlTextL(text);
CleanupStack::PopAndDestroy(); //text
}
}
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::IsEditorFieldControlEmpty
// --------------------------------------------------------------------------
//
TBool CPbk2ContactEditorFieldArray::IsEditorFieldControlEmpty( TInt aIndex ) const
{
TBool result = ETrue;
const TInt count = iFieldArray.Count();
if ( aIndex >= count )
{
return result;
}
if ( iFieldArray[aIndex]->ContactEditorField() )
{
HBufC* text = NULL;
TRAP_IGNORE( text = iFieldArray[aIndex]->ContactEditorField()->ControlTextL() );
TInt fld = iFieldArray[aIndex]->ContactEditorField()->FieldProperty().FieldType().FieldTypeResId();
if ( fld != R_VPBK_FIELD_TYPE_RINGTONE &&
fld != R_VPBK_FIELD_TYPE_THUMBNAILPIC &&
fld != R_VPBK_FIELD_TYPE_CALLEROBJIMG )
{
if ( text && text->Length() > 0 )
{
// If Fields contain only spaces; then treat field as empty field
text->Des().TrimAll();
if ( text->Length() > 0 )
{
result = EFalse;
}
}
}
delete text;
text = NULL;
}
return result;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::IsEditorUiFieldControlEmpty
// --------------------------------------------------------------------------
//
TBool CPbk2ContactEditorFieldArray::IsEditorUiFieldControlEmpty( TInt aIndex ) const
{
TBool result = ETrue;
const TInt count = iFieldArray.Count();
if ( aIndex >= count )
{
return result;
}
if( iFieldArray[aIndex]->ContactEditorUIField() )
{
TInt type = iFieldArray[aIndex]->ContactEditorUIField()->UIField()->CtrlType();
if( type == EPbk2FieldCtrlTypeExtAddressEditor
|| type == EPbk2FieldCtrlTypeExtAddressHomeEditor
|| type == EPbk2FieldCtrlTypeExtAddressOfficeEditor )
{
TPtrC* data = NULL;
RHashMap<TInt, TPtrC> aFieldsMap;
Pbk2AddressTools::GetAddressFieldsLC( iContact.StoreContact(),
Pbk2AddressTools::MapCtrlTypeToAddress(
iFieldArray[aIndex]->ContactEditorUIField()->UIField()->CtrlType() ), aFieldsMap );
for(TInt addrType = EVPbkVersitSubFieldPostOfficeAddress; addrType <= EVPbkVersitSubFieldCountry; addrType++ )
{
data = aFieldsMap.Find( addrType );
if(data && data->Length() > 0 )
{
result= EFalse;
}
}
CleanupStack::PopAndDestroy( &aFieldsMap );
}
}
return result;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::SaveFieldsL
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::SaveFieldsL()
{
const TInt count = iFieldArray.Count();
for(TInt i = 0; i < count; ++i)
{
if( iFieldArray[i]->ContactEditorField() )
{
iFieldArray[i]->ContactEditorField()->SaveFieldL();
}
}
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::FieldsChanged
// --------------------------------------------------------------------------
//
TBool CPbk2ContactEditorFieldArray::FieldsChanged() const
{
TBool result = EFalse;
for (TInt i = 0; i < iFieldArray.Count(); ++i)
{
if ( iFieldArray[i]->ContactEditorField() &&
iFieldArray[i]->ContactEditorField()->FieldDataChanged() )
{
result = ETrue;
}
// can break because at least one field has changed
if (result)
{
break;
}
}
return result;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::AreAllUiFieldsEmpty
// --------------------------------------------------------------------------
//
TBool CPbk2ContactEditorFieldArray::AreAllUiFieldsEmpty() const
{
TBool result(ETrue);
const TInt count = iFieldArray.Count();
for(TInt i = 0; i < count && result; ++i)
{
if( iFieldArray[i]->ContactEditorField() )
{
result = IsEditorFieldControlEmpty( i );
}
// if not managed in ContactEditorField, judge whether available in ContactEditorUIField
else if( iFieldArray[i]->ContactEditorUIField() )
{
result = IsEditorUiFieldControlEmpty( i );
}
}
return result;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::SetFocus
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::SetFocus(TInt aFieldIndex)
{
if (aFieldIndex >= 0 && aFieldIndex < iFieldArray.Count())
{
iFieldArray[aFieldIndex]->SetFocus();
}
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::Find
// --------------------------------------------------------------------------
//
CPbk2ContactEditorArrayItem* CPbk2ContactEditorFieldArray::Find
( TInt aControlId )
{
const TInt count = iFieldArray.Count();
for (TInt i = 0; i < count; ++i)
{
if (iFieldArray[i]->ControlId() == aControlId)
{
return iFieldArray[i];
}
}
return NULL;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::FindIndex
// --------------------------------------------------------------------------
//
TInt CPbk2ContactEditorFieldArray::FindIndex
( TInt aControlId )
{
const TInt count = iFieldArray.Count();
for (TInt i = 0; i < count; ++i)
{
if (iFieldArray[i]->ControlId() == aControlId)
{
return i;
}
}
return KErrArgument;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::AddNewFieldL
// --------------------------------------------------------------------------
//
TInt CPbk2ContactEditorFieldArray::AddNewFieldL
( const MVPbkFieldType& aFieldType)
{
return AddNewFieldL(aFieldType, KNullDesC);
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::AddNewFieldL
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::AddNewFieldL
( const TPbk2FieldGroupId aAddressGroup )
{
CPbk2UIFieldArray* uiArray = CPbk2UIFieldArray::NewL(
KPbk2UIControlsResFile, CCoeEnv::Static()->FsSession(), iFieldFactory);
CleanupStack::PushL(uiArray);
TInt uiIndex = GetUiFieldIndex(aAddressGroup);
// Before adding a new field the focus must be on the previous item
TInt focusIndex = uiIndex - 1;
SetFocus(focusIndex);
for(TInt idx = 0; idx < uiArray->Count(); idx++)
{
MPbk2UIField& field = uiArray->At(idx);
if( aAddressGroup == Pbk2AddressTools::MapCtrlTypeToAddress( field.CtrlType() ) )
{
MPbk2ContactEditorUIField* cefield =
iFieldFactory.CreateFieldLC(field, uiIndex, iUiBuilder, KNullDesC(), *iIconInfoContainer);
if( cefield )
{
uiArray->RemoveAt(idx);
iFieldArray.InsertL( CPbk2ContactEditorArrayItem::NewL(cefield), uiIndex );
cefield->ActivateL();
CleanupStack::Pop(cefield);
}
break;
}
}
CleanupStack::PopAndDestroy(uiArray);
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::AddNewFieldL
// --------------------------------------------------------------------------
//
TInt CPbk2ContactEditorFieldArray::AddNewFieldL
( const MVPbkFieldType& aFieldType, const TDesC& aName )
{
__TEST_INVARIANT;
// Check first is field adding possible. If there already is max amount
// of this type fields, leave with KErrNotSupported.
if ( !IsFieldAdditionPossibleL( aFieldType, iContact ) )
{
User::Leave( KErrNotSupported );
}
MVPbkStoreContactField* storeField = iContact.CreateFieldLC(aFieldType);
TInt index = iContact.AddFieldL(storeField, aName);
CleanupStack::Pop( storeField );
TArray<TVPbkFieldVersitProperty> propArr = aFieldType.VersitProperties();
TInt count = propArr.Count();
TBool addrProp = EFalse;
for( TInt idx = 0; idx < count; idx++)
{
if( propArr[idx].Name() == EVPbkVersitNameADR )
{
addrProp = ETrue;
}
}
if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView && addrProp )
{
return KErrNone;
}
TInt uiIndex = GetUiFieldIndex(index);
// Before adding a new field the focus must be on the previous item
TInt focusIndex = uiIndex - 1;
SetFocus(focusIndex);
__ASSERT_DEBUG( iContact.PresentationFields().FieldCount() > index,
Panic( EPanic_AddNewFieldL_OOB ) );
MPbk2ContactEditorField* uiField = iFieldFactory.CreateFieldLC(
iContact.PresentationFields().At(index), NULL, *iIconInfoContainer);
iFieldArray.InsertL(CPbk2ContactEditorArrayItem::NewL(uiField), uiIndex);
CleanupStack::Pop();
// The first SetFocus is needed.
// Otherwise the added focused field can be outside of screen.
SetFocus( 0 );
SetFocus( uiIndex );
uiField->AcceptL(*iReadingFieldBinder);
uiField->ActivateL();
__TEST_INVARIANT;
return uiField->ControlId();
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::RemoveField
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::RemoveField
( CPbk2ContactEditorArrayItem& aField )
{
__TEST_INVARIANT;
const TInt count = iFieldArray.Count();
for (TInt i = 0; i < count; ++i)
{
CPbk2ContactEditorArrayItem* field = iFieldArray[i];
if (field == &aField)
{
iUiBuilder.DeleteControl(field->ControlId());
if( field->ContactEditorField() )
{
TInt index = iContact.PresentationFields().FindFieldIndex(
field->ContactEditorField()->ContactField());
iContact.RemoveField(index);
iFieldArray.Remove(i);
delete field;
}
else if( field->ContactEditorUIField() )
{
TPbk2FieldGroupId groupId =
Pbk2AddressTools::MapCtrlTypeToAddress(
field->ContactEditorUIField()->UIField()->CtrlType() );
iFieldArray.Remove(i);
delete field;
if( groupId == EPbk2FieldGroupIdNone )
{
break;
}
CPbk2PresentationContactFieldCollection& fields = iContact.PresentationFields();
TBool removed = EFalse;
for(TInt idx = 0; idx < fields.FieldCount() && !removed; idx++)
{
MVPbkStoreContactField& storeField = fields.FieldAt(idx);
TInt countProps =
storeField.BestMatchingFieldType()->VersitProperties().Count();
TArray<TVPbkFieldVersitProperty> props =
storeField.BestMatchingFieldType()->VersitProperties();
for( TInt idx2 = 0; idx2 < countProps && !removed; idx2++ )
{
if ( props[ idx2 ].Name() == EVPbkVersitNameGEO &&
( ( props[ idx2 ].Parameters().Contains( EVPbkVersitParamHOME ) &&
groupId == EPbk2FieldGroupIdHomeAddress ) ||
( props[ idx2 ].Parameters().Contains( EVPbkVersitParamWORK ) &&
groupId == EPbk2FieldGroupIdCompanyAddress ) ||
( !props[ idx2 ].Parameters().Contains( EVPbkVersitParamHOME ) &&
!props[ idx2 ].Parameters().Contains( EVPbkVersitParamWORK ) &&
groupId == EPbk2FieldGroupIdPostalAddress ) ) )
{
iContact.RemoveField(idx);
removed = ETrue;
}
}
}
for( TInt idx = fields.FieldCount() - 1; idx >= 0 ; idx-- )
{
if( groupId == fields.At( idx ).FieldProperty().GroupId() )
{
iContact.RemoveField(idx);
}
}
}
break;
}
}
__TEST_INVARIANT;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::RemoveFieldFromUI
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::RemoveFieldFromUI( TInt aIndex )
{
__TEST_INVARIANT;
CPbk2ContactEditorArrayItem* field = iFieldArray[aIndex];
iUiBuilder.DeleteControl(field->ControlId());
iFieldArray.Remove(aIndex);
delete field;
__TEST_INVARIANT;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::GetUiFieldIndex
// The fields are in the same order in the ui and in the contact.
// The difference is that ui has only editable fields while contact can have
// not editable fields too and for every address all address fields are
// joined into one field.
// --------------------------------------------------------------------------
//
inline TInt CPbk2ContactEditorFieldArray::GetUiFieldIndex
( TInt aContactFieldIndex )
{
TPbk2FieldGroupId previousGroupId = EPbk2FieldGroupIdNone;
TInt result = aContactFieldIndex;
for (TInt i = aContactFieldIndex - 1; i >= 0; --i)
{
__ASSERT_DEBUG( iContact.PresentationFields().FieldCount() > i,
Panic( EPanic_GetUiFieldIndex_OOB ) );
CPbk2PresentationContactField& contactField =
iContact.PresentationFields().At(i);
if (!contactField.IsEditable())
{
--result;
continue;
}
if(TPbk2ContactEditorParams::EEditorView && IsFieldPartOfAddress(contactField))
{
if(contactField.FieldProperty().GroupId() == previousGroupId)
{
//Every address has one button, if address has 'n' fields we must remove 'n-1'
--result;
}
previousGroupId = contactField.FieldProperty().GroupId();
}
}
return result;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::GetUiFieldIndex
// The fields are in the same order in the ui and in the contact.
// The difference is that ui has only editable fields while contact can have
// not editable fields too and for every address all address fields are
// joined into one field.
// --------------------------------------------------------------------------
//
inline TInt CPbk2ContactEditorFieldArray::GetUiFieldIndex
( TPbk2FieldGroupId aContactAddressGroupID )
{
TPbk2FieldGroupId previousGroupId = EPbk2FieldGroupIdNone;
TInt result = KErrNone;
for (TInt i = iContact.PresentationFields().FieldCount() - 1; i >= 0; --i)
{
__ASSERT_DEBUG( iContact.PresentationFields().FieldCount() > i,
Panic( EPanic_GetUiFieldIndex_OOB ) );
CPbk2PresentationContactField& contactField =
iContact.PresentationFields().At(i);
if (!contactField.IsEditable() && result != KErrNone)
{
--result;
continue;
}
if(TPbk2ContactEditorParams::EEditorView && IsFieldPartOfAddress(contactField))
{
if(contactField.FieldProperty().GroupId() == previousGroupId)
{
if(result != KErrNone)
{
//Every address has one button, if address has 'n' fields we must remove 'n-1'
--result;
}
}
else if(previousGroupId == aContactAddressGroupID)
{
//Start counting down from first address field position in CPbk2PresentationContact
result = i + 1;
}
previousGroupId = contactField.FieldProperty().GroupId();
}
else if(previousGroupId != EPbk2FieldGroupIdNone)
{
if(previousGroupId == aContactAddressGroupID)
{
//Start counting down from first address field position in CPbk2PresentationContact
result = i + 1;
}
previousGroupId = EPbk2FieldGroupIdNone;
}
}
return result;
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::AcceptL
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::AcceptL
( MPbk2ContactEditorFieldVisitor& aVisitor )
{
const TInt count = iFieldArray.Count();
for (TInt i = 0; i < count; ++i)
{
if( iFieldArray[i]->ContactEditorField() )
{
iFieldArray[i]->ContactEditorField()->AcceptL(aVisitor);
}
}
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::__DbgTestInvariant
// --------------------------------------------------------------------------
//
void CPbk2ContactEditorFieldArray::__DbgTestInvariant() const
{
#if defined(_DEBUG)
const TInt fieldCount = iContact.Fields().FieldCount();
TInt editableFields = 0;
for (TInt i = 0; i < fieldCount; ++i)
{
if (iContact.PresentationFields().At(i).IsEditable())
{
++editableFields;
}
}
__ASSERT_DEBUG(iFieldArray.Count() <= editableFields,
Panic(EPanicInvariant_CountMismatch));
const TInt uiCount = iFieldArray.Count();
const TInt storeFieldCount = iContact.StoreContact().Fields().FieldCount();
for (TInt i = 0; i < uiCount; ++i)
{
if( !iFieldArray[i]->ContactEditorField() )
{
continue;
}
__ASSERT_DEBUG( !( iFieldArray[i]->ContactEditorField()->FieldProperty().Flags() &
KPbk2FieldFlagDisableEdit ),
Panic(EPanicInvariant_NotEditableFieldFound));
TBool result = EFalse;
for (TInt j = 0; j < storeFieldCount && !result; ++j)
{
MVPbkStoreContactField& field =
iContact.StoreContact().Fields().FieldAt( j );
if ( iFieldArray[i]->ContactEditorField()->ContactField().IsSame( field ) )
{
result = ETrue;
}
}
__ASSERT_DEBUG(result, Panic(EPanicInvariant_FieldNotFound));
}
#endif // _DEBUG
}
// --------------------------------------------------------------------------
// CPbk2ContactEditorFieldArray::IsFieldPartOfAddress
// --------------------------------------------------------------------------
//
TBool CPbk2ContactEditorFieldArray::IsFieldPartOfAddress
( CPbk2PresentationContactField& aField )
{
if( aField.FieldProperty().GroupId() == EPbk2FieldGroupIdPostalAddress ||
aField.FieldProperty().GroupId() == EPbk2FieldGroupIdHomeAddress ||
aField.FieldProperty().GroupId() == EPbk2FieldGroupIdCompanyAddress )
return ETrue;
return EFalse;
}
// End of File