phonebookui/Phonebook2/UIControls/src/CPbk2FetchResults.cpp
changeset 0 e686773b3f54
child 58 d4f567ce2e7c
--- /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 <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