diff -r 000000000000 -r e686773b3f54 phonebookui/Phonebook2/UIControls/src/CPbk2FetchResults.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/UIControls/src/CPbk2FetchResults.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,638 @@ +/* +* 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 +#include + +// Virtual Phonebook +#include +#include +#include +#include +#include +#include +#include +#include + +// System includes +#include + +// Debugging headers +#include + +// -------------------------------------------------------------------------- +// 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(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