phonebookui/Phonebook2/CommonUI/src/CPbk2NavigationBase.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/CommonUI/src/CPbk2NavigationBase.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,470 @@
+/*
+* 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 contact navigator base.
+*
+*/
+
+
+#include "CPbk2NavigationBase.h"
+
+// Phonebook 2
+#include <MPbk2NavigationObserver.h>
+#include <MPbk2ContactNavigationLoader.h>
+
+// Virtual Phonebook
+#include <MVPbkContactStore.h>
+#include <MVPbkContactViewBase.h>
+#include <MVPbkContactLink.h>
+
+// System Includes
+#include <coemain.h>
+
+// Debugging headers
+#include <Pbk2Debug.h>
+
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CPbk2NavigationBase
+// --------------------------------------------------------------------------
+//
+CPbk2NavigationBase::CPbk2NavigationBase
+        ( MPbk2NavigationObserver& aObserver,
+          MPbk2ContactNavigationLoader& aNavigationLoader,
+          TArray<MVPbkContactStore*> aStoreList ):
+            iNavigationObserver( aObserver ),
+            iNavigationLoader( aNavigationLoader ),
+            iStoreList( aStoreList )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::~CPbk2NavigationBase
+// --------------------------------------------------------------------------
+//
+CPbk2NavigationBase::~CPbk2NavigationBase()
+    {
+    RemoveViewObserver();
+    delete iOwnedView;
+    
+    CloseStores();
+    
+    delete iIdleNotifier;
+    delete iDeletedContactInfo;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::BaseConstructL
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::BaseConstructL()
+    {
+    iDeletedContactInfo = new( ELeave ) CDeletedContactInfo( *this );
+    
+    const TInt storeCount = iStoreList.Count();
+    for (TInt i = 0; i < storeCount; ++i)
+        {
+        MVPbkContactStore& store = *iStoreList[i];
+        // Asynchronous call to open a store
+        store.OpenL( *this );
+        }
+    }
+    
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::SetScrollViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::SetScrollViewL
+        ( MVPbkContactViewBase* aScrollView, TBool aOwnershipTransfered )
+    {
+    // If there was a scroll view set, remove observer and delete it
+    if ( iScrollView )
+        {
+        iScrollView->RemoveObserver( *this );
+        delete iOwnedView;
+        iOwnedView = NULL;
+        }
+
+    iScrollView = NULL;
+
+    // Set new scroll view and add observer
+    if ( aScrollView )
+        {
+        iScrollView = aScrollView;
+        if ( aOwnershipTransfered )
+            {
+            iOwnedView = aScrollView;
+            }
+        iScrollView->AddObserverL( *this );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CurrentContactLC
+// --------------------------------------------------------------------------
+//
+MVPbkContactLink* CPbk2NavigationBase::CurrentContactLC() const
+    {
+    MVPbkContactLink* link = iDeletedContactInfo->FocusedContactOrNullLC();
+    if ( !link )
+        {
+        CleanupStack::Pop( link );
+        link = iNavigationLoader.ContactLinkLC();
+        }
+    return link;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::ContactViewReady
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::ContactViewReady
+        ( MVPbkContactViewBase& /*aView*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::ContactViewUnavailable
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::ContactViewUnavailable
+        ( MVPbkContactViewBase& /*aView*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::ContactAddedToView
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::ContactAddedToView
+        ( MVPbkContactViewBase& /*aView*/, TInt /*aIndex*/,
+          const MVPbkContactLink& /*aContactLink*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2VoidNavigation::ContactRemovedFromView
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::ContactRemovedFromView
+        ( MVPbkContactViewBase& aView, TInt aIndex,
+          const MVPbkContactLink& aContactLink )
+    {
+    TRAPD( res, HandleContactRemovedFromViewL( aView,
+            aIndex, aContactLink ) );
+    if ( res != KErrNone )
+        {
+        CCoeEnv::Static()->HandleError( res );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::ContactViewError
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::ContactViewError
+        ( MVPbkContactViewBase& /*aView*/, TInt /*aError*/,
+          TBool /*aErrorNotified*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::StoreReady
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::StoreReady
+        ( MVPbkContactStore& /*aContactStore*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::StoreUnavailable
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::StoreUnavailable
+        ( MVPbkContactStore& /*aContactStore*/, TInt /*aReason*/ )
+    {
+    // Do nothing
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::HandleStoreEventL
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::HandleStoreEventL
+        ( MVPbkContactStore& aContactStore,
+          TVPbkContactStoreEvent aStoreEvent )
+    {
+    iDeletedContactInfo->HandleStoreEventL( aContactStore, aStoreEvent );
+    
+    switch ( aStoreEvent.iEventType )
+        {
+        case TVPbkContactStoreEvent::EContactChanged:
+            {
+            MVPbkContactLink* currentContact =
+                iNavigationLoader.ContactLinkLC();
+
+            if ( currentContact && aStoreEvent.iContactLink &&
+                currentContact->IsSame( *aStoreEvent.iContactLink ) )
+                {
+                // Reload current contact
+                iNavigationLoader.ChangeContactL( *currentContact );
+                }
+            CleanupStack::PopAndDestroy(); // currentContact
+            break;
+            }
+        case TVPbkContactStoreEvent::EGroupDeleted: // FALLTHROUGH
+        case TVPbkContactStoreEvent::EContactDeleted:
+            {
+            // Start the call back after we have got event from both
+            // store and view. But if we do not have iScrollView then only
+            // store event is enough.
+            if ( iDeletedContactInfo->DeletedAndRemoved() || !iScrollView )
+                {
+                StartIdleCallBackL();
+                }
+            break;
+            }
+        default:
+            {
+            // Do nothing
+            break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::HandleContactRemovedFromViewL
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::HandleContactRemovedFromViewL( 
+        MVPbkContactViewBase& aView,
+        TInt aIndex,
+        const MVPbkContactLink& aContactLink )
+    {
+    iDeletedContactInfo->HandleContactRemovedFromViewL( aView,
+            aIndex, aContactLink );
+    
+    if ( iDeletedContactInfo->DeletedAndRemoved() )
+        {
+        StartIdleCallBackL();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CloseStores
+// --------------------------------------------------------------------------
+//        
+void CPbk2NavigationBase::CloseStores()
+    {
+    for ( TInt i = 0; i < iStoreList.Count(); ++i )
+        {
+        MVPbkContactStore& store = *iStoreList[i];
+        store.Close( *this );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::RemoveViewObserver
+// --------------------------------------------------------------------------
+//        
+void CPbk2NavigationBase::RemoveViewObserver()
+    {
+    if ( iScrollView )
+        {
+        iScrollView->RemoveObserver( *this );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::StartIdleCallBackL
+// --------------------------------------------------------------------------
+//    
+void CPbk2NavigationBase::StartIdleCallBackL()
+    {
+    // The viewed contact was deleted, signal the
+    // observer asynchronously that the contact was deleted
+    if ( !iIdleNotifier )
+        {
+        iIdleNotifier = CIdle::NewL( CActive::EPriorityStandard );
+        }
+    else
+        {
+        iIdleNotifier->Cancel();
+        }
+    iIdleNotifier->Start
+        ( TCallBack( &IdleNotifierCallBack, this ) );
+    }
+    
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::IdleNotifierCallBack
+// --------------------------------------------------------------------------
+//
+TInt CPbk2NavigationBase::IdleNotifierCallBack( TAny* aSelf )
+    {
+    static_cast<CPbk2NavigationBase*>( aSelf )->HandleIdleNotify();
+    return EFalse;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::HandleIdleNotify
+// --------------------------------------------------------------------------
+//
+void CPbk2NavigationBase::HandleIdleNotify()
+    {
+    iNavigationObserver.HandleNavigationEvent
+        ( MPbk2NavigationObserver::EContactDeleted );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CDeletedContactInfo::CDeletedContactInfo
+// --------------------------------------------------------------------------
+//
+CPbk2NavigationBase::CDeletedContactInfo::CDeletedContactInfo( 
+        CPbk2NavigationBase& aNavigationBase )
+        :   iNavigationBase ( aNavigationBase ),
+            iRemovedContactIndex( KErrNotFound )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CDeletedContactInfo::~CDeletedContactInfo
+// --------------------------------------------------------------------------
+//     
+CPbk2NavigationBase::CDeletedContactInfo::~CDeletedContactInfo()
+    {
+    delete iDeletedContact;
+    delete iRemovedContact;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CDeletedContactInfo::HandleContactRemovedFromViewL
+// --------------------------------------------------------------------------
+//             
+void CPbk2NavigationBase::CDeletedContactInfo::HandleContactRemovedFromViewL(
+        MVPbkContactViewBase& /*aView*/,
+        TInt aIndex,
+        const MVPbkContactLink& aContactLink )
+    {
+    /// Handle delete event but not if we already have the information
+    /// that the current contact was deleted.
+    if ( !DeletedAndRemoved() )
+        {
+        MVPbkContactLink* curContact = 
+                iNavigationBase.NavigationLoader().ContactLinkLC();
+        
+        // Save the removed contact if it's the current contact
+        if ( curContact && curContact->IsSame( aContactLink ) )
+            {
+            delete iRemovedContact;
+            iRemovedContact = curContact;
+            CleanupStack::Pop(); // curContact
+            iRemovedContactIndex = aIndex;
+            }
+        else
+            {
+            CleanupStack::PopAndDestroy(); // curContact
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CDeletedContactInfo::HandleStoreEventL
+// --------------------------------------------------------------------------
+//                     
+void CPbk2NavigationBase::CDeletedContactInfo::HandleStoreEventL(
+        MVPbkContactStore& /*aContactStore*/,
+        TVPbkContactStoreEvent aStoreEvent )
+    {
+    /// Handle delete event but not if we already have the information
+    /// that the current contact was deleted.
+    if ( !DeletedAndRemoved() &&
+         (aStoreEvent.iEventType == TVPbkContactStoreEvent::EContactDeleted
+         || aStoreEvent.iEventType == TVPbkContactStoreEvent::EGroupDeleted))
+        {
+        // Save the deleted contact if it's the current contact.
+        MVPbkContactLink* curContact = 
+            iNavigationBase.NavigationLoader().ContactLinkLC();
+        if ( curContact && aStoreEvent.iContactLink && 
+             curContact->IsSame( *aStoreEvent.iContactLink ) )
+            {
+            delete iDeletedContact;
+            iDeletedContact = curContact;
+            CleanupStack::Pop(); // curContact
+            }
+        else
+            {
+            CleanupStack::PopAndDestroy(); // curContact
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CDeletedContactInfo::DeletedAndRemoved
+// --------------------------------------------------------------------------
+//                             
+TBool CPbk2NavigationBase::CDeletedContactInfo::DeletedAndRemoved() const
+    {
+    TBool res = EFalse;
+    if ( iDeletedContact && iRemovedContact && 
+         iRemovedContact->IsSame( *iDeletedContact ) )
+        {
+        res = ETrue;
+        }
+    return res;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2NavigationBase::CDeletedContactInfo::FocusedContactOrNullLC
+// --------------------------------------------------------------------------
+//                             
+MVPbkContactLink* 
+        CPbk2NavigationBase::CDeletedContactInfo::FocusedContactOrNullLC()
+    {
+    MVPbkContactLink* res = NULL;
+    MVPbkContactViewBase* view = iNavigationBase.ScrollView();
+    
+    if ( DeletedAndRemoved() && view )
+        {
+        TInt index = iRemovedContactIndex;
+        if ( index >= 0 )
+            {
+            const TInt lastIndex = view->ContactCountL() - 1;
+            if ( index > lastIndex )
+                {
+                index = lastIndex;
+                }
+            
+            // Returns a link to the contact that is in the same position
+            // as the removed one or in the last position.   
+            if ( index >= 0 )
+                {
+                res = view->CreateLinkLC( index );
+                }
+            }
+        }
+    
+    if ( !res )
+        {
+        // LC -semantics, push also NULL to cleanup stack
+        CleanupStack::PushL( res );
+        }
+        
+    return res;
+    }
+// End of File