phonebookui/Phonebook2/UIControls/src/CPbk2AddItemManager.cpp
changeset 0 e686773b3f54
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     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:  Manages adding new items to the contact
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CPbk2AddItemManager.h"
       
    22 
       
    23 // Phonebook 2
       
    24 #include "MPbk2ContactEditorFieldArray.h"
       
    25 #include "MPbk2ContactEditorField.h"
       
    26 #include <CPbk2PresentationContact.h>
       
    27 #include <CPbk2PresentationContactField.h>
       
    28 #include <CPbk2PresentationContactFieldCollection.h>
       
    29 #include <CPbk2AddItemToContactDlg.h>
       
    30 #include <TPbk2AddItemWrapper.h>
       
    31 #include <MPbk2FieldProperty.h>
       
    32 #include <MPbk2FieldProperty2.h>
       
    33 #include <CPbk2FieldPropertyArray.h>
       
    34 #include <CPbk2StoreConfiguration.h>
       
    35 #include <CPbk2ContactRelocator.h>
       
    36 #include <CPbk2FieldGroupPropertyArray.h>
       
    37 #include <MPbk2ApplicationServices.h>
       
    38 #include <MPbk2AppUi.h>
       
    39 #include <MPbk2StoreValidityInformer.h>
       
    40 #include <CPbk2FieldPropertyGroup.h>
       
    41 #include <MPbk2ApplicationServices.h>
       
    42 
       
    43 // Virtual Phonebook
       
    44 #include <TVPbkContactStoreUriPtr.h>
       
    45 #include <VPbkContactStoreUris.h>
       
    46 #include <MVPbkContactStore.h>
       
    47 #include <MVPbkContactStoreProperties.h>
       
    48 #include <CVPbkContactStoreUriArray.h>
       
    49 #include <CVPbkContactManager.h>
       
    50 #include <MVPbkContactStoreList.h>
       
    51 #include <MVPbkStoreContact.h>
       
    52 #include <MVPbkFieldType.h>
       
    53 
       
    54 
       
    55 /// Unnamed namespace for local definitions
       
    56 namespace {
       
    57 
       
    58 #ifdef _DEBUG
       
    59 enum TPanicCode
       
    60     {
       
    61     EPanicPreCond_MakePhoneContactL = 1,
       
    62     EPanicPreCond_RetryFieldsAdditionL
       
    63     };
       
    64 #endif // _DEBUG
       
    65 
       
    66 #ifdef _DEBUG
       
    67 void Panic(TPanicCode aReason)
       
    68     {
       
    69     _LIT(KPanicText, "CPbk2AddItemManager");
       
    70     User::Panic(KPanicText, aReason);
       
    71     }
       
    72 #endif // _DEBUG
       
    73 
       
    74 /**
       
    75  * Checks is the store valid.
       
    76  *
       
    77  * @param aInformer         Store validity informer.
       
    78  * @param aStoreUri         URI of the store to inspect.
       
    79  * @return  ETrue if store is valid.
       
    80  */
       
    81 TBool IsValidStoreL
       
    82         ( MPbk2StoreValidityInformer& aInformer, TVPbkContactStoreUriPtr aStoreUri )
       
    83     {
       
    84     TBool isValid = EFalse;
       
    85     CVPbkContactStoreUriArray* currentlyValidStores =
       
    86         aInformer.CurrentlyValidStoresL();
       
    87     isValid = currentlyValidStores->IsIncluded( aStoreUri );
       
    88     delete currentlyValidStores;
       
    89 
       
    90     return isValid;
       
    91     }
       
    92    
       
    93 }  /// namespace
       
    94 
       
    95 // --------------------------------------------------------------------------
       
    96 // CPbk2AddItemManager::CPbk2AddItemManager
       
    97 // --------------------------------------------------------------------------
       
    98 //
       
    99 CPbk2AddItemManager::CPbk2AddItemManager
       
   100         (CPbk2PresentationContact& aContact,
       
   101         MPbk2ContactEditorFieldArray& aFieldArray, 
       
   102         TPbk2ContactEditorParams& aParams,
       
   103         MPbk2ApplicationServices* aAppServices ) :
       
   104             iContact(&aContact),
       
   105             iFieldArray(&aFieldArray),
       
   106             iParams(aParams),
       
   107             iAppServices( aAppServices ),
       
   108             iProperties(&aContact.PresentationFields().FieldProperties() )
       
   109     {
       
   110     }
       
   111 
       
   112 // --------------------------------------------------------------------------
       
   113 // CPbk2AddItemManager::~CPbk2AddItemManager
       
   114 // --------------------------------------------------------------------------
       
   115 //
       
   116 CPbk2AddItemManager::~CPbk2AddItemManager()
       
   117     {
       
   118     delete iTemporaryPresentationContact;
       
   119     delete iTemporaryStoreContact;
       
   120     delete iGroupProperties;
       
   121     delete iXSpName;
       
   122     }
       
   123 
       
   124 // --------------------------------------------------------------------------
       
   125 // CPbk2AddItemManager::NewL
       
   126 // --------------------------------------------------------------------------
       
   127 //
       
   128 CPbk2AddItemManager* CPbk2AddItemManager::NewL
       
   129         ( CPbk2PresentationContact& aContact,
       
   130           MPbk2ContactEditorFieldArray& aFieldArray, 
       
   131           TPbk2ContactEditorParams& aParams,
       
   132           MPbk2ApplicationServices* aAppServices )
       
   133     {
       
   134     CPbk2AddItemManager* self = 
       
   135         new ( ELeave ) CPbk2AddItemManager( aContact, aFieldArray, aParams, aAppServices );
       
   136     return self;
       
   137     }
       
   138 
       
   139 // --------------------------------------------------------------------------
       
   140 // CPbk2AddItemManager::AddFieldsL
       
   141 // --------------------------------------------------------------------------
       
   142 //
       
   143 CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::AddFieldsL
       
   144  (TInt& aFieldTypeResId, TPtrC& aFieldTypeXspName )
       
   145     {
       
   146     CArrayPtr<const MPbk2FieldProperty>* propArray = 
       
   147         iContact->AvailableFieldsToAddL();
       
   148     CleanupStack::PushL(propArray);
       
   149     
       
   150     CPbk2ContactRelocator* contactRelocator = CPbk2ContactRelocator::NewL();
       
   151     CleanupStack::PushL( contactRelocator );
       
   152 
       
   153     if (!contactRelocator->IsPhoneMemoryContact( *iContact ) &&
       
   154             contactRelocator->IsPhoneMemoryInConfigurationL() &&
       
   155             IsValidStoreL ( Phonebook2::Pbk2AppUi()->ApplicationServices().
       
   156                 StoreValidityInformer(), VPbkContactStoreUris::DefaultCntDbUri() ) )
       
   157         {
       
   158         // Expand the property array with phone memory field types
       
   159         AddPhoneMemoryFieldTypesL(*propArray);
       
   160         }
       
   161 
       
   162     CleanupStack::PopAndDestroy( contactRelocator );
       
   163 
       
   164     
       
   165     // Create group properties
       
   166     if ( iGroupProperties )
       
   167         {
       
   168         delete iGroupProperties;
       
   169         iGroupProperties = NULL;                
       
   170         }
       
   171         
       
   172     iGroupProperties = CPbk2FieldGroupPropertyArray::NewL( *iProperties );
       
   173 
       
   174     TReturnValue ret = DoAddFieldsL(*propArray, aFieldTypeResId, aFieldTypeXspName);
       
   175             
       
   176     CleanupStack::PopAndDestroy(propArray);
       
   177     return ret;
       
   178     }
       
   179 
       
   180 // --------------------------------------------------------------------------
       
   181 // CPbk2AddItemManager::AddFieldsToUiAndContactL
       
   182 // --------------------------------------------------------------------------
       
   183 //
       
   184 inline CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::AddFieldsToUiAndContactL(
       
   185     const TPbk2AddItemWrapper& aWrapper)
       
   186     {
       
   187     TReturnValue ret;
       
   188     TInt controlId = KErrUnknown;
       
   189     const TInt count = aWrapper.PropertyCount();
       
   190     for (TInt i = 0; i < count; ++i)
       
   191         {
       
   192         const MPbk2FieldProperty& prop = aWrapper.PropertyAt(i);
       
   193 
       
   194 
       
   195         MPbk2FieldProperty2* fieldPropertyExtension =
       
   196             reinterpret_cast<MPbk2FieldProperty2*>(
       
   197                 const_cast<MPbk2FieldProperty&>( prop ).
       
   198                     FieldPropertyExtension(
       
   199                         KMPbk2FieldPropertyExtension2Uid ) );
       
   200         User::LeaveIfNull( fieldPropertyExtension ); 
       
   201         
       
   202         TInt tmpId = iFieldArray->AddNewFieldL( prop.FieldType(),
       
   203             fieldPropertyExtension->XSpName() );
       
   204         if (controlId == KErrUnknown)
       
   205             {
       
   206             controlId = tmpId;
       
   207             }
       
   208         }
       
   209     
       
   210     if( aWrapper.Group() )
       
   211     	{
       
   212     	ret.iGruopId = aWrapper.Group()->GroupId();
       
   213     	}
       
   214     
       
   215     ret.iControlId = controlId;
       
   216     return ret;
       
   217     }
       
   218     
       
   219 // --------------------------------------------------------------------------
       
   220 // CPbk2AddItemManager::RunDialogAndAddFieldsL
       
   221 // --------------------------------------------------------------------------
       
   222 //
       
   223 inline CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::RunDialogAndAddFieldsL
       
   224         ( RArray<TPbk2AddItemWrapper>& aWrappers,
       
   225           TInt& aFieldTypeResId, 
       
   226           TPtrC& aFieldTypeXspName )
       
   227     {
       
   228     TReturnValue ret;
       
   229     ret.iControlId = KErrUnknown;
       
   230     TInt selectionIndex( KErrNotFound );
       
   231     
       
   232     if (aWrappers.Count() > 0)
       
   233         {
       
   234         if ( aFieldTypeResId != KErrNotFound )
       
   235             {
       
   236             // Make a conversion from ResId to selection
       
   237             TInt wrapCount( aWrappers.Count() );
       
   238             for ( TInt i(0); i < wrapCount && selectionIndex == KErrNotFound; ++i)
       
   239                 {
       
   240                 TPbk2AddItemWrapper* wrapper = &aWrappers[i];
       
   241                 TInt propCount( wrapper->PropertyCount() );
       
   242                 for ( TInt j(0); j < propCount && selectionIndex == KErrNotFound; ++j )
       
   243                     {
       
   244                     const MPbk2FieldProperty& prop = wrapper->PropertyAt(j);
       
   245                     MPbk2FieldProperty2* fieldPropertyExtension =
       
   246                         reinterpret_cast<MPbk2FieldProperty2*>(
       
   247                             const_cast<MPbk2FieldProperty&>( prop ).
       
   248                                 FieldPropertyExtension(
       
   249                                     KMPbk2FieldPropertyExtension2Uid ) );
       
   250                     User::LeaveIfNull( fieldPropertyExtension );
       
   251                     if ( (aFieldTypeResId == prop.FieldType().FieldTypeResId() ) &&
       
   252                             !aFieldTypeXspName.CompareF(fieldPropertyExtension->XSpName()) )
       
   253                         {
       
   254                         selectionIndex = i;
       
   255                         }
       
   256                     }
       
   257                 }
       
   258             if ( selectionIndex == KErrNotFound )
       
   259                 {
       
   260                 // Field cannot be added to current contact
       
   261                 // propably it already exist and this field type cannot be 
       
   262                 // more than once in one contact
       
   263                 ret.iControlId = KErrAlreadyExists;
       
   264                 }
       
   265             }
       
   266         
       
   267         if( ret.iControlId == KErrUnknown )
       
   268             {
       
   269             if ( selectionIndex == KErrNotFound )
       
   270                 {
       
   271                 CPbk2AddItemToContactDlg* dlg = CPbk2AddItemToContactDlg::NewL( iAppServices );
       
   272                 TPbk2AddItemDialogParams params(NULL, 0, selectionIndex);
       
   273                 selectionIndex = dlg->ExecuteLD(aWrappers, &params);
       
   274                 }
       
   275                 
       
   276             if (selectionIndex != KErrCancel)
       
   277                 {
       
   278                 TPbk2AddItemWrapper* wrapper = &aWrappers[selectionIndex];
       
   279                 MPbk2FieldProperty2* fieldPropertyExtension =
       
   280                     reinterpret_cast<MPbk2FieldProperty2*>(
       
   281                         const_cast<MPbk2FieldProperty&>( wrapper->PropertyAt(0) ).
       
   282                             FieldPropertyExtension(
       
   283                                 KMPbk2FieldPropertyExtension2Uid ) );
       
   284                 User::LeaveIfNull( fieldPropertyExtension );
       
   285                 
       
   286                 aFieldTypeResId = wrapper->PropertyAt(0).FieldType().FieldTypeResId();
       
   287                 aFieldTypeXspName.Set(fieldPropertyExtension->XSpName());
       
   288                 delete iXSpName;
       
   289                 iXSpName = NULL;
       
   290                 if (aFieldTypeXspName != KNullDesC)
       
   291                     {
       
   292                     iXSpName = fieldPropertyExtension->XSpName().AllocL();
       
   293                     }
       
   294                 aFieldTypeXspName.Set(iXSpName ? *iXSpName : KNullDesC());
       
   295                 TRAPD(err, ret = AddFieldsToUiAndContactL(*wrapper));
       
   296                 
       
   297                 if (err == KErrNotSupported)
       
   298                     {
       
   299                     // KErrNotSupported means that the current
       
   300                     // contact does not support the selected detail.
       
   301                     // When receiving this error code the caller
       
   302                     // may choose to relocate the contact and try again.
       
   303                     ret.iControlId = KErrNotSupported;
       
   304                     }
       
   305                 else
       
   306                     {
       
   307                     User::LeaveIfError(err);
       
   308                     }
       
   309                 }
       
   310             }
       
   311         }
       
   312     return ret;
       
   313     }
       
   314 
       
   315 // --------------------------------------------------------------------------
       
   316 // CPbk2AddItemManager::AddPhoneMemoryFieldTypesL
       
   317 // --------------------------------------------------------------------------
       
   318 //
       
   319 inline void CPbk2AddItemManager::AddPhoneMemoryFieldTypesL
       
   320         (CArrayPtr<const MPbk2FieldProperty>& aProperties)
       
   321     {
       
   322     // Make a duplicate phone contact instance out of the current contact
       
   323     MakePhoneContactL(*iContact);
       
   324     
       
   325     // Get available fields to add to the phone contact
       
   326     CArrayPtr<const MPbk2FieldProperty>* phonePropArray =
       
   327         iTemporaryPresentationContact->AvailableFieldsToAddL();
       
   328     CleanupStack::PushL(phonePropArray);
       
   329     
       
   330     // Append new properties to the old array
       
   331     TInt currentPropertyCount = aProperties.Count();
       
   332     TInt phonePropertyCount = phonePropArray->Count();
       
   333     for (TInt i=0; i<phonePropertyCount; ++i)
       
   334         {
       
   335         TBool found = EFalse;
       
   336         const MPbk2FieldProperty* phoneProp = phonePropArray->At(i);
       
   337         for (TInt j=0; j<currentPropertyCount; ++j)
       
   338             {
       
   339             const MPbk2FieldProperty* prop = aProperties.At(j);
       
   340             if (prop->IsSame(*phoneProp))
       
   341                 {
       
   342                 found = ETrue;
       
   343                 break;
       
   344                 }
       
   345             }
       
   346         // Append the property only if not found already
       
   347         if ( !found && iParams.iActiveView == TPbk2ContactEditorParams::EEditorView )
       
   348             {
       
   349             aProperties.AppendL(phoneProp);
       
   350             }
       
   351         }
       
   352 
       
   353     CleanupStack::PopAndDestroy(phonePropArray);
       
   354     
       
   355     // Switch properties member to reference the properties of
       
   356     // the temporary contact
       
   357     iProperties = &iTemporaryPresentationContact->PresentationFields().
       
   358         FieldProperties();
       
   359     }
       
   360     
       
   361 // --------------------------------------------------------------------------
       
   362 // CPbk2AddItemManager::DoAddFieldsL
       
   363 // --------------------------------------------------------------------------
       
   364 //
       
   365 inline CPbk2AddItemManager::TReturnValue CPbk2AddItemManager::DoAddFieldsL
       
   366         (CArrayPtr<const MPbk2FieldProperty>& aProperties,
       
   367         TInt& aFieldTypeResId,
       
   368         TPtrC& aFieldTypeXspName )
       
   369     {
       
   370     RArray<TPbk2AddItemWrapper> wrappers;
       
   371     CleanupClosePushL(wrappers);
       
   372    
       
   373     RPointerArray<const CPbk2FieldPropertyGroup> addedGroups;
       
   374     CleanupClosePushL(addedGroups);
       
   375     
       
   376     const CPbk2FieldPropertyGroup* address = NULL;
       
   377     TInt countAddr = 0;
       
   378     const TInt count = aProperties.Count();
       
   379     for (TInt i = 0; i < count; ++i)
       
   380         {
       
   381         const MPbk2FieldProperty& prop = *(aProperties)[i];
       
   382         const CPbk2FieldPropertyGroup* group = 
       
   383             iGroupProperties->FindGroupForProperty(prop);
       
   384         
       
   385         TPbk2FieldGroupId propGroup = EPbk2FieldGroupIdNone; 
       
   386         if( group )
       
   387         	{
       
   388         	propGroup = group->GroupId();
       
   389         	}
       
   390 
       
   391         if ( propGroup != EPbk2FieldGroupIdNone )
       
   392         	{
       
   393         	 if( addedGroups.Find(group) == KErrNotFound  )
       
   394 	            {
       
   395 	            addedGroups.AppendL(group); 
       
   396 	            if (iContact->PresentationFields().ContainsFieldFromGroup(
       
   397 	                    *group))
       
   398 	                {
       
   399 	                if( propGroup != EPbk2FieldGroupIdPostalAddress &&
       
   400 	            		propGroup != EPbk2FieldGroupIdHomeAddress &&
       
   401 	            		propGroup != EPbk2FieldGroupIdCompanyAddress || 
       
   402 	            		aFieldTypeResId > 0 )
       
   403 	                	{
       
   404 		                // Item belongs to the group but there are already
       
   405 		                // items from the same group in the contact
       
   406 		                wrappers.AppendL(TPbk2AddItemWrapper(prop));
       
   407 	                	}
       
   408 	                }
       
   409 	            else
       
   410 	                {
       
   411 	                // Add the whole group of fields
       
   412 	                wrappers.AppendL(TPbk2AddItemWrapper(*group));
       
   413 	            	}
       
   414 	            }
       
   415             }
       
   416         else
       
   417         	{
       
   418             // Item doesn't belong to group
       
   419             wrappers.AppendL(TPbk2AddItemWrapper(prop));
       
   420         	}
       
   421         }
       
   422     
       
   423     CleanupStack::PopAndDestroy(); // addedGroups
       
   424 
       
   425     TReturnValue ret = RunDialogAndAddFieldsL(wrappers, aFieldTypeResId,
       
   426             aFieldTypeXspName);
       
   427     CleanupStack::PopAndDestroy(); // wrappers
       
   428     
       
   429     return ret;
       
   430     }
       
   431     
       
   432 // --------------------------------------------------------------------------
       
   433 // CPbk2AddItemManager::IsFieldAdditionPossibleL
       
   434 // --------------------------------------------------------------------------
       
   435 //
       
   436 inline TBool CPbk2AddItemManager::IsFieldAdditionPossibleL
       
   437         (const CPbk2PresentationContact& aContact,
       
   438         const MPbk2FieldProperty& aProperty)
       
   439     {
       
   440     TBool ret = EFalse;
       
   441     // To be able to add field requires that the property must fit
       
   442     // either into phone memory contact or into the current
       
   443     // memory contact
       
   444     if ((aContact.IsFieldAdditionPossibleL(aProperty.FieldType())) &&
       
   445           (aProperty.Flags() & KPbk2FieldFlagUserCanAddField))
       
   446         {
       
   447         ret = ETrue;
       
   448         }
       
   449 
       
   450     return ret;
       
   451     }
       
   452 
       
   453 // --------------------------------------------------------------------------
       
   454 // CPbk2AddItemManager::MakePhoneContactL
       
   455 // --------------------------------------------------------------------------
       
   456 //
       
   457 void CPbk2AddItemManager::MakePhoneContactL
       
   458         (const CPbk2PresentationContact& aContact)
       
   459     {
       
   460     // Get phone memory contact store
       
   461     MVPbkContactStore* phoneStore =
       
   462         Phonebook2::Pbk2AppUi()->ApplicationServices().ContactManager().
       
   463             ContactStoresL().Find
       
   464                 (VPbkContactStoreUris::DefaultCntDbUri());
       
   465             
       
   466     __ASSERT_DEBUG(phoneStore,
       
   467         Panic(EPanicPreCond_MakePhoneContactL));
       
   468 
       
   469     // Create a temporary contact to phone memory store
       
   470     iTemporaryStoreContact = phoneStore->CreateNewContactLC();
       
   471     CleanupStack::Pop(); // CreateNewContactLC
       
   472 
       
   473     // Make a presentation contact out of it
       
   474     iTemporaryPresentationContact = CPbk2PresentationContact::NewL
       
   475         (*iTemporaryStoreContact,
       
   476         Phonebook2::Pbk2AppUi()->ApplicationServices().FieldProperties());
       
   477     
       
   478     // Add the fields of the current store contact in to it
       
   479     const TInt count(aContact.Fields().FieldCount());
       
   480     for (TInt i = 0; i<count; ++i)
       
   481         {
       
   482         CPbk2PresentationContactField& field =
       
   483             aContact.PresentationFields().At(i);
       
   484         
       
   485         if (iTemporaryPresentationContact->IsFieldAdditionPossibleL
       
   486                 (field.FieldProperty().FieldType()))
       
   487             {
       
   488             MVPbkStoreContactField* newField =
       
   489                 iTemporaryPresentationContact->CreateFieldLC(
       
   490                     field.FieldProperty().FieldType());
       
   491             iTemporaryPresentationContact->AddFieldL(newField);
       
   492             CleanupStack::Pop(); // newField
       
   493             }
       
   494         }
       
   495     }
       
   496 
       
   497 //  End of File