/*
* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Phonebook 2 fetch results.
*
*/
#include "CPbk2FetchResults.h"
// Phonebook 2
#include "MPbk2FetchDlg.h"
#include "MPbk2FetchDlgPage.h"
#include "MPbk2FetchDlgPages.h"
#include "MPbk2FetchResultsObserver.h"
#include <MPbk2FetchDlgObserver.h>
#include <MPbk2ContactUiControl.h>
// Virtual Phonebook
#include <CVPbkContactLinkArray.h>
#include <MVPbkContactLink.h>
#include <CVPbkContactManager.h>
#include <MVPbkContactGroup.h>
#include <MVPbkContactStoreList.h>
#include <MVPbkContactStore.h>
#include <MVPbkContactOperationBase.h>
#include <MVPbkContactViewBase.h>
// System includes
#include <coemain.h>
// Debugging headers
#include <Pbk2Debug.h>
// --------------------------------------------------------------------------
// CPbk2FetchResults::CPbk2FetchResults
// --------------------------------------------------------------------------
//
CPbk2FetchResults::CPbk2FetchResults
( CVPbkContactManager& aContactManager,
MPbk2FetchDlg& aFetchDlg,
MPbk2FetchDlgPages& aPages,
MPbk2FetchDlgObserver& aObserver,
MPbk2FetchResultsObserver& aResultsObserver ) :
iContactManager( aContactManager ),
iFetchDlg( aFetchDlg ),
iPages( aPages ),
iObserver( aObserver ),
iResultsObserver( aResultsObserver )
{
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::~CPbk2FetchResults
// --------------------------------------------------------------------------
//
CPbk2FetchResults::~CPbk2FetchResults()
{
if ( iStoreList )
{
for ( TInt i = 0; i < iStoreList->Count(); ++i )
{
MVPbkContactStore& store = iStoreList->At( i );
store.Close( *this );
}
}
delete iSelectedContacts;
delete iRetrieveOperation;
if( iOperationQueue )
{
for ( TInt k = 0; k < iOperationQueue->Count(); k++ )
delete iOperationQueue->At(k);
delete iOperationQueue;
}
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::ConstructL
// --------------------------------------------------------------------------
//
inline void CPbk2FetchResults::ConstructL
( CVPbkContactManager& aContactManager )
{
iSelectedContacts = CVPbkContactLinkArray::NewL();
iStoreList = &aContactManager.ContactStoresL();
const TInt storeCount = iStoreList->Count();
for (TInt i = 0; i < storeCount; ++i)
{
MVPbkContactStore& store = iStoreList->At( i );
store.OpenL( *this );
}
iOperationQueue = new (ELeave) CArrayFixFlat<CFRConatactOperation*>(4);
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::NewL
// --------------------------------------------------------------------------
//
CPbk2FetchResults* CPbk2FetchResults::NewL
( CVPbkContactManager& aContactManager,
MPbk2FetchDlg& aFetchDlg, MPbk2FetchDlgPages& aPages,
MPbk2FetchDlgObserver& aObserver,
MPbk2FetchResultsObserver& aResultsObserver )
{
CPbk2FetchResults* self = new ( ELeave ) CPbk2FetchResults
( aContactManager, aFetchDlg, aPages, aObserver,
aResultsObserver );
CleanupStack::PushL( self );
self->ConstructL( aContactManager );
CleanupStack::Pop( self );
return self;
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::AppendL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::AppendL( const MVPbkContactLink& aLink )
{
CFRConatactOperation* newAppendOperation = CFRConatactOperation::NewL( aLink, CFRConatactOperation::EAppendContact );
AppendContactOperationL(newAppendOperation);
ProcessNextContactOperationL();
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::AppendDelayedL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::AppendDelayedL( const MVPbkContactLink& aLink )
{
CFRConatactOperation* newAppendOperation = CFRConatactOperation::NewL( aLink, CFRConatactOperation::EAppendContactDelayed );
AppendContactOperationL(newAppendOperation);
ProcessNextContactOperationL();
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::RemoveL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::RemoveL( const MVPbkContactLink& aLink )
{
CFRConatactOperation* newRemoveOperation = CFRConatactOperation::NewL( aLink, CFRConatactOperation::ERemoveContact );
AppendContactOperationL(newRemoveOperation);
ProcessNextContactOperationL();
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::ResetAndDestroy
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::ResetAndDestroy()
{
delete iRetrieveOperation;
iRetrieveOperation = NULL;
RemoveCurrentContactOperation();
iSelectedContacts->ResetAndDestroy();
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::Count
// --------------------------------------------------------------------------
//
TInt CPbk2FetchResults::Count() const
{
return iSelectedContacts->Count();
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::At
// --------------------------------------------------------------------------
//
const MVPbkContactLink& CPbk2FetchResults::At( TInt aIndex ) const
{
return iSelectedContacts->At( aIndex );
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::Find
// --------------------------------------------------------------------------
//
TInt CPbk2FetchResults::Find( const MVPbkContactLink& aLink ) const
{
return iSelectedContacts->Find( aLink );
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::PackLC
// --------------------------------------------------------------------------
//
HBufC8* CPbk2FetchResults::PackLC() const
{
return iSelectedContacts->PackLC();
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::Streamable
// --------------------------------------------------------------------------
//
const MVPbkStreamable* CPbk2FetchResults::Streamable() const
{
return iSelectedContacts->Streamable();
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::VPbkSingleContactOperationComplete
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::VPbkSingleContactOperationComplete
( MVPbkContactOperationBase& aOperation,
MVPbkStoreContact* aContact )
{
TRAPD( err, HandleContactOperationCompleteL( aOperation, aContact ) );
if ( err != KErrNone )
{
iResultsObserver.ContactSelectionFailed();
CCoeEnv::Static()->HandleError( err );
}
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::VPbkSingleContactOperationFailed
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::VPbkSingleContactOperationFailed
( MVPbkContactOperationBase& /*aOperation*/, TInt aError )
{
iResultsObserver.ContactSelectionFailed();
CCoeEnv::Static()->HandleError( aError );
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::StoreReady
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::StoreReady
( MVPbkContactStore& /*aContactStore*/ )
{
// Do nothing
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::StoreUnavailable
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::StoreUnavailable
( MVPbkContactStore& /*aContactStore*/, TInt /*aReason*/ )
{
// Do nothing
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::HandleStoreEventL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::HandleStoreEventL
( MVPbkContactStore& /*aContactStore*/,
TVPbkContactStoreEvent aStoreEvent )
{
switch ( aStoreEvent.iEventType )
{
case TVPbkContactStoreEvent::EContactDeleted:
{
// Do not update UI selections - just remove the link
// from results. The view event, listened by the control,
// takes care of updating the UI selections.
TInt findResult = iSelectedContacts->Find( *aStoreEvent.iContactLink );
if ( findResult != KErrNotFound )
{
User::LeaveIfError( findResult );
iSelectedContacts->Delete( findResult );
}
break;
}
case TVPbkContactStoreEvent::EGroupDeleted:
{
// Do nothing.
// This means that we keep the selection of the contacts
// which belonged to a group when the group is deleted.
break;
}
default:
{
// Do nothing
break;
}
}
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::DoAppendContactL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::DoAppendContactL
( MVPbkStoreContact& aContact, TBool aDelayed )
{
MVPbkContactLink* link = aContact.CreateLinkLC();
TInt count = CountContactsL( aContact, *link );
// Ask observer for acceptance
MPbk2FetchDlgObserver::TPbk2FetchAcceptSelection accept =
MPbk2FetchDlgObserver::EFetchYes;
if ( !aDelayed )
{
// Observer needs to asked
accept = iObserver.AcceptFetchSelectionL( count, *link );
}
if ( accept == MPbk2FetchDlgObserver::EFetchNo )
{
// Observer did not accept or delayed the selection
MVPbkContactViewBase& view = iFetchDlg.FetchDlgViewL
( iPages.CurrentPage().FetchDlgPageId() );
TInt index = view.IndexOfLinkL( *link );
iPages.CurrentPage().Control().SetSelectedContactL
( index, EFalse );
}
else if( accept == MPbk2FetchDlgObserver::EFetchYes )
{
MVPbkContactGroup* group = aContact.Group();
if ( group )
{
// Contact was a group, insert group members into append queue
MVPbkContactLinkArray* groupMembers = group->ItemsContainedLC();
for ( TInt i = 0; i < groupMembers->Count(); ++i )
{
AppendToResultsL( groupMembers->At( i ) );
}
CleanupStack::PopAndDestroy(); // groupMembers
}
else
{
AppendToResultsL( *link );
}
iResultsObserver.ContactSelected( *link, ETrue );
}
CleanupStack::PopAndDestroy(); // link
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::DoRemoveContactL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::DoRemoveContactL( MVPbkStoreContact& aContact )
{
MVPbkContactLink* link = aContact.CreateLinkLC();
MVPbkContactGroup* group = aContact.Group();
if ( group )
{
MVPbkContactLinkArray* groupMembers = group->ItemsContainedLC();
for ( TInt i = 0; i < groupMembers->Count(); ++i )
{
RemoveFromResultsL( groupMembers->At( i ) );
}
CleanupStack::PopAndDestroy(); // groupMembers
}
else
{
RemoveFromResultsL( *link );
}
iResultsObserver.ContactSelected( *link, EFalse );
CleanupStack::PopAndDestroy(); // link
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::AppendToResultsL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::AppendToResultsL( const MVPbkContactLink& aLink )
{
TInt findResult = iSelectedContacts->Find( aLink );
if ( findResult == KErrNotFound )
{
iPages.SelectContactL( aLink, ETrue );
MVPbkContactLink* clone = aLink.CloneLC();
CleanupStack::Pop(); // clone
iSelectedContacts->AppendL( clone );
}
else
{
User::LeaveIfError( findResult );
}
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::RemoveFromResultsL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::RemoveFromResultsL( const MVPbkContactLink& aLink )
{
TInt findResult = iSelectedContacts->Find( aLink );
if ( findResult != KErrNotFound )
{
User::LeaveIfError( findResult );
iPages.SelectContactL( aLink, EFalse );
iSelectedContacts->Delete( findResult );
}
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::CountContactsL
// --------------------------------------------------------------------------
//
TInt CPbk2FetchResults::CountContactsL
( MVPbkStoreContact& aContact, MVPbkContactLink& aLink )
{
TInt count = iSelectedContacts->Count();
MVPbkContactGroup* group = aContact.Group();
if ( group )
{
// Contact was a group, insert group members into append queue
MVPbkContactLinkArray* groupMembers = group->ItemsContainedLC();
for ( TInt i = 0; i < groupMembers->Count(); ++i )
{
if ( iSelectedContacts->Find( groupMembers->At( i ) )
== KErrNotFound )
{
++count;
}
}
CleanupStack::PopAndDestroy(); // groupMembers
}
else
{
if ( iSelectedContacts->Find( aLink ) == KErrNotFound )
{
++count;
}
}
return count;
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::HandleContactOperationCompleteL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::HandleContactOperationCompleteL(
MVPbkContactOperationBase& /*aOperation*/,
MVPbkStoreContact* aContact )
{
/*************** Do class member operations here *****************/
// Delete retrieve contact operation ptr
delete iRetrieveOperation;
iRetrieveOperation = NULL;
// Copy current operation type before deleting
CFRConatactOperation::EOperationType operationType =
GetCurrentContactOperation()->GetOperationType();
// Remove executed operation from queue
RemoveCurrentContactOperation();
// Initialize next operation from queue
ProcessNextContactOperationL();
/**********************************************************************/
/**************! Dont use class members after SWITCH !*****************/
/*** DoAppendContactL, DoRemoveContactL are able to call destructor ***/
/**********************************************************************/
// Finish contact operation
CleanupDeletePushL( aContact );
switch( operationType )
{
case CFRConatactOperation::EAppendContact:
{
DoAppendContactL( *aContact, EFalse );
break;
}
case CFRConatactOperation::EAppendContactDelayed:
{
DoAppendContactL( *aContact, ETrue );
break;
}
case CFRConatactOperation::ERemoveContact:
{
DoRemoveContactL( *aContact );
break;
}
}
CleanupStack::PopAndDestroy(); // aContact
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::ProcessNextContactOperationL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::ProcessNextContactOperationL()
{
if( !iRetrieveOperation )
{
// No operation is executing -> process next one
if( GetCurrentContactOperation() )
{
// Start asynchronous contact retrieve operation, which completes
// in CPbk2FetchResults::HandleContactOperationCompleteL.
iRetrieveOperation = iContactManager.RetrieveContactL( *( GetCurrentContactOperation()->GetContactLink() ),
*this );
}
else
{
// Empty operation queue -> do nothing
PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING( "CPbk2FetchResults::ProcessNextContactOperationL emtpy queue" ));
}
}
else
{
// Ongoing operation -> do nothing
PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING( "CPbk2FetchResults::ProcessNextContactOperationL busy" ));
}
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::AppendContactOperationL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::AppendContactOperationL( CFRConatactOperation* aOperation )
{
iOperationQueue->AppendL( aOperation ); // Append to the end
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::GetCurrentContactOperation
// --------------------------------------------------------------------------
//
CPbk2FetchResults::CFRConatactOperation* CPbk2FetchResults::GetCurrentContactOperation()
{
if( iOperationQueue->Count() )
return iOperationQueue->At(0); // Return first element
else
return NULL; // If empty, return NULL
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::RemoveCurrentContactOperation
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::RemoveCurrentContactOperation( )
{
if( iOperationQueue->Count() )
{
// Remove and delete first operation
delete ( iOperationQueue->At( 0 ) );
iOperationQueue->Delete( 0 );
}
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::CFRConatactOperation::NewL
// --------------------------------------------------------------------------
//
CPbk2FetchResults::CFRConatactOperation* CPbk2FetchResults::CFRConatactOperation::NewL(
const MVPbkContactLink& aContactLink, const EOperationType aType )
{
CFRConatactOperation* self = new ( ELeave ) CFRConatactOperation( aType );
CleanupStack::PushL( self );
self->ConstructL( aContactLink );
CleanupStack::Pop( self );
return self;
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::CFRConatactOperation::CFRConatactOperation
// --------------------------------------------------------------------------
//
CPbk2FetchResults::CFRConatactOperation::CFRConatactOperation(
const EOperationType aType ):
iType( aType )
{
// Nothing
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::CFRConatactOperation::~CFRConatactOperation
// --------------------------------------------------------------------------
//
CPbk2FetchResults::CFRConatactOperation::~CFRConatactOperation( )
{
delete iContactLink;
}
// --------------------------------------------------------------------------
// CPbk2FetchResults::CFRConatactOperation::ConstructL
// --------------------------------------------------------------------------
//
void CPbk2FetchResults::CFRConatactOperation::ConstructL(
const MVPbkContactLink& aContactLink )
{
// Copy ContactLink
iContactLink = aContactLink.CloneLC();
CleanupStack::Pop();
}
// End of File