phonebookui/Phonebook2/UIControls/src/CPbk2ContactEditorFieldArray.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
child 68 9da50d567e3c
equal deleted inserted replaced
62:5b6f26637ad3 63:f4a778e096c2
       
     1 /*
       
     2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Phonebook 2 contact editor field array.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "CPbk2ContactEditorFieldArray.h"
       
    19 
       
    20 // Phonebook 2
       
    21 #include "CPbk2ReadingFieldEditorVisitor.h"
       
    22 #include "CPbk2IconInfoContainer.h"
       
    23 #include "Pbk2ContactEditorFieldFactory.h"
       
    24 #include "MPbk2ContactEditorField.h"
       
    25 #include "MPbk2ContactEditorUiBuilder.h"
       
    26 #include <Pbk2CommonUi.rsg>
       
    27 #include <CPbk2PresentationContact.h>
       
    28 #include <CPbk2PresentationContactFieldCollection.h>
       
    29 #include <CPbk2PresentationContactField.h>
       
    30 #include <MPbk2FieldProperty.h>
       
    31 #include <Pbk2UIControls.rsg>
       
    32 #include <MPbk2AppUi.h>
       
    33 #include <CPbk2ServiceManager.h>
       
    34 #include "TPbk2ContactEditorParams.h"
       
    35 #include <MPbk2ApplicationServices.h>
       
    36 #include "CPbk2IconInfo.h"
       
    37 #include <AknsUtils.h>
       
    38 #include <aknlayoutscalable_avkon.cdl.h>
       
    39 #include "CPbk2UIFieldArray.h"
       
    40 #include "CPbk2UIField.h"
       
    41 #include "Pbk2UIFieldProperty.hrh"
       
    42 #include "Pbk2AddressTools.h"
       
    43 #include <MPbk2ApplicationServices2.h>
       
    44 
       
    45 
       
    46 // Virtual Phonebook
       
    47 #include <MVPbkContactStore.h>
       
    48 #include <MVPbkContactStoreProperties.h>
       
    49 #include <CVPbkFieldTypeSelector.h>
       
    50 #include <VPbkEng.rsg>
       
    51 #include <MVPbkFieldType.h>
       
    52 #include <VPbkFieldType.hrh>
       
    53 #include <TVPbkFieldVersitProperty.h>
       
    54 #include <MVPbkContactFieldData.h>
       
    55 #include <MVPbkContactFieldTextData.h>
       
    56 
       
    57 
       
    58 // System includes
       
    59 #include <barsread.h>
       
    60 #include <coemain.h>
       
    61 #include <AknUtils.h>
       
    62 #include <StringLoader.h>
       
    63 
       
    64 /// Unnamed namespace for local definitions
       
    65 namespace  {
       
    66 
       
    67 _LIT( KPbk2UIControlsResFile, "Pbk2UIControls.rsc" );
       
    68 
       
    69 #ifdef _DEBUG
       
    70 
       
    71 enum TPanicCode
       
    72     {
       
    73     EPanicInvariant_CountMismatch = 1,
       
    74     EPanicInvariant_FieldNotFound,
       
    75     EPanicInvariant_NotEditableFieldFound,
       
    76     EPanic_AddNewFieldL_OOB,
       
    77     EPanic_GetUiFieldIndex_OOB
       
    78     };
       
    79 
       
    80 void Panic(TInt aReason)
       
    81     {
       
    82     _LIT(KPanicText, "CPbk2ContactEditorFieldArray");
       
    83     User::Panic(KPanicText, aReason);
       
    84     }
       
    85 
       
    86 #endif // _DEBUG
       
    87     
       
    88 /**
       
    89  * Finds property of given type from given contact.
       
    90  *
       
    91  * @param aFieldType    Field type to search for.
       
    92  * @param aContact      The contact in question.
       
    93  * @return  Field property if any. 
       
    94  */
       
    95 const MPbk2FieldProperty* FindProperty
       
    96         ( const MVPbkFieldType& aType,
       
    97           const CPbk2PresentationContact& aContact )
       
    98     {
       
    99     CArrayPtr<const MPbk2FieldProperty>* props=
       
   100         aContact.AvailableFieldsToAddL();
       
   101     CleanupStack::PushL( props );
       
   102     TInt count( props->Count() );
       
   103     const MPbk2FieldProperty* property = NULL;
       
   104     for ( TInt i = 0; i < count && !property; ++i )
       
   105         {
       
   106         if ( props->At( i )->FieldType().IsSame( aType ) )
       
   107             {            
       
   108             property = props->At( i );
       
   109             }
       
   110         }    
       
   111     CleanupStack::PopAndDestroy( props );
       
   112     return property;
       
   113     }
       
   114 
       
   115 /**
       
   116  * Returns maximum number of fields of given type in given contact.
       
   117  *
       
   118  * @param aType     Field type in question.
       
   119  * @param aContact  Contact in question.
       
   120  * @return  Maximum number of fields.
       
   121  */
       
   122 TInt MaxNumberOfFieldL
       
   123         ( const MVPbkFieldType& aType,
       
   124           const CPbk2PresentationContact& aContact )
       
   125     {
       
   126     // Get the store limits
       
   127     TInt res = aContact.MaxNumberOfFieldL(aType);
       
   128     
       
   129     // If store has no limits or the number is bigger than one
       
   130     // -> check the UI limits
       
   131     const TInt oneFieldInContact = 1;
       
   132     if (res > oneFieldInContact || res == KVPbkStoreContactUnlimitedNumber)
       
   133         {
       
   134         const MPbk2FieldProperty* prop = FindProperty( aType, aContact );
       
   135         if (prop && prop->Multiplicity() == EPbk2FieldMultiplicityOne)
       
   136             {
       
   137             res = oneFieldInContact;
       
   138             }
       
   139         }
       
   140     return res;
       
   141     }
       
   142 
       
   143 /**
       
   144  * Returns current amount of fields of given type in given contact.
       
   145  *
       
   146  * @param aType     Field type in question.
       
   147  * @param aContact  Contact in question.
       
   148  * @return  Amount of fields.
       
   149  */
       
   150 TInt CurrentAmountOfFieldTypeInContact
       
   151         ( const MVPbkFieldType& aType,
       
   152           const CPbk2PresentationContact& aContact  )
       
   153     {
       
   154     const TInt maxMatchPriority = aContact.ContactStore().
       
   155         StoreProperties().SupportedFields().MaxMatchPriority();
       
   156 
       
   157     const TInt count = aContact.PresentationFields().FieldCount();
       
   158     TInt res = 0;
       
   159     for ( TInt i = 0; i < count; ++i )
       
   160         {
       
   161         const MVPbkStoreContactField& field =
       
   162             aContact.PresentationFields().FieldAt(i);
       
   163         const MVPbkFieldType* type = NULL;
       
   164         for ( TInt j = 0; j < maxMatchPriority && !type; ++j )
       
   165             {
       
   166             type = field.MatchFieldType(j);
       
   167             }            
       
   168             
       
   169         if ( (aType.IsSame( *type ) ) )
       
   170             {
       
   171             ++res;
       
   172             }
       
   173         }
       
   174     return res;
       
   175     }
       
   176 
       
   177 /**
       
   178  * Checks is field addition possible.
       
   179  *
       
   180  * @param aType     Field type to add.
       
   181  * @param aContact  Contact in question.
       
   182  * @return  ETrue if field addition is possible.
       
   183  */
       
   184 TBool IsFieldAdditionPossibleL
       
   185         ( const MVPbkFieldType& aType,
       
   186           const CPbk2PresentationContact& aContact )
       
   187     {
       
   188     TInt max = MaxNumberOfFieldL(aType, aContact);
       
   189     if (max == KVPbkStoreContactUnlimitedNumber)
       
   190         {
       
   191         return ETrue;
       
   192         }
       
   193     else
       
   194         {
       
   195         TInt cur = CurrentAmountOfFieldTypeInContact( aType, aContact );
       
   196         return cur < max;
       
   197         }
       
   198     }    
       
   199 
       
   200 } /// namespace
       
   201 
       
   202 
       
   203 // --------------------------------------------------------------------------
       
   204 // CPbk2ContactEditorFieldArray::CPbk2ContactEditorFieldArray
       
   205 // --------------------------------------------------------------------------
       
   206 //
       
   207 inline CPbk2ContactEditorFieldArray::CPbk2ContactEditorFieldArray
       
   208         ( CPbk2PresentationContact& aContact,
       
   209           MPbk2ContactEditorUiBuilder& aUiBuilder,
       
   210           CPbk2ContactEditorFieldFactory& aFieldFactory,
       
   211           MPbk2ApplicationServices* aAppServices ) :
       
   212             iContact( aContact ),
       
   213             iUiBuilder( aUiBuilder ),
       
   214             iFieldFactory(aFieldFactory),
       
   215             iAppServices( aAppServices )
       
   216     {
       
   217     }
       
   218 
       
   219 // --------------------------------------------------------------------------
       
   220 // CPbk2ContactEditorFieldArray::~CPbk2ContactEditorFieldArray
       
   221 // --------------------------------------------------------------------------
       
   222 //
       
   223 CPbk2ContactEditorFieldArray::~CPbk2ContactEditorFieldArray()
       
   224     {
       
   225     iFieldArray.ResetAndDestroy();
       
   226     delete iIconInfoContainer;
       
   227     delete iReadingFieldBinder;
       
   228     }
       
   229 
       
   230 // --------------------------------------------------------------------------
       
   231 // CPbk2ContactEditorFieldArray::NewL
       
   232 // --------------------------------------------------------------------------
       
   233 //
       
   234 CPbk2ContactEditorFieldArray* CPbk2ContactEditorFieldArray::NewL
       
   235         ( CVPbkContactManager& aContactManager,
       
   236           CPbk2PresentationContact& aContact,
       
   237           MPbk2ContactEditorUiBuilder& aUiBuilder,
       
   238           CPbk2ContactEditorFieldFactory& aFieldFactory )
       
   239     {
       
   240     CPbk2ContactEditorFieldArray* self = 
       
   241         new ( ELeave ) CPbk2ContactEditorFieldArray
       
   242             ( aContact, aUiBuilder, aFieldFactory );
       
   243     CleanupStack::PushL( self );
       
   244     self->ConstructL( aContactManager );
       
   245     CleanupStack::Pop( self );
       
   246     return self;
       
   247     }
       
   248 
       
   249 
       
   250 // --------------------------------------------------------------------------
       
   251 // CPbk2ContactEditorFieldArray::NewL
       
   252 // --------------------------------------------------------------------------
       
   253 //
       
   254 CPbk2ContactEditorFieldArray* CPbk2ContactEditorFieldArray::NewL
       
   255         ( CVPbkContactManager& aContactManager,
       
   256           CPbk2PresentationContact& aContact,
       
   257           MPbk2ContactEditorUiBuilder& aUiBuilder,
       
   258           CPbk2ContactEditorFieldFactory& aFieldFactory,
       
   259           MPbk2ApplicationServices* aAppServices )
       
   260     {
       
   261     CPbk2ContactEditorFieldArray* self = 
       
   262         new ( ELeave ) CPbk2ContactEditorFieldArray
       
   263             ( aContact, aUiBuilder, aFieldFactory,aAppServices );
       
   264     CleanupStack::PushL( self );
       
   265     self->ConstructL( aContactManager );
       
   266     CleanupStack::Pop( self );
       
   267     return self;
       
   268     }
       
   269 
       
   270 // --------------------------------------------------------------------------
       
   271 // CPbk2ContactEditorFieldArray::ConstructL
       
   272 // --------------------------------------------------------------------------
       
   273 //
       
   274 inline void CPbk2ContactEditorFieldArray::ConstructL
       
   275         ( CVPbkContactManager& aContactManager )
       
   276     {
       
   277     iIconInfoContainer = CPbk2IconInfoContainer::NewL
       
   278         ( R_PBK2_ICON_INFO_ARRAY );
       
   279 
       
   280     //Calculate preferred size for xsp service icons 
       
   281     TRect mainPane;
       
   282     AknLayoutUtils::LayoutMetricsRect(
       
   283         AknLayoutUtils::EMainPane, mainPane );
       
   284     TAknLayoutRect listLayoutRect;
       
   285     listLayoutRect.LayoutRect(
       
   286         mainPane,
       
   287         AknLayoutScalable_Avkon::list_single_graphic_pane_g2(0).LayoutLine() );
       
   288     TSize size(listLayoutRect.Rect().Size());
       
   289     
       
   290     /*
       
   291      * Use iAppServices if provided. This is to enable editor use outside from pbk2 context
       
   292      */
       
   293     MPbk2ApplicationServices2* servicesExtension = NULL;
       
   294     if( iAppServices )
       
   295     	{
       
   296     	// Add xsp service icons
       
   297 		servicesExtension = 
       
   298 			reinterpret_cast<MPbk2ApplicationServices2*>
       
   299 				( iAppServices->MPbk2ApplicationServicesExtension(
       
   300 						KMPbk2ApplicationServicesExtension2Uid ) );
       
   301     	}
       
   302     else
       
   303     	{
       
   304     	// Add xsp service icons
       
   305 		servicesExtension = 
       
   306 			reinterpret_cast<MPbk2ApplicationServices2*>
       
   307 				( Phonebook2::Pbk2AppUi()->ApplicationServices().
       
   308 					MPbk2ApplicationServicesExtension(
       
   309 						KMPbk2ApplicationServicesExtension2Uid ) );
       
   310     	}
       
   311     
       
   312     
       
   313     CPbk2ServiceManager& servMan = servicesExtension->ServiceManager();
       
   314     const CPbk2ServiceManager::RServicesArray& services = servMan.Services();
       
   315     TUid uid;
       
   316     uid.iUid = KPbk2ServManId;
       
   317     for ( TInt i = 0; i < services.Count(); i++ )
       
   318         {
       
   319         const CPbk2ServiceManager::TService& service = services[i];
       
   320         if ( service.iBitmapId && service.iBitmap )
       
   321             {
       
   322             AknIconUtils::SetSize(
       
   323                 services[i].iBitmap,
       
   324                 size );
       
   325             AknIconUtils::SetSize(
       
   326                 services[i].iMask,
       
   327                 size );
       
   328             TPbk2IconId id = TPbk2IconId( uid, services[i].iBitmapId );
       
   329             CPbk2IconInfo* info = CPbk2IconInfo::NewLC(
       
   330                 id, services[i].iBitmap, services[i].iMask, size );
       
   331             iIconInfoContainer->AppendIconL(info);
       
   332             CleanupStack::Pop(info);
       
   333             }
       
   334         }
       
   335     iReadingFieldBinder = CPbk2ReadingFieldEditorVisitor::NewL
       
   336         ( aContactManager );
       
   337     }
       
   338     
       
   339 // --------------------------------------------------------------------------
       
   340 // CPbk2ContactEditorFieldArray::CreateFieldsFromContactL
       
   341 // --------------------------------------------------------------------------
       
   342 //
       
   343 void CPbk2ContactEditorFieldArray::CreateFieldsFromContactL(TPbk2ContactEditorParams& aParams)
       
   344     {
       
   345     __TEST_INVARIANT;
       
   346     iParams = aParams;
       
   347     
       
   348     RArray<TPbk2FieldGroupId> addedGroups;
       
   349     CleanupClosePushL(addedGroups);
       
   350     
       
   351    
       
   352     CPbk2UIFieldArray* uiArray = CPbk2UIFieldArray::NewL(
       
   353    		KPbk2UIControlsResFile, CCoeEnv::Static()->FsSession(), iFieldFactory);
       
   354     CleanupStack::PushL(uiArray);
       
   355     
       
   356     TInt nextFreePos = 0;
       
   357     CreateUIFieldL(*uiArray, EPbk2FieldGroupIdNone, EPbk2FieldOrderTop, nextFreePos);
       
   358     
       
   359     const TInt count = iContact.PresentationFields().FieldCount();
       
   360     for (TInt i = 0; i < count; ++i)
       
   361         {
       
   362         CPbk2PresentationContactField& contactField = 
       
   363             iContact.PresentationFields().At(i);
       
   364             
       
   365         if ( contactField.IsEditable() )
       
   366             {
       
   367             if( IsFieldPartOfAddress(contactField) )
       
   368             	{
       
   369             	if( Pbk2AddressTools::MapViewTypeToAddress(iParams.iActiveView) == 
       
   370             		contactField.FieldProperty().GroupId() )
       
   371             		{
       
   372             		MPbk2ContactEditorField* field = 
       
   373             			iFieldFactory.CreateFieldLC( contactField, nextFreePos++, *iIconInfoContainer );
       
   374 		            iFieldArray.AppendL( CPbk2ContactEditorArrayItem::NewL( field ) );
       
   375 		            CleanupStack::Pop();
       
   376             		}
       
   377             	else if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView )
       
   378             		{
       
   379             		if( addedGroups.Find(contactField.FieldProperty().GroupId()) == KErrNotFound )
       
   380             			{	
       
   381 		        		CreateUIFieldL(
       
   382 		        				*uiArray, 
       
   383 		        				contactField.FieldProperty().GroupId(),
       
   384 		        				(TPbk2FieldOrder)Pbk2AddressTools::MapAddressToOrdering(contactField.FieldProperty().GroupId()), 
       
   385 		        				nextFreePos );
       
   386 		        		addedGroups.AppendL(contactField.FieldProperty().GroupId());
       
   387             			}
       
   388             		}
       
   389             	}
       
   390             else if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView )
       
   391             	{
       
   392             	MPbk2ContactEditorField* field = 
       
   393         			iFieldFactory.CreateFieldLC( contactField, nextFreePos, *iIconInfoContainer );
       
   394                 if ( field )
       
   395                     {
       
   396                     nextFreePos++;
       
   397                     iFieldArray.AppendL( CPbk2ContactEditorArrayItem::NewL( field ) );
       
   398                     CleanupStack::Pop();
       
   399                     }
       
   400             	}
       
   401             }
       
   402         }
       
   403     
       
   404     CreateUIFieldL(*uiArray, EPbk2FieldGroupIdNone, EPbk2FieldOrderBottom, nextFreePos);
       
   405         
       
   406     AcceptL(*iReadingFieldBinder);
       
   407     CleanupStack::PopAndDestroy(uiArray);
       
   408     CleanupStack::PopAndDestroy(&addedGroups);
       
   409     __TEST_INVARIANT;
       
   410     }
       
   411   
       
   412 // --------------------------------------------------------------------------
       
   413 // CPbk2ContactEditorFieldArray::CreateUIFieldL
       
   414 // --------------------------------------------------------------------------
       
   415 //
       
   416 void CPbk2ContactEditorFieldArray::CreateUIFieldL(
       
   417 		CPbk2UIFieldArray& aFieldsArr, 
       
   418 		TPbk2FieldGroupId aAddressGroup,
       
   419 		TPbk2FieldOrder aOrder,
       
   420 		TInt& aNextFreePos )
       
   421     {
       
   422     if( aOrder == EPbk2FieldOrderUndefinied )
       
   423     	{
       
   424     	return;
       
   425     	}
       
   426     
       
   427     for(TInt idx = 0; idx < aFieldsArr.Count(); idx++)
       
   428        	{
       
   429        	MPbk2UIField& field = aFieldsArr.At(idx);
       
   430        	if( field.Order() == aOrder )
       
   431    	   		{
       
   432    	   		if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView && 
       
   433    	   			field.CtrlType() == EPbk2FieldCtrlTypeExtAssignFromMapsEditor )
       
   434    	   			{
       
   435    	   			continue;
       
   436    	   			}
       
   437    	   		RBuf text;
       
   438    	   		TBool textAlloc = EFalse;
       
   439    	   		if( aAddressGroup == EPbk2FieldGroupIdPostalAddress ||
       
   440    	   			aAddressGroup == EPbk2FieldGroupIdHomeAddress ||
       
   441    	   			aAddressGroup == EPbk2FieldGroupIdCompanyAddress )
       
   442    	   			{
       
   443    	   			Pbk2AddressTools::GetAddressPreviewLC( iContact.StoreContact(), aAddressGroup, text );
       
   444    	   			textAlloc = ETrue;
       
   445    	   			}
       
   446    	   		MPbk2ContactEditorUIField* cefield = 
       
   447    	   			iFieldFactory.CreateFieldLC(field, aNextFreePos, iUiBuilder, text, *iIconInfoContainer);
       
   448    	   	    if( cefield )
       
   449    	   	    	{
       
   450    	   	    	aFieldsArr.RemoveAt(idx);
       
   451    	   	    	iFieldArray.AppendL(CPbk2ContactEditorArrayItem::NewL(cefield));
       
   452    		   		CleanupStack::Pop(cefield);
       
   453    		   		aNextFreePos++;
       
   454    	   	    	}
       
   455    	   	    if ( textAlloc )
       
   456    	   	    	{
       
   457    	   	    	CleanupStack::PopAndDestroy(); //text
       
   458    	   	    	}
       
   459    	   	    else
       
   460    	   	    	{
       
   461    	   	    	text.Close();
       
   462    	   	    	}
       
   463    	   	    break;
       
   464    	   		}
       
   465        	}
       
   466     }
       
   467 
       
   468 
       
   469 // --------------------------------------------------------------------------
       
   470 // CPbk2ContactEditorFieldArray::UpdateControlsL
       
   471 // --------------------------------------------------------------------------
       
   472 //
       
   473 void CPbk2ContactEditorFieldArray::UpdateControlsL()
       
   474     {
       
   475     const TInt count = iFieldArray.Count();
       
   476     for(TInt i = 0; i < count; ++i)
       
   477         {
       
   478         if( iFieldArray[i]->ContactEditorUIField() && 
       
   479         	iFieldArray[i]->ContactEditorUIField()->UIField()->CtrlType() != 
       
   480         	EPbk2FieldCtrlTypeExtAssignFromMapsEditor )
       
   481         	{
       
   482         	RBuf text;
       
   483         	Pbk2AddressTools::GetAddressPreviewLC( iContact.StoreContact(),
       
   484 				Pbk2AddressTools::MapCtrlTypeToAddress( 
       
   485 					iFieldArray[i]->ContactEditorUIField()->UIField()->CtrlType()), text );
       
   486         	   	   			
       
   487   	    	iFieldArray[i]->ContactEditorUIField()->SetControlTextL(text);
       
   488   	    	CleanupStack::PopAndDestroy(); //text
       
   489         	}
       
   490         }
       
   491     }
       
   492 
       
   493 // --------------------------------------------------------------------------
       
   494 // CPbk2ContactEditorFieldArray::IsEditorFieldControlEmpty
       
   495 // --------------------------------------------------------------------------
       
   496 //
       
   497 TBool CPbk2ContactEditorFieldArray::IsEditorFieldControlEmpty( TInt aIndex ) const
       
   498     {
       
   499     TBool result = ETrue;
       
   500     const TInt count = iFieldArray.Count();
       
   501     if ( aIndex >= count )
       
   502         {
       
   503         return result;
       
   504         }
       
   505     
       
   506     if ( iFieldArray[aIndex]->ContactEditorField() )
       
   507         {
       
   508         HBufC* text = NULL;
       
   509         TRAP_IGNORE( text = iFieldArray[aIndex]->ContactEditorField()->ControlTextL() );
       
   510         TInt fld = iFieldArray[aIndex]->ContactEditorField()->FieldProperty().FieldType().FieldTypeResId();
       
   511         
       
   512         if ( fld != R_VPBK_FIELD_TYPE_RINGTONE && 
       
   513                 fld != R_VPBK_FIELD_TYPE_THUMBNAILPIC &&
       
   514                 fld != R_VPBK_FIELD_TYPE_CALLEROBJIMG ) 
       
   515             {
       
   516             if ( text && text->Length() > 0 )
       
   517                 {
       
   518                 // If Fields contain only spaces; then treat field as empty field 
       
   519                 text->Des().TrimAll();
       
   520                 if ( text->Length() > 0 )
       
   521                     {
       
   522                     result = EFalse;
       
   523                     }
       
   524                 }
       
   525             }
       
   526 
       
   527         delete text;
       
   528         text = NULL;
       
   529         }
       
   530     
       
   531     return result;
       
   532     }
       
   533 
       
   534 // --------------------------------------------------------------------------
       
   535 // CPbk2ContactEditorFieldArray::IsEditorUiFieldControlEmpty
       
   536 // --------------------------------------------------------------------------
       
   537 //
       
   538 TBool CPbk2ContactEditorFieldArray::IsEditorUiFieldControlEmpty( TInt aIndex ) const
       
   539     {
       
   540     TBool result = ETrue;
       
   541     
       
   542     const TInt count = iFieldArray.Count();
       
   543     if ( aIndex >= count )
       
   544         {
       
   545         return result;
       
   546         }
       
   547     
       
   548     if( iFieldArray[aIndex]->ContactEditorUIField() ) 
       
   549         {
       
   550         TInt type = iFieldArray[aIndex]->ContactEditorUIField()->UIField()->CtrlType();
       
   551         if( type == EPbk2FieldCtrlTypeExtAddressEditor
       
   552                 || type == EPbk2FieldCtrlTypeExtAddressHomeEditor
       
   553                 || type == EPbk2FieldCtrlTypeExtAddressOfficeEditor )
       
   554             {
       
   555             TPtrC* data = NULL;
       
   556             RHashMap<TInt, TPtrC> aFieldsMap;
       
   557 
       
   558             Pbk2AddressTools::GetAddressFieldsLC( iContact.StoreContact(), 
       
   559                 Pbk2AddressTools::MapCtrlTypeToAddress( 
       
   560                     iFieldArray[aIndex]->ContactEditorUIField()->UIField()->CtrlType() ), aFieldsMap );
       
   561 
       
   562             for(TInt addrType = EVPbkVersitSubFieldPostOfficeAddress; addrType <= EVPbkVersitSubFieldCountry; addrType++ )
       
   563                 {
       
   564                 data = aFieldsMap.Find( addrType );
       
   565                 if(data && data->Length() > 0 )
       
   566                     {
       
   567                     result= EFalse;
       
   568                     }
       
   569                 }
       
   570 
       
   571             CleanupStack::PopAndDestroy( &aFieldsMap );
       
   572             }
       
   573         }
       
   574     return result;
       
   575     }
       
   576 
       
   577 // --------------------------------------------------------------------------
       
   578 // CPbk2ContactEditorFieldArray::SaveFieldsL
       
   579 // --------------------------------------------------------------------------
       
   580 //
       
   581 void CPbk2ContactEditorFieldArray::SaveFieldsL()
       
   582     {
       
   583     const TInt count = iFieldArray.Count();
       
   584     for(TInt i = 0; i < count; ++i)
       
   585         {
       
   586         if( iFieldArray[i]->ContactEditorField() )
       
   587             {
       
   588             iFieldArray[i]->ContactEditorField()->SaveFieldL();
       
   589             }
       
   590         }
       
   591     }
       
   592 
       
   593 // --------------------------------------------------------------------------
       
   594 // CPbk2ContactEditorFieldArray::FieldsChanged
       
   595 // --------------------------------------------------------------------------
       
   596 //
       
   597 TBool CPbk2ContactEditorFieldArray::FieldsChanged() const
       
   598     {
       
   599 	TBool result = EFalse;
       
   600     for (TInt i = 0; i < iFieldArray.Count(); ++i)
       
   601         {
       
   602         if ( iFieldArray[i]->ContactEditorField() && 
       
   603         	 iFieldArray[i]->ContactEditorField()->FieldDataChanged() )
       
   604 			{
       
   605 			result = ETrue;
       
   606 			}
       
   607         // can break because at least one field has changed
       
   608         if (result)
       
   609             {
       
   610             break;
       
   611             }
       
   612         }
       
   613     return result;
       
   614     }
       
   615 
       
   616 // --------------------------------------------------------------------------
       
   617 // CPbk2ContactEditorFieldArray::AreAllUiFieldsEmpty
       
   618 // --------------------------------------------------------------------------
       
   619 //
       
   620 TBool CPbk2ContactEditorFieldArray::AreAllUiFieldsEmpty() const
       
   621     {
       
   622     TBool result(ETrue);
       
   623     const TInt count = iFieldArray.Count();
       
   624  
       
   625     for(TInt i = 0; i < count && result; ++i)
       
   626         {     
       
   627         if( iFieldArray[i]->ContactEditorField() )
       
   628             {
       
   629             result = IsEditorFieldControlEmpty( i );
       
   630             }
       
   631         
       
   632         // if not managed in ContactEditorField, judge whether available in ContactEditorUIField
       
   633         else if( iFieldArray[i]->ContactEditorUIField() ) 
       
   634             {
       
   635             result = IsEditorUiFieldControlEmpty( i );
       
   636             }
       
   637         }
       
   638     return result;
       
   639     }
       
   640 
       
   641 // --------------------------------------------------------------------------
       
   642 // CPbk2ContactEditorFieldArray::SetFocus
       
   643 // --------------------------------------------------------------------------
       
   644 //
       
   645 void CPbk2ContactEditorFieldArray::SetFocus(TInt aFieldIndex)
       
   646     {
       
   647     if (aFieldIndex >= 0 && aFieldIndex < iFieldArray.Count())
       
   648         {
       
   649         iFieldArray[aFieldIndex]->SetFocus();
       
   650         }
       
   651     }
       
   652 
       
   653 // --------------------------------------------------------------------------
       
   654 // CPbk2ContactEditorFieldArray::Find
       
   655 // --------------------------------------------------------------------------
       
   656 //
       
   657 CPbk2ContactEditorArrayItem* CPbk2ContactEditorFieldArray::Find
       
   658         ( TInt aControlId )
       
   659     {
       
   660     const TInt count = iFieldArray.Count();
       
   661     for (TInt i = 0; i < count; ++i)
       
   662         {
       
   663         if (iFieldArray[i]->ControlId() == aControlId)
       
   664             {
       
   665             return iFieldArray[i];
       
   666             }
       
   667         }
       
   668     return NULL;
       
   669     }
       
   670 
       
   671 // --------------------------------------------------------------------------
       
   672 // CPbk2ContactEditorFieldArray::FindIndex
       
   673 // --------------------------------------------------------------------------
       
   674 //
       
   675 TInt CPbk2ContactEditorFieldArray::FindIndex
       
   676         ( TInt aControlId )
       
   677     {
       
   678     const TInt count = iFieldArray.Count();
       
   679     for (TInt i = 0; i < count; ++i)
       
   680         {
       
   681         if (iFieldArray[i]->ControlId() == aControlId)
       
   682             {
       
   683             return i;
       
   684             }
       
   685         }
       
   686     return KErrArgument;
       
   687     }
       
   688 
       
   689 // --------------------------------------------------------------------------
       
   690 // CPbk2ContactEditorFieldArray::AddNewFieldL
       
   691 // --------------------------------------------------------------------------
       
   692 //
       
   693 TInt CPbk2ContactEditorFieldArray::AddNewFieldL
       
   694         ( const MVPbkFieldType& aFieldType)
       
   695     {
       
   696     return AddNewFieldL(aFieldType, KNullDesC);
       
   697     }
       
   698 
       
   699 // --------------------------------------------------------------------------
       
   700 // CPbk2ContactEditorFieldArray::AddNewFieldL
       
   701 // --------------------------------------------------------------------------
       
   702 //
       
   703 void CPbk2ContactEditorFieldArray::AddNewFieldL
       
   704         ( const TPbk2FieldGroupId aAddressGroup )
       
   705     {
       
   706     CPbk2UIFieldArray* uiArray = CPbk2UIFieldArray::NewL(
       
   707    		KPbk2UIControlsResFile, CCoeEnv::Static()->FsSession(), iFieldFactory);
       
   708     CleanupStack::PushL(uiArray);
       
   709     
       
   710     TInt uiIndex = GetUiFieldIndex(aAddressGroup);
       
   711             
       
   712     // Before adding a new field the focus must be on the previous item
       
   713     TInt focusIndex = uiIndex - 1;
       
   714     SetFocus(focusIndex);
       
   715     
       
   716     for(TInt idx = 0; idx < uiArray->Count(); idx++)
       
   717 	   	{
       
   718 	   	MPbk2UIField& field = uiArray->At(idx);
       
   719 	   	if( aAddressGroup == Pbk2AddressTools::MapCtrlTypeToAddress( field.CtrlType() ) )
       
   720 	   		{
       
   721 	   		MPbk2ContactEditorUIField* cefield = 
       
   722 	   			iFieldFactory.CreateFieldLC(field, uiIndex, iUiBuilder, KNullDesC(), *iIconInfoContainer);
       
   723 	   	    if( cefield )
       
   724 	   	    	{
       
   725 	   	    	uiArray->RemoveAt(idx);
       
   726 	   	    	iFieldArray.InsertL( CPbk2ContactEditorArrayItem::NewL(cefield), uiIndex );
       
   727 	   	    	cefield->ActivateL();
       
   728 		   		CleanupStack::Pop(cefield);
       
   729 	   	    	}
       
   730 	   	    break;
       
   731 	   		}
       
   732 	   	}
       
   733     
       
   734     CleanupStack::PopAndDestroy(uiArray);
       
   735     }
       
   736 
       
   737 // --------------------------------------------------------------------------
       
   738 // CPbk2ContactEditorFieldArray::AddNewFieldL
       
   739 // --------------------------------------------------------------------------
       
   740 //
       
   741 TInt CPbk2ContactEditorFieldArray::AddNewFieldL
       
   742         ( const MVPbkFieldType& aFieldType, const TDesC& aName )
       
   743     {
       
   744     __TEST_INVARIANT;
       
   745     
       
   746     // Check first is field adding possible. If there already is max amount
       
   747     // of this type fields, leave with KErrNotSupported.
       
   748     if ( !IsFieldAdditionPossibleL( aFieldType, iContact ) )
       
   749         {
       
   750         User::Leave( KErrNotSupported );
       
   751         }
       
   752     
       
   753     
       
   754     MVPbkStoreContactField* storeField = iContact.CreateFieldLC(aFieldType);
       
   755     TInt index = iContact.AddFieldL(storeField, aName);
       
   756     CleanupStack::Pop( storeField );
       
   757     
       
   758     TArray<TVPbkFieldVersitProperty> propArr = aFieldType.VersitProperties();
       
   759     TInt count = propArr.Count();
       
   760     TBool addrProp = EFalse;
       
   761     for( TInt idx = 0; idx < count; idx++)
       
   762     	{
       
   763     	if( propArr[idx].Name() == EVPbkVersitNameADR )
       
   764     		{
       
   765     		addrProp = ETrue;
       
   766     		}
       
   767     	}
       
   768     if( iParams.iActiveView == TPbk2ContactEditorParams::EEditorView && addrProp )
       
   769     	{
       
   770     	return KErrNone;
       
   771     	}
       
   772     
       
   773     TInt uiIndex = GetUiFieldIndex(index);
       
   774     
       
   775     // Before adding a new field the focus must be on the previous item
       
   776     TInt focusIndex = uiIndex - 1;
       
   777     SetFocus(focusIndex);
       
   778     
       
   779     __ASSERT_DEBUG( iContact.PresentationFields().FieldCount() > index,
       
   780         Panic( EPanic_AddNewFieldL_OOB ) );
       
   781     MPbk2ContactEditorField* uiField = iFieldFactory.CreateFieldLC(
       
   782         iContact.PresentationFields().At(index), NULL, *iIconInfoContainer);
       
   783     iFieldArray.InsertL(CPbk2ContactEditorArrayItem::NewL(uiField), uiIndex);
       
   784     CleanupStack::Pop();
       
   785     // The first SetFocus is needed.
       
   786     // Otherwise the added focused field can be outside of screen.
       
   787     SetFocus( 0 );
       
   788     SetFocus( uiIndex );
       
   789     uiField->AcceptL(*iReadingFieldBinder);
       
   790     uiField->ActivateL();
       
   791     
       
   792     __TEST_INVARIANT;
       
   793     return uiField->ControlId();
       
   794     }
       
   795 
       
   796 // --------------------------------------------------------------------------
       
   797 // CPbk2ContactEditorFieldArray::RemoveField
       
   798 // --------------------------------------------------------------------------
       
   799 //
       
   800 void CPbk2ContactEditorFieldArray::RemoveField
       
   801         ( CPbk2ContactEditorArrayItem& aField )
       
   802     {
       
   803     __TEST_INVARIANT;
       
   804     const TInt count = iFieldArray.Count();
       
   805     for (TInt i = 0; i < count; ++i)
       
   806         {
       
   807         CPbk2ContactEditorArrayItem* field = iFieldArray[i];
       
   808         if (field == &aField)
       
   809             {
       
   810             iUiBuilder.DeleteControl(field->ControlId());
       
   811             if( field->ContactEditorField() )
       
   812             	{
       
   813 		        TInt index = iContact.PresentationFields().FindFieldIndex(
       
   814 	        		field->ContactEditorField()->ContactField());
       
   815 		        iContact.RemoveField(index);
       
   816 		        iFieldArray.Remove(i);
       
   817 		        delete field;
       
   818             	}
       
   819             else if( field->ContactEditorUIField() )
       
   820             	{
       
   821             	TPbk2FieldGroupId groupId = 
       
   822 					Pbk2AddressTools::MapCtrlTypeToAddress(
       
   823 						field->ContactEditorUIField()->UIField()->CtrlType() );
       
   824             	iFieldArray.Remove(i);
       
   825 				delete field;
       
   826             	
       
   827 				if( groupId == EPbk2FieldGroupIdNone )
       
   828 					{
       
   829 					break;
       
   830 					}
       
   831 				
       
   832             	CPbk2PresentationContactFieldCollection& fields = iContact.PresentationFields();
       
   833             	TBool removed = EFalse;
       
   834 				for(TInt idx = 0; idx < fields.FieldCount() && !removed; idx++)
       
   835 					{
       
   836 					MVPbkStoreContactField& storeField = fields.FieldAt(idx);
       
   837 					TInt countProps =
       
   838 						storeField.BestMatchingFieldType()->VersitProperties().Count();
       
   839 					TArray<TVPbkFieldVersitProperty> props =
       
   840 						storeField.BestMatchingFieldType()->VersitProperties();
       
   841 					for( TInt idx2 = 0; idx2 < countProps && !removed; idx2++ )
       
   842 						{
       
   843 						if ( props[ idx2 ].Name() == EVPbkVersitNameGEO &&
       
   844 							 ( ( props[ idx2 ].Parameters().Contains( EVPbkVersitParamHOME ) &&
       
   845 									 groupId == EPbk2FieldGroupIdHomeAddress ) ||
       
   846 							   ( props[ idx2 ].Parameters().Contains( EVPbkVersitParamWORK ) &&
       
   847 									 groupId == EPbk2FieldGroupIdCompanyAddress ) ||
       
   848 							   ( !props[ idx2 ].Parameters().Contains( EVPbkVersitParamHOME ) &&
       
   849 								 !props[ idx2 ].Parameters().Contains( EVPbkVersitParamWORK ) &&
       
   850 								 groupId == EPbk2FieldGroupIdPostalAddress ) ) )
       
   851 							{
       
   852 							iContact.RemoveField(idx);
       
   853 							removed = ETrue;
       
   854 							}
       
   855 						}
       
   856 					}
       
   857             	
       
   858 				for( TInt idx = fields.FieldCount() - 1; idx >= 0 ; idx-- )
       
   859 					{
       
   860 					if( groupId == fields.At( idx ).FieldProperty().GroupId() )
       
   861 						{
       
   862 						iContact.RemoveField(idx);
       
   863 						}
       
   864 					}
       
   865             	}
       
   866             break;
       
   867             }
       
   868         }
       
   869     __TEST_INVARIANT;
       
   870     }
       
   871 
       
   872 // --------------------------------------------------------------------------
       
   873 // CPbk2ContactEditorFieldArray::RemoveFieldFromUI
       
   874 // --------------------------------------------------------------------------
       
   875 //
       
   876 void CPbk2ContactEditorFieldArray::RemoveFieldFromUI( TInt aIndex )
       
   877     {
       
   878     __TEST_INVARIANT;
       
   879     CPbk2ContactEditorArrayItem* field = iFieldArray[aIndex];
       
   880     iUiBuilder.DeleteControl(field->ControlId());
       
   881 	iFieldArray.Remove(aIndex);
       
   882 	delete field;
       
   883     __TEST_INVARIANT;
       
   884     }
       
   885 
       
   886 // --------------------------------------------------------------------------
       
   887 // CPbk2ContactEditorFieldArray::GetUiFieldIndex
       
   888 // The fields are in the same order in the ui and in the contact.
       
   889 // The difference is that ui has only editable fields while contact can have
       
   890 // not editable fields too and for every address all address fields are 
       
   891 // joined into one field.
       
   892 // --------------------------------------------------------------------------
       
   893 //
       
   894 inline TInt CPbk2ContactEditorFieldArray::GetUiFieldIndex
       
   895         ( TInt aContactFieldIndex )
       
   896     {
       
   897     TPbk2FieldGroupId previousGroupId = EPbk2FieldGroupIdNone;
       
   898     TInt result = aContactFieldIndex;
       
   899     for (TInt i = aContactFieldIndex - 1; i >= 0; --i)
       
   900         {
       
   901         __ASSERT_DEBUG( iContact.PresentationFields().FieldCount() > i,
       
   902             Panic( EPanic_GetUiFieldIndex_OOB ) );
       
   903         CPbk2PresentationContactField& contactField = 
       
   904                     iContact.PresentationFields().At(i);
       
   905         
       
   906         if (!contactField.IsEditable())
       
   907             {
       
   908             --result;
       
   909             continue;
       
   910             }
       
   911         
       
   912 		if(TPbk2ContactEditorParams::EEditorView && IsFieldPartOfAddress(contactField))
       
   913 			{
       
   914 			if(contactField.FieldProperty().GroupId() == previousGroupId)
       
   915 				{
       
   916 				//Every address has one button, if address has 'n' fields we must remove 'n-1'
       
   917 				--result;
       
   918 				}
       
   919 			previousGroupId = contactField.FieldProperty().GroupId();
       
   920 			}
       
   921         }
       
   922 
       
   923     return result;
       
   924     }
       
   925 
       
   926 // --------------------------------------------------------------------------
       
   927 // CPbk2ContactEditorFieldArray::GetUiFieldIndex
       
   928 // The fields are in the same order in the ui and in the contact.
       
   929 // The difference is that ui has only editable fields while contact can have
       
   930 // not editable fields too and for every address all address fields are 
       
   931 // joined into one field.
       
   932 // --------------------------------------------------------------------------
       
   933 //
       
   934 inline TInt CPbk2ContactEditorFieldArray::GetUiFieldIndex
       
   935         ( TPbk2FieldGroupId aContactAddressGroupID )
       
   936     {
       
   937     TPbk2FieldGroupId previousGroupId = EPbk2FieldGroupIdNone;
       
   938     TInt result = KErrNone;
       
   939     for (TInt i = iContact.PresentationFields().FieldCount() - 1; i >= 0; --i)
       
   940         {
       
   941         __ASSERT_DEBUG( iContact.PresentationFields().FieldCount() > i,
       
   942             Panic( EPanic_GetUiFieldIndex_OOB ) );
       
   943         CPbk2PresentationContactField& contactField = 
       
   944                     iContact.PresentationFields().At(i);
       
   945         
       
   946         if (!contactField.IsEditable() && result != KErrNone)
       
   947             {
       
   948             --result;
       
   949             continue;
       
   950             }
       
   951         
       
   952 		if(TPbk2ContactEditorParams::EEditorView && IsFieldPartOfAddress(contactField))
       
   953 			{
       
   954 			if(contactField.FieldProperty().GroupId() == previousGroupId)
       
   955 				{
       
   956 				if(result != KErrNone)
       
   957 					{
       
   958 					//Every address has one button, if address has 'n' fields we must remove 'n-1'
       
   959 					--result;
       
   960 					}
       
   961 				}
       
   962 			else if(previousGroupId == aContactAddressGroupID)
       
   963 				{
       
   964 				//Start counting down from first address field position in CPbk2PresentationContact
       
   965 				result = i + 1;
       
   966 				}
       
   967 			previousGroupId = contactField.FieldProperty().GroupId();
       
   968 			}
       
   969 		else if(previousGroupId != EPbk2FieldGroupIdNone)
       
   970 			{
       
   971 			if(previousGroupId == aContactAddressGroupID)
       
   972 				{
       
   973 				//Start counting down from first address field position in CPbk2PresentationContact
       
   974 				result = i + 1;
       
   975 				}
       
   976 			previousGroupId = EPbk2FieldGroupIdNone;
       
   977 			}
       
   978         }
       
   979 
       
   980     return result;
       
   981     }
       
   982 
       
   983 // --------------------------------------------------------------------------
       
   984 // CPbk2ContactEditorFieldArray::AcceptL
       
   985 // --------------------------------------------------------------------------
       
   986 //
       
   987 void CPbk2ContactEditorFieldArray::AcceptL
       
   988         ( MPbk2ContactEditorFieldVisitor& aVisitor )
       
   989     {
       
   990     const TInt count = iFieldArray.Count();
       
   991     for (TInt i = 0; i < count; ++i)
       
   992         {
       
   993         if( iFieldArray[i]->ContactEditorField() )
       
   994         	{
       
   995         	iFieldArray[i]->ContactEditorField()->AcceptL(aVisitor);
       
   996         	}
       
   997         }
       
   998     }
       
   999 
       
  1000 // --------------------------------------------------------------------------
       
  1001 // CPbk2ContactEditorFieldArray::__DbgTestInvariant
       
  1002 // --------------------------------------------------------------------------
       
  1003 //
       
  1004 void CPbk2ContactEditorFieldArray::__DbgTestInvariant() const
       
  1005 	{
       
  1006 	#if defined(_DEBUG)
       
  1007 	const TInt fieldCount = iContact.Fields().FieldCount();
       
  1008 	TInt editableFields = 0;
       
  1009 	for (TInt i = 0; i < fieldCount; ++i)
       
  1010 	    {
       
  1011 	    if (iContact.PresentationFields().At(i).IsEditable())
       
  1012 	        {
       
  1013 	        ++editableFields;
       
  1014 	        }
       
  1015 	    }
       
  1016 	__ASSERT_DEBUG(iFieldArray.Count() <= editableFields, 
       
  1017 			Panic(EPanicInvariant_CountMismatch));
       
  1018 
       
  1019 	const TInt uiCount = iFieldArray.Count();
       
  1020 	const TInt storeFieldCount = iContact.StoreContact().Fields().FieldCount();
       
  1021 	for (TInt i = 0; i < uiCount; ++i)
       
  1022 		{
       
  1023 		if( !iFieldArray[i]->ContactEditorField() )
       
  1024 			{
       
  1025 			continue;
       
  1026 			}
       
  1027 		
       
  1028         __ASSERT_DEBUG( !( iFieldArray[i]->ContactEditorField()->FieldProperty().Flags() &
       
  1029             KPbk2FieldFlagDisableEdit ),
       
  1030                 Panic(EPanicInvariant_NotEditableFieldFound));
       
  1031 
       
  1032         TBool result = EFalse;
       
  1033         for (TInt j = 0; j < storeFieldCount && !result; ++j)
       
  1034 			{
       
  1035             MVPbkStoreContactField& field =
       
  1036                 iContact.StoreContact().Fields().FieldAt( j );
       
  1037             if ( iFieldArray[i]->ContactEditorField()->ContactField().IsSame( field ) )
       
  1038                 {
       
  1039                 result = ETrue;
       
  1040                 }
       
  1041             }
       
  1042         __ASSERT_DEBUG(result, Panic(EPanicInvariant_FieldNotFound));
       
  1043         }
       
  1044     #endif // _DEBUG
       
  1045 	}
       
  1046 
       
  1047 // --------------------------------------------------------------------------
       
  1048 // CPbk2ContactEditorFieldArray::IsFieldPartOfAddress
       
  1049 // --------------------------------------------------------------------------
       
  1050 //
       
  1051 TBool CPbk2ContactEditorFieldArray::IsFieldPartOfAddress
       
  1052         ( CPbk2PresentationContactField& aField )
       
  1053     {
       
  1054     if( aField.FieldProperty().GroupId() == EPbk2FieldGroupIdPostalAddress ||
       
  1055     	aField.FieldProperty().GroupId() == EPbk2FieldGroupIdHomeAddress ||
       
  1056     	aField.FieldProperty().GroupId() == EPbk2FieldGroupIdCompanyAddress )
       
  1057     	return ETrue;
       
  1058     return EFalse;
       
  1059     }
       
  1060 //  End of File