/*
* 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: A phonebook2 presentation level contact
*
*/
#include "CPbk2PresentationContact.h"
// Phonebook 2
#include <CPbk2PresentationContactField.h>
#include <CPbk2PresentationContactFieldCollection.h>
#include <MPbk2FieldProperty.h>
#include <MPbk2FieldProperty2.h>
#include <CPbk2FieldPropertyArray.h>
#include <Phonebook2PrivateCRKeys.h>
// Virtual Phonebook
#include <MVPbkFieldType.h>
#include <MVPbkContactStore.h>
#include <MVPbkContactStoreProperties.h>
#include <MVPbkContactFieldUriData.h>
#include <MVPbkStoreContact2.h>
#include <TVPbkFieldVersitProperty.h>
#include <VPbkVariant.hrh>
#include <VPbkEng.rsg>
// System includes
#include <centralrepository.h>
/// Unnamed namespace for local definitions
namespace {
// This is done locally here because we are not dependent from CommonUI
TBool LocalVariationFeatureEnabled( TInt aFeatureFlag )
{
TInt lvFlags( KErrNotFound );
TBool ret( EFalse );
CRepository* key = NULL;
// Read local variation flags
TRAPD( err, key =
CRepository::NewL(TUid::Uid(KCRUidPhonebook)));
// if NewL fails do not set iLVFlags, new query is made next time
if ( err == KErrNone )
{
err = key->Get(KPhonebookLocalVariationFlags, lvFlags);
if (err != KErrNone)
{
// If there were problems reading the flags,
// assume everything is off
lvFlags = 0;
}
delete key;
}
if ( lvFlags != KErrNotFound )
{
ret = lvFlags & aFeatureFlag;
}
return ret;
}
TBool IsVariatedLocallyL( const MPbk2FieldProperty& aProperty )
{
// Check if "pager" field should be part of the template,
// USA flagged feature
// Read local variation flag for pager field
TBool useInTemplate ( ETrue );
if ( aProperty.FieldType().FieldTypeResId() ==
R_VPBK_FIELD_TYPE_PAGERNUMBER )
{
useInTemplate =
LocalVariationFeatureEnabled( EVPbkLVPagerInTemplate );
}
// Returns ETrue if field with aProperty should be added to contact.
return useInTemplate;
}
} /// namespace
// --------------------------------------------------------------------------
// CPbk2PresentationContact::CPbk2PresentationContact
// C++ default constructor can NOT contain any code, that
// might leave.
// --------------------------------------------------------------------------
//
CPbk2PresentationContact::CPbk2PresentationContact(
MVPbkStoreContact& aStoreContact,
const MPbk2FieldPropertyArray& aFieldProperties)
: iStoreContact(aStoreContact),
iFieldProperties(aFieldProperties)
{
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::ConstructL
// Symbian 2nd phase constructor can leave.
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::ConstructL()
{
iCollection = CPbk2PresentationContactFieldCollection::NewL(
iFieldProperties, iStoreContact.Fields(), *this);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::NewL
// Two-phased constructor.
// --------------------------------------------------------------------------
//
EXPORT_C CPbk2PresentationContact* CPbk2PresentationContact::NewL(
MVPbkStoreContact& aStoreContact,
const MPbk2FieldPropertyArray& aFieldProperties)
{
CPbk2PresentationContact* self =
new( ELeave ) CPbk2PresentationContact(aStoreContact, aFieldProperties);
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
// Destructor
CPbk2PresentationContact::~CPbk2PresentationContact()
{
delete iCollection;
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::IsFieldAdditionPossibleL
// --------------------------------------------------------------------------
//
EXPORT_C TBool CPbk2PresentationContact::IsFieldAdditionPossibleL(
const MVPbkFieldType& aType) const
{
TInt max = MaxNumberOfFieldL(aType);
if (max == KVPbkStoreContactUnlimitedNumber)
{
return ETrue;
}
else
{
TInt cur = CurrentAmountOfFieldTypeInContact(aType, KNullDesC);
return cur < max;
}
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::AddSupportedTemplateFieldsL
// --------------------------------------------------------------------------
//
EXPORT_C void CPbk2PresentationContact::AddSupportedTemplateFieldsL()
{
// Adds fields that belongs to the template according to UI specification.
// In addition checks that the store supports the field and that
// there isn't already a same type of field in the contact.
// Also locally variated features are checked.
const MVPbkFieldTypeList& supportedTypes =
iStoreContact.ParentStore().StoreProperties().SupportedFields();
const TInt count = iFieldProperties.Count();
for (TInt i = 0; i < count; ++i)
{
const MPbk2FieldProperty& prop = iFieldProperties.At( i );
MPbk2FieldProperty2* fieldPropertyExtension =
reinterpret_cast<MPbk2FieldProperty2*>(
const_cast<MPbk2FieldProperty&>( prop ).
FieldPropertyExtension(
KMPbk2FieldPropertyExtension2Uid ) );
if ( fieldPropertyExtension != NULL )
{
if ( prop.Flags() & KPbk2FieldFlagTemplateField &&
supportedTypes.ContainsSame( prop.FieldType() ) &&
CurrentAmountOfFieldTypeInContact( prop.FieldType(),
fieldPropertyExtension->XSpName() ) == 0 &&
IsVariatedLocallyL( prop ) )
{
AddFieldL( CreateFieldLC( prop.FieldType() ),
fieldPropertyExtension->XSpName() );
CleanupStack::Pop(); // new field
}
}
}
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::AvailableFieldsToAddL
// --------------------------------------------------------------------------
//
EXPORT_C CArrayPtr<const MPbk2FieldProperty>*
CPbk2PresentationContact::AvailableFieldsToAddL() const
{
const TInt count = iFieldProperties.Count();
CArrayPtrFlat<const MPbk2FieldProperty>* propArray =
new(ELeave) CArrayPtrFlat<const MPbk2FieldProperty>(count);
CleanupStack::PushL(propArray);
for (TInt i = 0; i < count; ++i)
{
const MPbk2FieldProperty& prop = iFieldProperties.At(i);
if (IsFieldAdditionPossibleL(prop.FieldType()) &&
prop.Flags() & KPbk2FieldFlagUserCanAddField)
{
propArray->AppendL(&prop);
}
}
propArray->Compress();
CleanupStack::Pop(propArray);
return propArray;
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::ParentObject
// --------------------------------------------------------------------------
//
MVPbkObjectHierarchy& CPbk2PresentationContact::ParentObject() const
{
return iStoreContact.ParentObject();
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::Fields
// --------------------------------------------------------------------------
//
const MVPbkStoreContactFieldCollection& CPbk2PresentationContact::Fields() const
{
return *iCollection;
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::IsSame
// --------------------------------------------------------------------------
//
TBool CPbk2PresentationContact::IsSame(
const MVPbkStoreContact& aOtherContact) const
{
const CPbk2PresentationContact* cnt =
dynamic_cast<const CPbk2PresentationContact*>(&aOtherContact);
if (cnt)
{
return iStoreContact.IsSame(cnt->iStoreContact);
}
return iStoreContact.IsSame(aOtherContact);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::CreateLinkLC
// --------------------------------------------------------------------------
//
MVPbkContactLink* CPbk2PresentationContact::CreateLinkLC() const
{
return iStoreContact.CreateLinkLC();
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::DeleteL
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::DeleteL(MVPbkContactObserver& aObserver) const
{
iStoreContact.DeleteL(aObserver);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::Close
// Does not destroy iStoreContact, since it is not owned
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::Close() const
{
delete this;
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::ParentStore
// --------------------------------------------------------------------------
//
MVPbkContactStore& CPbk2PresentationContact::ParentStore() const
{
return iStoreContact.ParentStore();
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::Fields
// --------------------------------------------------------------------------
//
MVPbkStoreContactFieldCollection& CPbk2PresentationContact::Fields()
{
return *iCollection;
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::CreateFieldLC
// --------------------------------------------------------------------------
//
MVPbkStoreContactField* CPbk2PresentationContact::CreateFieldLC(
const MVPbkFieldType& aFieldType) const
{
return iStoreContact.CreateFieldLC(aFieldType);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::AddFieldL
// --------------------------------------------------------------------------
//
TInt CPbk2PresentationContact::AddFieldL(MVPbkStoreContactField* aField)
{
// The aField instance can not be used after AddFieldL
TInt index = iStoreContact.AddFieldL(aField);
MVPbkStoreContactFieldCollection& fields = iStoreContact.Fields();
// Create a presistent store field for the mapping field
const MVPbkStoreContactField& field = fields.FieldAt(index);
TRAPD(res, iCollection->AddFieldMappingL(field, KNullDesC));
if (res != KErrNone)
{
// If creation of mapping field failed, remove also the field
// from the store
iStoreContact.RemoveField(index);
User::Leave(res);
}
return iCollection->FindFieldIndex(field);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::RemoveField
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::RemoveField(TInt aIndex)
{
TInt storeIndex = iCollection->StoreIndexOfField(aIndex);
iStoreContact.RemoveField(storeIndex);
iCollection->RemoveFieldMapping(aIndex);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::RemoveAllFields
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::RemoveAllFields()
{
iCollection->ResetFieldMappings();
iStoreContact.RemoveAllFields();
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::LockL
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::LockL(MVPbkContactObserver& aObserver) const
{
iStoreContact.LockL(aObserver);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::CommitL
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::CommitL(MVPbkContactObserver& aObserver) const
{
iStoreContact.CommitL(aObserver);
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::GroupsJoinedLC
// --------------------------------------------------------------------------
//
MVPbkContactLinkArray* CPbk2PresentationContact::GroupsJoinedLC() const
{
return iStoreContact.GroupsJoinedLC();
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::Group
// --------------------------------------------------------------------------
//
MVPbkContactGroup* CPbk2PresentationContact::Group()
{
return iStoreContact.Group();
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::MaxNumberOfFieldL
// In addition of checking the store maximum MaxNumberOfFieldL()
// checks the multiplicity defined in the field property for
// the given field type.
// --------------------------------------------------------------------------
//
TInt CPbk2PresentationContact::MaxNumberOfFieldL(
const MVPbkFieldType& aType ) const
{
// Get the store limits
TInt res = iStoreContact.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 = iFieldProperties.FindProperty(aType);
if (prop && prop->Multiplicity() == EPbk2FieldMultiplicityOne)
{
res = oneFieldInContact;
}
}
return res;
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::StoreContactExtension
// --------------------------------------------------------------------------
//
TAny* CPbk2PresentationContact::StoreContactExtension(TUid aExtensionUid)
{
if( aExtensionUid == KMVPbkStoreContactExtension2Uid )
return static_cast<MVPbkStoreContact2*>( this );
return NULL;
}
// CPbk2PresentationContact::PropertiesLC
// --------------------------------------------------------------------------
//
MVPbkStoreContactProperties* CPbk2PresentationContact::PropertiesL() const
{
MVPbkStoreContact2* tempContact =
reinterpret_cast<MVPbkStoreContact2*>
(iStoreContact.StoreContactExtension
(KMVPbkStoreContactExtension2Uid));
return tempContact->PropertiesL();
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::SetAsOwnL
// --------------------------------------------------------------------------
//
void CPbk2PresentationContact::SetAsOwnL(
MVPbkContactObserver& aObserver) const
{
MVPbkStoreContact2* tempContact =
reinterpret_cast<MVPbkStoreContact2*>
(iStoreContact.StoreContactExtension
(KMVPbkStoreContactExtension2Uid));
tempContact->SetAsOwnL( aObserver );
}
// -----------------------------------------------------------------------------
// CPbk2PresentationContact::MatchContactStore
// -----------------------------------------------------------------------------
//
TBool CPbk2PresentationContact::MatchContactStore(
const TDesC& aContactStoreUri) const
{
return iStoreContact.MatchContactStore(aContactStoreUri);
}
// -----------------------------------------------------------------------------
// CPbk2PresentationContact::MatchContactStoreDomain
// -----------------------------------------------------------------------------
//
TBool CPbk2PresentationContact::MatchContactStoreDomain(
const TDesC& aContactStoreDomain) const
{
return iStoreContact.MatchContactStoreDomain(aContactStoreDomain);
}
// -----------------------------------------------------------------------------
// CPbk2PresentationContact::CreateBookmarkLC
// -----------------------------------------------------------------------------
//
MVPbkContactBookmark* CPbk2PresentationContact::CreateBookmarkLC() const
{
return iStoreContact.CreateBookmarkLC();
}
// -----------------------------------------------------------------------------
// CPbk2PresentationContact::CurrentAmountOfFieldTypeInContact
// -----------------------------------------------------------------------------
//
TInt CPbk2PresentationContact::CurrentAmountOfFieldTypeInContact(
const MVPbkFieldType& aType, const TDesC& aName ) const
{
const TInt maxMatchPriority = iStoreContact.ContactStore().
StoreProperties().SupportedFields().MaxMatchPriority();
const TInt count = iCollection->FieldCount();
TInt res = 0;
for ( TInt i = 0; i < count; ++i )
{
const MVPbkStoreContactField& field = iCollection->FieldAt(i);
const MVPbkFieldType* type = NULL;
for ( TInt j = 0; j < maxMatchPriority && !type; ++j )
{
type = field.MatchFieldType(j);
}
if ( (aType.IsSame( *type ) ) )
{
if (aName == KNullDesC)
{
++res;
}
else
{
TVPbkFieldVersitProperty prop;
prop.SetName(EVPbkVersitNameIMPP);
if (aType.Matches(prop, 0) &&
(MVPbkContactFieldUriData::Cast(field.FieldData()).
Scheme() == aName))
{
res++;
}
}
}
}
return res;
}
// --------------------------------------------------------------------------
// CPbk2PresentationContact::AddFieldL
// --------------------------------------------------------------------------
//
EXPORT_C TInt CPbk2PresentationContact::AddFieldL(MVPbkStoreContactField* aField,
const TDesC& aName)
{
// The aField instance can not be used after AddFieldL
TInt index = iStoreContact.AddFieldL(aField);
MVPbkStoreContactFieldCollection& fields = iStoreContact.Fields();
// Create a presistent store field for the mapping field
const MVPbkStoreContactField& field = fields.FieldAt(index);
TRAPD(res, iCollection->AddFieldMappingL(field, aName));
if (res != KErrNone)
{
// If creation of mapping field failed, remove also the field
// from the store
iStoreContact.RemoveField(index);
User::Leave(res);
}
return iCollection->FindFieldIndex(field);
}
// End of File