phonebookui/Phonebook2/CommandsExtension/src/CPbk2DeleteContactsCmd.cpp
changeset 0 e686773b3f54
child 3 04ab22b956c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/CommandsExtension/src/CPbk2DeleteContactsCmd.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,702 @@
+/*
+* 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 delete contacts command.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbk2DeleteContactsCmd.h"
+
+// Phonebook2
+#include <MPbk2CommandObserver.h>
+#include "MPbk2ProcessDecorator.h"
+#include "Pbk2ProcessDecoratorFactory.h"
+#include <Pbk2Commands.rsg>
+#include <Pbk2UIControls.rsg>
+#include <MPbk2ContactUiControl.h>
+#include <MPbk2ContactNameFormatter.h>
+#include <CPbk2GeneralConfirmationQuery.h>
+#include <MPbk2ContactLinkIterator.h>
+#include <CPbk2ApplicationServices.h>
+#include <MPbk2AppUi.h>
+
+// Virtual Phonebook
+#include <CVPbkContactManager.h>
+#include <MVPbkContactLink.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkContactOperationBase.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkContactStoreProperties.h>
+#include <CVPbkContactLinkArray.h>
+
+// System includes
+#include <AknQueryDialog.h>
+
+// Debugging headers
+#include <Pbk2Debug.h>
+
+
+/// Unnamed namespace for local definitions
+namespace {
+
+const TInt KOneContact = 1;
+
+// LOCAL DEBUG CODE
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicPreCond_ResetWhenDestroyed = 1,
+    ERunL_InvalidState,
+    EPanicLogic_DoDeleteContactsL,
+    EPanicPreCond_Null_Pointer
+    };
+
+void Panic(TPanicCode aReason)
+    {
+    _LIT(KPanicText, "CPbk2DeleteContactsCmd");
+    User::Panic(KPanicText,aReason);
+    }
+#endif // _DEBUG
+
+}
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::CPbk2DeleteContactsCmd
+// --------------------------------------------------------------------------
+//
+inline CPbk2DeleteContactsCmd::CPbk2DeleteContactsCmd(
+        MPbk2ContactUiControl& aUiControl ) :
+    CActive( EPriorityIdle ),
+    iUiControl( &aUiControl )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2DeleteContactsCmd::CPbk2DeleteContactsCmd(0x%x)"), this);
+
+    CActiveScheduler::Add( this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::~CPbk2DeleteContactsCmd
+// --------------------------------------------------------------------------
+//
+CPbk2DeleteContactsCmd::~CPbk2DeleteContactsCmd()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2DeleteContactsCmd::~CPbk2DeleteContactsCmd(0x%x)"), this);
+
+    Cancel();
+    if (iUiControl)
+        {
+        iUiControl->RegisterCommand(NULL);
+        }
+    delete iDecorator;
+    delete iContactIterator;
+    delete iContactsToDelete;
+
+    delete iRetrieveOperation;
+    delete iDeleteOperation;
+    delete iListContactsOperation;
+    delete iStoreContact;
+    Release( iAppServices );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::ConstructL
+// --------------------------------------------------------------------------
+//
+inline void CPbk2DeleteContactsCmd::ConstructL()
+    {
+    iAppServices = CPbk2ApplicationServices::InstanceL();
+
+    // register command to ui control
+    iUiControl->RegisterCommand(this);
+
+    // Returns NULL if there are no selected contacts.
+    // In that case we will delete the focused contact.
+    iContactIterator = iUiControl->SelectedContactsIteratorL();
+
+    iContactCount = GetContactCountL();
+
+    if( iContactCount > 1 )
+    	{
+    	//we are deleting multiple contacts
+        iDecorator = Pbk2ProcessDecoratorFactory::CreateProgressDialogDecoratorL
+            ( R_QTN_PHOB_NOTE_CLEARING_PB_WITH_CANCEL, EFalse );
+
+        iDecorator->SetObserver(*this);
+    	}
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::NewL
+// --------------------------------------------------------------------------
+//
+CPbk2DeleteContactsCmd* CPbk2DeleteContactsCmd::NewL(
+        MPbk2ContactUiControl& aUiControl )
+    {
+    CPbk2DeleteContactsCmd* self = new(ELeave) CPbk2DeleteContactsCmd(
+            aUiControl );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::ExecuteLD
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::ExecuteLD()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2DeleteContactsCmd::ExecuteLD(0x%x)"), this);
+
+    CleanupStack::PushL(this);
+
+    if ( iContactCount > KOneContact )
+        {
+        // Move straight to confirm phase
+        iState = EConfirming;
+        IssueRequest();
+        }
+    else if ( iContactCount == KOneContact )
+        {
+        // There was only one contact, we have to retrieve it to get
+        // its name
+        iState = ERetrieving;
+        IssueRequest();
+        }
+    else 
+        {
+        // If iContactCount == 0 we should end this command properly.
+        // This happens when contact to be deleted is from read-only store.
+        ProcessDismissed( KErrNone );
+        }        
+
+    CleanupStack::Pop( this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::AddObserver
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::AddObserver(
+        MPbk2CommandObserver& aObserver )
+    {
+    iCommandObserver = &aObserver;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::ResetUiControl
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::ResetUiControl(
+        MPbk2ContactUiControl& aUiControl)
+    {
+    if (iUiControl == &aUiControl)
+        {
+        iUiControl = NULL;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::DoCancel
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::DoCancel()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::RunL
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::RunL()
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2DeleteContactsCmd::RunL() start"), this);
+
+   switch ( iState )
+        {
+        case ERetrieving:
+            {
+            // Retrieve phase is executed only when there is one contact
+            // to delete. Check is the contact marked one or focused one.            
+            if ( iContactIterator )
+                {
+                iContactIterator->SetToFirst();
+                if ( iContactIterator->HasNext() )
+                    {
+                    MVPbkContactLink* link = iContactIterator->NextL();
+                    CleanupDeletePushL( link );
+                    if ( link )
+                        {
+                        RetrieveContactL( *link );
+                        }                    
+                    CleanupStack::PopAndDestroy(); // link
+                    }                   
+                }
+            else
+                {
+                if (iUiControl)
+                    {
+                    const MVPbkBaseContact* focusedContact =
+                            iUiControl->FocusedContactL();
+                    if ( focusedContact )
+                        {
+                        MVPbkContactLink* link = focusedContact->CreateLinkLC();
+                        RetrieveContactL( *link );
+                        CleanupStack::PopAndDestroy(); // link
+                        }
+                    }
+                else
+                    {
+                    // nothing to delete
+                    IssueStopRequest( EStopping );
+                    }
+                }            
+            break;
+            }
+        case EConfirming:
+            {
+            ConfirmDeletionL();
+            break;
+            }
+        case EStarting:
+            {
+            if( iDecorator )
+            	{
+                iDecorator->ProcessStartedL( iContactCount );
+            	}
+            
+            if ( iContactIterator )
+                {
+                iContactIterator->SetToLast();
+                }
+            DoDeleteContactsL();
+            break;
+            }
+        case EDeleting:
+            {
+            // Do nothing
+            break;
+            }
+        case EStopping:
+            {
+            // Decorator calls ProcessDismissed
+            if( iDecorator )
+            	{
+                iDecorator->ProcessStopped();            	
+            	}
+            else
+            	{
+                ProcessDismissed( KErrNone );
+            	}
+            break;
+            }
+        case ECanceling:
+            {
+            ProcessDismissed( KErrCancel );
+            break;
+            }
+        default:
+            {
+            __ASSERT_DEBUG(EFalse, Panic(ERunL_InvalidState));
+            break;
+            }
+        }
+
+    PBK2_DEBUG_PRINT
+        (PBK2_DEBUG_STRING("CPbk2DeleteContactsCmd::RunL end"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::RunError
+// --------------------------------------------------------------------------
+//
+TInt CPbk2DeleteContactsCmd::RunError( 
+        TInt aError )
+    {
+    return FilterErrors( aError );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::VPbkSingleContactOperationComplete
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::VPbkSingleContactOperationComplete(
+        MVPbkContactOperationBase& aOperation,
+        MVPbkStoreContact* aContact )
+    {
+    if ( &aOperation == iRetrieveOperation )
+        {
+        delete iRetrieveOperation;
+        iRetrieveOperation = NULL;
+
+        // We now have a store contact and we can issue a confirmation
+        iStoreContact = aContact;
+        iState = EConfirming;
+        IssueRequest();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::VPbkSingleContactOperationFailed
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::VPbkSingleContactOperationFailed(
+        MVPbkContactOperationBase& aOperation,
+        TInt aError )
+    {
+    if ( &aOperation == iRetrieveOperation )
+        {
+        delete iRetrieveOperation;
+        iRetrieveOperation = NULL;
+
+        // We cannot get the contact, so we have to
+        // fail. We cannot continue, since this operation
+        // was executed only in case of one contact.
+        ProcessDismissed( aError );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::StepComplete
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::StepComplete(
+        MVPbkContactOperationBase& aOperation,
+        TInt aStepSize )
+    {
+    if ( &aOperation == iDeleteOperation )
+        {
+        // Indicate process advancement to the decorator
+        if( iDecorator )
+        	{
+            iDecorator->ProcessAdvance( aStepSize );
+        	}
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::StepFailed
+// --------------------------------------------------------------------------
+//
+TBool CPbk2DeleteContactsCmd::StepFailed(
+        MVPbkContactOperationBase& aOperation,
+        TInt /*aStepSize*/,
+        TInt aError )
+    {
+    TBool result = ETrue;
+
+    if ( &aOperation == iDeleteOperation )
+        {
+        // Check whether the error is a serious one
+        TInt err = FilterErrors( aError );
+        if ( err != KErrNone )
+            {
+            Cancel();
+            result = EFalse;
+            }
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::OperationComplete
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::OperationComplete(
+        MVPbkContactOperationBase& aOperation )
+    {
+    if ( &aOperation == iDeleteOperation )
+        {
+        delete iDeleteOperation;
+        iDeleteOperation = NULL;
+
+        if ( iContactIterator && iContactIterator->HasPrevious() )
+            {
+            TRAPD( error, DoDeleteContactsL() );
+            if ( error != KErrNone )
+                {
+                FilterErrors( error );
+                IssueStopRequest( EStopping );
+                }
+            }
+        else
+            {
+            IssueStopRequest( EStopping );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::ProcessDismissed
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::ProcessDismissed( TInt aCancelCode )
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2DeleteContactsCmd::ProcessDismissed()"));
+
+    __ASSERT_DEBUG(iCommandObserver, Panic(EPanicPreCond_Null_Pointer));
+
+    Cancel();
+    delete iDeleteOperation;
+    iDeleteOperation = NULL;
+
+    if ( aCancelCode != KErrCancel && iUiControl)
+        {
+        // Don't remove list markings if user canceled
+        iUiControl->SetBlank(EFalse);
+        iUiControl->UpdateAfterCommandExecution();
+        }
+
+    // Notify command owner that the command has finished
+    iCommandObserver->CommandFinished( *this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::RetrieveContactL
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::RetrieveContactL(
+        const MVPbkContactLink& aContactLink )
+    {
+    // Retrieve the actual store contact from the given link
+    iRetrieveOperation = iAppServices->
+        ContactManager().RetrieveContactL( aContactLink, *this );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::DoDeleteContactsL
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::DoDeleteContactsL()
+    {
+    delete iContactsToDelete;
+    iContactsToDelete = NULL;
+    iContactsToDelete = CVPbkContactLinkArray::NewL();
+    const TInt KDeleteBlockSize = 200;
+
+    if ( iContactIterator )
+        {
+        for ( TInt i = 0; i < KDeleteBlockSize &&
+                iContactIterator->HasPrevious(); ++i )
+            {
+            MVPbkContactLink* link = iContactIterator->PreviousL();
+            CleanupDeletePushL( link );
+            iContactsToDelete->AppendL( link ); // takes ownership
+            CleanupStack::Pop(); // link
+            }
+        }
+    else
+        {
+        __ASSERT_DEBUG( iStoreContact,
+            Panic( EPanicLogic_DoDeleteContactsL ) );
+
+        MVPbkContactLink* link = iStoreContact->CreateLinkLC();
+        iContactsToDelete->AppendL( link ); // takes ownership
+        CleanupStack::Pop(); // link
+        }
+
+    iDeleteOperation = iAppServices->
+        ContactManager().DeleteContactsL( *iContactsToDelete, *this );
+
+    if (iUiControl)
+        {
+        // Blank UI control to avoid flicker
+        iUiControl->SetBlank( ETrue );
+        }
+
+    iState = EDeleting;
+    IssueRequest();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::FilterErrors
+// --------------------------------------------------------------------------
+//
+inline TInt CPbk2DeleteContactsCmd::FilterErrors( TInt aErrorCode )
+	{
+	PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING
+        ( "CPbk2DeleteContactsCmd::FilterErrors(%d) start" ), aErrorCode );
+
+	TInt result = aErrorCode;
+	switch ( aErrorCode )
+		{
+		case KErrNotFound:  // FALLTHROUGH
+		case KErrInUse:
+			{
+			// If you only have one contact or it's the last contact that failed, 
+			// remove the progress bar. 
+			if ( iContactCount == KOneContact || 
+				( ( iContactIterator ) && !( iContactIterator->HasNext() ) ) ) 
+				{ 
+				Cancel(); 
+				if ( iDecorator )
+					{
+					iDecorator->ProcessStopped();
+				 	}
+				ProcessDismissed( aErrorCode );
+				} 
+			else 
+				{ 
+				// Ignore these errors 
+				// KErrNotFound means that somebody got the contact first  
+				// KErrInUse means that the contact is open
+				result = KErrNone;   
+				}
+			CCoeEnv::Static()->HandleError( aErrorCode ); 
+			
+			break; 
+			}
+
+		default:  // Something more serious happened -> give up
+			{
+			Cancel();
+			ProcessDismissed( aErrorCode );
+			
+			break;
+			}
+		}
+	
+	PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING
+		( "CPbk2DeleteContactsCmd::FilterErrors(%d) end" ), result );
+	
+	return result;
+	}
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::IssueRequest
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::IssueRequest()
+    {
+    TRequestStatus* status = &iStatus;
+    User::RequestComplete( status, KErrNone );
+    SetActive();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::IssueStopRequest
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::IssueStopRequest( TProcessState aState )
+    {
+    iState = aState;
+    if ( !IsActive() )
+        {
+        IssueRequest();
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::ConfirmDeletionL
+// --------------------------------------------------------------------------
+//
+void CPbk2DeleteContactsCmd::ConfirmDeletionL()
+    {
+    CPbk2GeneralConfirmationQuery* query =
+            CPbk2GeneralConfirmationQuery::NewL();
+    TInt queryResult = KErrNotFound;
+    if (iContactCount > 1)
+        {
+        queryResult = query->ExecuteLD(
+            iContactCount, R_QTN_PHOB_QUERY_DELETE_N_ENTRIES );
+        }
+    else
+        {
+        queryResult = query->ExecuteLD(
+                    *iStoreContact, R_QTN_QUERY_COMMON_CONF_DELETE, MPbk2ContactNameFormatter::EPreserveAllOriginalSpaces );
+            
+        }
+
+    if (queryResult)
+        {
+        // Continue with starting the deletion
+        iState = EStarting;
+        IssueRequest();
+        }
+    else
+        {
+        IssueStopRequest(ECanceling);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::GetContactCountL
+// --------------------------------------------------------------------------
+//
+TInt CPbk2DeleteContactsCmd::GetContactCountL()
+    {
+    TInt result = 0;
+
+    if ( iContactIterator )
+        {
+        iContactIterator->SetToFirst();
+        while( iContactIterator->HasNext() )
+            {
+            MVPbkContactLink* link = iContactIterator->NextL();
+            if ( link && !IsFromReadOnlyStore( *link ) )
+                {
+                ++result;
+                }
+            delete link;
+            link = NULL;
+            }
+        }
+    else
+        {
+        if (iUiControl)
+            {            
+            // There was no iterator so there are no selected contacts,
+            // this means we are deleting only the focused contact
+            const MVPbkBaseContact* focusedContact = iUiControl->FocusedContactL();
+            if ( focusedContact )
+                {
+                MVPbkContactLink* link = focusedContact->CreateLinkLC();
+                if ( link && !IsFromReadOnlyStore( *link ) )
+                    {
+                    ++result;
+                    }
+                CleanupStack::PopAndDestroy(); // link
+                }
+            }
+        }
+
+    return result;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DeleteContactsCmd::IsFromReadOnlyStore
+// --------------------------------------------------------------------------
+//
+TBool CPbk2DeleteContactsCmd::IsFromReadOnlyStore
+        ( const MVPbkContactLink& aContactLink ) const
+    {
+    TBool ret = EFalse;
+
+    const MVPbkContactStore& store = aContactLink.ContactStore();
+    if ( store.StoreProperties().ReadOnly() )
+        {
+        ret = ETrue;
+        }
+
+    return ret;
+    }
+
+//  End of File