--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkCntModel/src/CDeleteContactsOperation.cpp Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,420 @@
+/*
+* Copyright (c) 2002-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: An operation object to delete contacts from contacts database
+*
+*/
+
+
+#include "CDeleteContactsOperation.h"
+
+// VPbkCntModel
+#include "CContactLink.h"
+#include "CContactStore.h"
+#include "CVPbkDiskSpaceCheck.h"
+#include "CContact.h"
+
+// Virtual Phonebook engine
+#include <MVPbkBatchOperationObserver.h>
+#include <MVPbkContactStoreInfo.h>
+
+// Contact Model
+#include <cntdef.h>
+#include <cntdb.h>
+#include <cntitem.h>
+
+
+namespace VPbkCntModel {
+
+// Definition for delete array size
+const TInt KDeleteArraySize = 3;
+
+// Definition for FreeDiskSpaceRequest towards DOSSERVER
+const TInt KFreeSpaceRequiredInKB = 140 * 1024; // 140 kB
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::CDeleteContactsOperation
+// -----------------------------------------------------------------------------
+//
+CDeleteContactsOperation::CDeleteContactsOperation(
+ CContactStore& aContactStore,
+ MVPbkBatchOperationObserver& aObserver,
+ RSharedDataClient* aSharedDataClient,
+ VPbkEngUtils::CVPbkDiskSpaceCheck& aDiskSpaceChecker ) :
+ CActive( CActive::EPriorityIdle ),
+ iContactStore( aContactStore ),
+ iObserver( aObserver ),
+ iState( EDelete ),
+ iSharedDataClient( aSharedDataClient ),
+ iDiskSpaceChecker( aDiskSpaceChecker )
+ {
+ CActiveScheduler::Add(this);
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::~CDeleteContactsOperation
+// -----------------------------------------------------------------------------
+//
+CDeleteContactsOperation::~CDeleteContactsOperation()
+ {
+ Cancel();
+ delete iRemainingContactIds;
+ delete iCurrentContactIds;
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::NewL
+// -----------------------------------------------------------------------------
+//
+CDeleteContactsOperation* CDeleteContactsOperation::NewL(
+ CContactStore& aContactStore,
+ const MVPbkContactLinkArray& aLinks,
+ MVPbkBatchOperationObserver& aObserver,
+ RSharedDataClient* aSharedDataClient,
+ VPbkEngUtils::CVPbkDiskSpaceCheck& aDiskSpaceChecker )
+ {
+ CDeleteContactsOperation* self =
+ new( ELeave ) CDeleteContactsOperation( aContactStore, aObserver,
+ aSharedDataClient, aDiskSpaceChecker );
+ CleanupStack::PushL( self );
+ self->ConstructL( aLinks );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::ConstructL
+// -----------------------------------------------------------------------------
+//
+inline void CDeleteContactsOperation::ConstructL
+ (const MVPbkContactLinkArray& aLinks)
+ {
+ iRemainingContactIds = CContactIdArray::NewL();
+ iCurrentContactIds = CContactIdArray::NewL();
+
+ iGroupCount = iContactStore.StoreInfo().NumberOfGroupsL();
+
+ const TInt count = aLinks.Count();
+ for ( TInt i=0 ; i < count; ++i )
+ {
+ const CContactLink& link =
+ static_cast<const CContactLink&>( aLinks.At( i ) );
+ iRemainingContactIds->AddL( link.ContactId() );
+ }
+ PrepareNextDelete();
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::DoCancel()
+ {
+ // Do nothing
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::RunL
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::RunL()
+ {
+ switch ( iState )
+ {
+ case EDelete:
+ {
+ RunDeleteL();
+ IssueRequest();
+ break;
+ }
+ case EComplete:
+ {
+ iObserver.OperationComplete( *this );
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CDeleteContactsOperation::RunError(TInt aError)
+ {
+ if ( iFreeDiskSpaceRequired )
+ {
+ // Notify shared data that we do not need free space anymore
+ DoCancelFreeDiskSpaceRequest();
+ iFreeDiskSpaceRequired = EFalse;
+ }
+
+ // if iCurrentContactIndex is valid, than it's delete error
+ // otherwise, RunDeleteL leaved outside the delete loop
+ TBool deleteError = iCurrentContactIndex >= 0 &&
+ iCurrentContactIndex < iCurrentContactIds->Count();
+
+ // if error outside the delete loop, than skip all current contacts,
+ // otherwise, remove failed contact and try again
+ TInt stepSize = iCurrentContactIds->Count();
+ if ( deleteError )
+ {
+ stepSize = 1;
+ }
+
+ if ( iObserver.StepFailed( *this, stepSize, aError ) )
+ {
+ if ( iCurrentContactIds->Count() > 1 && deleteError )
+ {
+ //remove failed contact and try without it again
+ iCurrentContactIds->Remove( iCurrentContactIndex );
+ iState = EDelete;
+ }
+ else
+ {
+ //skip iCurrentContactIds, try remaining
+ PrepareNextDelete();
+ }
+ IssueRequest();
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::StartL
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::StartL()
+ {
+ IssueRequest();
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::Cancel
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::Cancel()
+ {
+ CActive::Cancel();
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::IssueRequest
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::IssueRequest()
+ {
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+ SetActive();
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::UpdateTimeStampOfAllContactsInGroupL
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::UpdateTimeStampOfAllContactsInGroupL()
+ {
+ CContactItem* groupItem = iContactStore.NativeDatabase().
+ ReadContactLC( ( *iCurrentContactIds )[iCurrentContactIndex] );
+
+ CContact* group = CContact::NewL( iContactStore, groupItem );
+ CleanupStack::Pop(groupItem);
+ CleanupStack::PushL( group );
+
+ group->UpdateTimeStampOfAllContactsInGroupL();
+
+ CleanupStack::PopAndDestroy( group );
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::CurrentItemIsGroupL
+// -----------------------------------------------------------------------------
+//
+TBool CDeleteContactsOperation::CurrentItemIsGroupL()
+ {
+ TBool isGroup = EFalse;
+
+ // If groups exists, we need to read a minimal contact to get it's type
+ if (iGroupCount > 0)
+ {
+ CContactItem* item = iContactStore.NativeDatabase().
+ ReadMinimalContactLC( ( *iCurrentContactIds )[iCurrentContactIndex] );
+
+ if (item->Type() == KUidContactGroup)
+ {
+ isGroup = ETrue;
+ }
+
+ CleanupStack::PopAndDestroy(item);
+ }
+
+ return isGroup;
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::RunDeleteL
+// -----------------------------------------------------------------------------
+//
+inline void CDeleteContactsOperation::RunDeleteL()
+ {
+ StartTransactionLC();
+
+ TInt stepSize = iCurrentContactIds->Count();
+ for ( iCurrentContactIndex = 0;
+ iCurrentContactIndex < stepSize;
+ ++iCurrentContactIndex )
+ {
+ DoRequestFreeDiskSpaceLC();
+
+ // If contact item is a group, we need to update the timestamps
+ // of the contacts in the group before deleting the group.
+ // This is needed for sync services.
+ if ( CurrentItemIsGroupL() )
+ {
+ UpdateTimeStampOfAllContactsInGroupL();
+ }
+
+ // Cannot use DeleteContactsL here, since it does not
+ // send contact removed events
+ iContactStore.NativeDatabase().
+ DeleteContactL( ( *iCurrentContactIds )[iCurrentContactIndex] );
+
+ CleanupStack::PopAndDestroy(); // RequestFreeDiskSpaceLC
+
+ RunCompressL(EFalse);
+ }
+
+ // Commit database transaction
+ CommitTransactionLP();
+
+ iObserver.StepComplete( *this, stepSize );
+ RunCompressL(ETrue);
+ PrepareNextDelete();
+ }
+
+void CDeleteContactsOperation::PrepareNextDelete()
+ {
+ iCurrentContactIds->Reset();
+ for ( TInt i = Min(iRemainingContactIds->Count(), KDeleteArraySize) - 1;
+ i >= 0;
+ --i )
+ {
+ iCurrentContactIds->AddL( ( *iRemainingContactIds )[i] );
+ iRemainingContactIds->Remove( i );
+ }
+
+ iState = EDelete;
+ iCurrentContactIndex = -1; //make index invalid, it's checked in RunError
+ //to detect StartTransactionLC leave
+ if ( iCurrentContactIds->Count() == 0 )
+ {
+ // No more contacts to delete
+ iState = EComplete;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::RunCompressL
+// -----------------------------------------------------------------------------
+//
+inline void CDeleteContactsOperation::RunCompressL(TBool aForce)
+ {
+ if ( aForce || iContactStore.NativeDatabase().CompressRequired() )
+ {
+ DoRequestFreeDiskSpaceLC();
+ // Compress database
+ iContactStore.NativeDatabase().CompactL();
+ CleanupStack::PopAndDestroy(); // RequestFreeDiskSpaceLC
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::StartTransactionLC
+// -----------------------------------------------------------------------------
+//
+inline void CDeleteContactsOperation::StartTransactionLC()
+ {
+ // If database transaction starting leaves -->
+ // Reserved disk space if freed in CDeleteContactsOperation::RunError
+ DoRequestFreeDiskSpace();
+ iFreeDiskSpaceRequired = ETrue;
+
+ iContactStore.NativeDatabase().DatabaseBeginLC( EFalse );
+
+ DoCancelFreeDiskSpaceRequest();
+ iFreeDiskSpaceRequired = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::CommitTransactionLC
+// -----------------------------------------------------------------------------
+//
+inline void CDeleteContactsOperation::CommitTransactionLP()
+ {
+ // If database commit leaves --> Reserved disk space if freeed in
+ // CDeleteContactsOperation::RunError
+ DoRequestFreeDiskSpace();
+ iFreeDiskSpaceRequired = ETrue;
+
+ iContactStore.NativeDatabase().DatabaseCommitLP( EFalse );
+
+ DoCancelFreeDiskSpaceRequest();
+ iFreeDiskSpaceRequired = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::DoRequestFreeDiskSpace
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::DoRequestFreeDiskSpace()
+ {
+ if ( iSharedDataClient )
+ {
+ iSharedDataClient->RequestFreeDiskSpace(KFreeSpaceRequiredInKB);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::DoRequestFreeDiskSpaceLC
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::DoRequestFreeDiskSpaceLC()
+ {
+ if ( iSharedDataClient )
+ {
+ iSharedDataClient->RequestFreeDiskSpaceLC(KFreeSpaceRequiredInKB);
+ }
+ else
+ {
+ // place token in cleanup stack
+ TAny* const nop = NULL;
+ CleanupStack::PushL(nop);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDeleteContactsOperation::CancelFreeDiskSpaceRequest
+// -----------------------------------------------------------------------------
+//
+void CDeleteContactsOperation::DoCancelFreeDiskSpaceRequest()
+ {
+ if ( iSharedDataClient )
+ {
+ iSharedDataClient->CancelFreeDiskSpaceRequest();
+ }
+ }
+
+} // namespace VPbkCntModel
+
+// End of File