mmappcomponents/collectionhelper/src/mpxdeletehelper.cpp
changeset 0 a2952bb97e68
child 17 6f9f6e99a23e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmappcomponents/collectionhelper/src/mpxdeletehelper.cpp	Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,818 @@
+/*
+* Copyright (c) 2006 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:  MPX delete helper
+*
+*/
+
+
+#include <e32base.h>
+#include <f32file.h>
+#include <mpxmedia.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxcollectioncommanddefs.h>
+#include <mpxcollectionpath.h>
+#include <mpxcollectionplaylist.h>
+#include <mpxplaybackutility.h>
+#include <mpxcollectionutility.h>
+#include <mpxharvesterutility.h>
+#include <mpxplaybackutility.h>
+#include <mpxlog.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxcollectionmessage.h>
+#include <mpxcollectionmessagedefs.h>
+#include <mpxsubscription.h>
+#include <mpxharvestercommon.h>
+
+#ifdef RD_MPX_TNM_INTEGRATION
+#include <hash.h>
+#include <eikenv.h>
+#include <f32file.h>
+#include <sysutil.h>
+#include <thumbnailmanager.h>
+#endif //RD_MPX_TNM_INTEGRATION
+// cenrep key need to be checked whether USB cable is connected in MTP/Combined Mode
+#include <UsbWatcherInternalPSKeys.h>
+#include <usbpersonalityids.h>
+#include <mpxcollectionuihelper.h>
+#include "mpxcollectionuihelperobserver.h"
+#include "mpxcollectionhelpercommon.h"
+
+#include "mpxdeletehelper.h"
+
+// Constants
+const TInt KSQLErrGeneral = -311; // SQL General error. Don't want to include sql header here
+const TInt KDeleteUpdateCount = 50;  // Max # of times to update delete status during a group delete. Value (1-100)
+#ifdef RD_MPX_TNM_INTEGRATION
+_LIT( KImageFileType, "image/jpeg" );
+#endif //RD_MPX_TNM_INTEGRATION
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXDeleteHelper::CMPXDeleteHelper(MMPXCollectionUtility& aCollectionUtility,
+                                   MMPXHarvesterUtility& aHarvesterUtility,
+                                   MMPXCHelperObserver& aObserver)
+:   CActive(CActive::EPriorityLow),
+    iCollectionUtil(aCollectionUtility),
+    iHarvester(aHarvesterUtility),
+    iObserver(aObserver),
+    iMoreToDo(ETrue),
+    iHadInUse(EFalse),
+    iState(EMPXIdle),
+    iDeletePercent(0),
+    iDeleteIncFactor(1),
+    iDeleteCount(0),
+    iUsbManConnected( EFalse )
+    {
+    CActiveScheduler::Add(this);
+    }
+
+// ---------------------------------------------------------------------------
+// 2nd Phase Constructor
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::ConstructL()
+    {
+    iFiles = new(ELeave)CDesCArrayFlat(4);
+    iMessageArray = CMPXMessageArray::NewL();
+    // Connect to usbman
+    ConnectUsbMan();
+
+#ifdef __USE_MESSAGE_SUBSCRIPTION
+    // Subscribe to only a few messages from collection utility
+    CMPXSubscription* subscription( CMPXSubscription::NewL() );
+    CleanupStack::PushL( subscription );
+    CMPXSubscriptionItem* subItem1( CMPXSubscriptionItem::NewL() );
+    CleanupStack::PushL( subItem1 );
+    subItem1->SetTObjectValueL( KMPXMessageGeneralId, KMPXMessageGeneral );
+    subItem1->SetTObjectValueL( KMPXMessageGeneralEvent, TMPXCollectionMessage::EBroadcastEvent );
+    subItem1->SetTObjectValueL( KMPXMessageGeneralType, EMcMsgFormatStart );
+    subscription->AddItemL( *subItem1 );
+    CMPXSubscriptionItem* subItem2( CMPXSubscriptionItem::CopyL( *subItem1 ));
+    CleanupStack::PushL( subItem2 );
+    subItem2->SetTObjectValueL( KMPXMessageGeneralType, EMcMsgDiskRemoved );
+    subscription->AddItemL( *subItem2 );
+    CMPXSubscriptionItem* subItem3( CMPXSubscriptionItem::CopyL( *subItem1 ));
+    CleanupStack::PushL( subItem3 );
+    subItem3->SetTObjectValueL( KMPXMessageGeneralType, EMcMsgUSBMassStorageStart );
+    subscription->AddItemL( *subItem3 );
+    CMPXSubscriptionItem* subItem4( CMPXSubscriptionItem::CopyL( *subItem1 ));
+    CleanupStack::PushL( subItem4 );
+    subItem4->SetTObjectValueL( KMPXMessageGeneralType, EMcMsgUSBMTPStart );
+    subscription->AddItemL( *subItem4 );
+    CMPXSubscriptionItem* subItem5( CMPXSubscriptionItem::CopyL( *subItem1 ));
+    CleanupStack::PushL( subItem5 );
+    iCollectionUtil.Collection().AddSubscriptionL( *subscription );
+    CleanupStack::PopAndDestroy( subItem5 );
+    CleanupStack::PopAndDestroy( subItem4 );
+    CleanupStack::PopAndDestroy( subItem3 );
+    CleanupStack::PopAndDestroy( subItem2 );
+    CleanupStack::PopAndDestroy( subItem1 );
+    CleanupStack::PopAndDestroy( subscription );
+#endif
+
+#ifdef RD_MPX_TNM_INTEGRATION
+
+    // Create Thumbnail Manager instance. This object is the observer.
+    iTNManager = CThumbnailManager::NewL( *this );
+#endif //RD_MPX_TNM_INTEGRATION
+    }
+
+
+// ---------------------------------------------------------------------------
+// Two-Phased Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXDeleteHelper* CMPXDeleteHelper::NewL(MMPXCollectionUtility& aCollectionUtility,
+                                         MMPXHarvesterUtility& aHarvesterUtility,
+                                         MMPXCHelperObserver& aObserver)
+    {
+    CMPXDeleteHelper* self =
+        new(ELeave)CMPXDeleteHelper( aCollectionUtility,
+                                     aHarvesterUtility,
+                                     aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMPXDeleteHelper::~CMPXDeleteHelper()
+    {
+    if( iPbUtil )
+        {
+        iPbUtil->Close();
+        }
+    delete iDeletePath;
+    delete iFiles;
+    delete iMessageArray;
+#ifdef RD_MPX_TNM_INTEGRATION
+
+    delete iTNManager;
+#endif //RD_MPX_TNM_INTEGRATION
+    if ( iUsbManConnected )
+        {
+        iUsbMan.Close();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Start the delete operation
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::DeleteL( CMPXCollectionPath& aPath )
+    {
+    MPX_DEBUG1("CMPXDeleteHelper::DeleteL()");
+    MPX_DEBUG_PATH(aPath);
+    TInt deletePercentFactor = 100 / KDeleteUpdateCount;
+
+    if( iPbUtil )
+        {
+        iPbUtil->Close();
+        iPbUtil = NULL;
+        }
+    iPbUtil = MMPXPlaybackUtility::UtilityL();
+
+    iDeletePath = CMPXCollectionPath::NewL( aPath );
+    iState = EMPXInitDelete;
+    iDeleteCount = 0;
+    iMessageArray->Reset();
+    RArray<TMPXItemId> selections;
+    CleanupClosePushL(selections);
+    iDeletePath->SelectionL(selections);
+    iItemsCount = selections.Count();
+    CleanupStack::PopAndDestroy(&selections);
+    iRetrievedItemsCount = 0;
+
+    // Calculate percent increment factor used during a delete.
+    if ( (iItemsCount > 0) && (iItemsCount < KDeleteUpdateCount) )
+        {
+        TReal factor = (KDeleteUpdateCount/iItemsCount) * deletePercentFactor;
+        iDeleteIncFactor = factor;
+        }
+    else
+        {
+        iDeleteIncFactor = deletePercentFactor;
+        }
+
+    TRequestStatus* status = &iStatus;
+    *status = KRequestPending;
+    User::RequestComplete(status, KErrNone);
+
+    SetActive();
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// to-do: this should be changed to HandleCollectionMessage
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::HandleCollectionMessage(CMPXMessage* aMessage, TInt /*aErr*/)
+    {
+    if( aMessage &&
+        aMessage->IsSupported(KMPXMessageGeneralEvent) &&
+        aMessage->IsSupported(KMPXMessageGeneralType) )
+        {
+        TInt event( aMessage->ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) );
+        TInt op( aMessage->ValueTObjectL<TInt>( KMPXMessageGeneralType ) );
+
+        MPX_DEBUG3( "CMPXDeleteHelper::HandleCollectionMessageL event = %d, type = %d",
+                    event, op );
+
+        if( event == TMPXCollectionMessage::EBroadcastEvent )
+            {
+            if( op == EMcMsgFormatStart ||
+                op == EMcMsgDiskRemoved ||
+                op == EMcMsgUSBMassStorageStart ||
+                op == EMcMsgUSBMTPStart )
+                {
+                iCancelled = ETrue;
+                Cancel();
+                }
+            }
+
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Start the delete operation
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::DoTaskStep()
+    {
+    MPX_DEBUG1("CMPXDeleteHelper::DoTaskStep()");
+
+    TRequestStatus* status = &iStatus;
+    *status = KRequestPending;
+
+    TRAPD( error, DoTaskStepL() );
+
+    User::RequestComplete( status, error );
+    }
+
+// ---------------------------------------------------------------------------
+// Start the delete operation
+// to-do: delete file first before removing it from the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::DoTaskStepL()
+    {
+    MPX_DEBUG1("CMPXDeleteHelper::DoTaskStepL()");
+
+    switch(iState)
+        {
+        case EMPXInitDelete:
+            {
+            StartDeleteL();  
+            iState = EMPXPreparation;
+            break;
+            }
+        case EMPXPreparation:
+            {
+            RetrieveFileListL();
+            iState = EMPXDelete;
+            break;
+            }
+
+        case EMPXDelete:
+            {
+            DeleteL();
+            break;
+            }
+
+        default:
+            break;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Handles request completion event
+// ----------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::RunL()
+    {
+    MPX_DEBUG3("CMPXDeleteHelper::RunL. [iMoreToDo %d] [iStatus %d]", iMoreToDo, iStatus.Int());
+
+    // cenrep key need to be checked whether USB cable is connected in MTP/Combined Mode
+    TUsbDeviceState deviceState = EUsbDeviceStateConfigured;
+    if ( !iUsbManConnected )
+        {
+        ConnectUsbMan();
+        }
+    
+    if ( iUsbManConnected )
+        {
+        if ( iUsbMan.GetDeviceState( deviceState ) != KErrNone )
+            {
+            deviceState = EUsbDeviceStateConfigured;
+            }
+        }
+    
+    if ( deviceState == EUsbDeviceStateAddress ||
+         deviceState == EUsbDeviceStateConfigured )
+        {
+        TInt usbStatus;
+        RProperty::Get(KPSUidUsbWatcher, KUsbWatcherSelectedPersonality, usbStatus);
+        if ((usbStatus == KUsbPersonalityIdMTP) || (usbStatus == KUsbPersonalityIdPCSuiteMTP))
+            {
+            MPX_DEBUG1("USB is active, Stop Delete");
+            CompleteDelete( KErrLocked );
+            return;
+            }
+        }
+    
+    if (iMoreToDo && iStatus.Int() == KErrNone)
+        {
+        DoTaskStep();
+        SetActive();
+        }
+    else
+        {
+        CompleteDelete(iStatus.Int());
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Cancel the delete operation
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::DoCancel()
+    {
+    MPX_DEBUG3("CMPXDeleteHelper::DoCancel iStatus %d, iState %d", iStatus.Int(), iState);
+
+    CompleteDelete(iStatus.Int());
+    }
+
+// ---------------------------------------------------------------------------
+// End state for a delete operation
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::CompleteDelete( TInt aErr )
+    {
+    MPX_DEBUG2("CMPXDeleteHelper::CompleteDelete %d", aErr);
+
+    TRAP_IGNORE( DoCompleteDeleteL( aErr ) );
+    }
+
+// ---------------------------------------------------------------------------
+// End state for a delete operation
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::DoCompleteDeleteL( TInt aErr )
+    {
+    MPX_DEBUG3("CMPXDeleteHelper::CompleteDeleteL error %d cancelled %d", aErr, iCancelled);
+    if( iState != EMPXIdle )
+        {
+        // Finally callback to observer and complete task queue event
+        // to-do: change HandleOperationCompletedL to HandleOperationComplete
+        TInt error = iHadInUse ? KErrInUse : aErr;
+        // Error cases that need to be ignored when mmc card is removed
+        if( error == KErrBadName ||
+            error == KErrNotReady ||
+            error == KErrAbort ||
+            error == KSQLErrGeneral ||
+            (iCancelled && error == KErrNotFound) )
+            {
+            error = KErrNone;
+            }
+
+        // Reset all states
+        Reset();
+
+        // Close Harvester database transaction
+        TRAP_IGNORE(iHarvester.CloseTransactionL() );
+        
+        // Send a complete delete command to finish off the delete operation
+        //
+        CMPXCommand* cmd = CMPXCommand::NewL();
+        CleanupStack::PushL( cmd );
+        cmd->SetTObjectValueL(KMPXCommandGeneralId,KMPXCommandIdCollectionCompleteDelete);
+        cmd->SetTObjectValueL(KMPXCommandGeneralDoSync, ETrue);
+        cmd->SetTObjectValueL(KMPXCommandCollectionDeleteCompactDb, ETrue);
+        cmd->SetCObjectValueL(KMPXCommandCollectionDeleteMsgArray, iMessageArray);
+        iCollectionUtil.Collection().CommandL(*cmd);
+        CleanupStack::PopAndDestroy( cmd );
+
+        TRAP_IGNORE(iObserver.HandleOperationCompleteL( EDeleteOp, error, NULL ) );
+
+        // Message array ownership passed to engine
+        delete iMessageArray;
+        iMessageArray = NULL;
+        iMessageArray = CMPXMessageArray::NewL();
+
+        if( iPbUtil )
+            {
+            iPbUtil->Close();
+            iPbUtil = NULL;
+            }
+        iCancelled = EFalse;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Resets members to get ready for the next client request
+//
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::Reset()
+    {
+    MPX_DEBUG1("CMPXDeleteHelper::Reset");
+    iMoreToDo = ETrue;
+    iHadInUse = EFalse;
+    iDeleteCount = 0;
+    iDeletePercent = 0;
+    iDeleteIncFactor = 1;
+
+    iState = EMPXIdle;
+
+    delete iDeletePath;
+    iDeletePath = NULL;
+
+    iFiles->Reset();
+    }
+
+// ---------------------------------------------------------------------------
+// Perfom cleanup of all unused data before delete
+//
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::StartDeleteL()
+    {
+    //
+    // set up the command to send to the collection
+    //
+    CMPXCommand* command = CMPXCommand::NewL();
+    CleanupStack::PushL(command);
+    
+    command->SetTObjectValueL<TMPXCommandId>(
+        TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralId), KMPXCommandIdCollectionPrepareDelete);
+    command->SetTObjectValueL<TBool>(
+        TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralDoSync), ETrue);
+    command->SetCObjectValueL(
+        TMPXAttribute(KMPXCommandIdCollectionPrepareDelete, EMPXCommandCollectionRetrievePath), 
+        iDeletePath);
+    
+    // send sync prepare delete URI command    
+    iCollectionUtil.Collection().CommandL(*command);
+    CleanupStack::PopAndDestroy(command);
+}
+    
+//
+// Retrieve files associated with the path
+//
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::RetrieveFileListL()
+    {
+    //
+    // set up the command to send to the collection
+    //
+    CMPXCommand* command = CMPXCommand::NewL();
+    CleanupStack::PushL(command);
+
+    command->SetTObjectValueL<TMPXCommandId>(
+        TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralId), KMPXCommandIdCollectionRetrieveUriForDeletion);
+    command->SetTObjectValueL<TBool>(
+        TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralDoSync), ETrue);
+    command->SetCObjectValueL(
+        TMPXAttribute(KMPXCommandIdCollectionRetrieveUriForDeletion, EMPXCommandCollectionRetrievePath),
+        iDeletePath);
+
+    // send sync retrieve URI command
+    iCollectionUtil.Collection().CommandL(*command);
+
+    //
+    // return command should contain error and URI array
+    //
+    if (!command->IsSupported(TMPXAttribute(KMPXCommandIdCollectionRetrieveUriForDeletion, EMPXCommandCollectionRetrieveUriError)) ||
+        !command->IsSupported(TMPXAttribute(KMPXCommandIdCollectionRetrieveUriForDeletion, EMPXCommandCollectionRetrieveMediaUriArray)))
+        {
+        User::Leave(KErrAbort);
+        }
+
+    //
+    // abandon operation if an error occured removing a media from the collection
+    //
+    TInt error =
+         command->ValueTObjectL<TInt>(
+            TMPXAttribute(KMPXCommandIdCollectionRetrieveUriForDeletion, EMPXCommandCollectionRetrieveUriError));
+    User::LeaveIfError(error);
+
+    //
+    // retrieve the list of files to be deleted
+    //
+    CDesCArray* files =
+        command->ValueNoNewLCObjectL<CDesCArray>(
+            TMPXAttribute(KMPXCommandIdCollectionRetrieveUriForDeletion, EMPXCommandCollectionRetrieveMediaUriArray));
+    CleanupStack::PushL(files);
+    ::CopyArrayL(*files, *iFiles);
+    iRetrievedItemsCount +=files->MdcaCount();
+    CleanupStack::PopAndDestroy(files);
+    //
+    // retrieve the updated path. If the original path ends at a particular artist,
+    // album, genre, or composer, the path will have been expended to include the
+    // songs under that category
+    //
+    delete iDeletePath;
+    iDeletePath = NULL;
+    iDeletePath =
+        command->ValueCObjectL<CMPXCollectionPath>(
+            TMPXAttribute(KMPXCommandIdCollectionRetrieveUriForDeletion, EMPXCommandCollectionRetrievePath));
+
+    CleanupStack::PopAndDestroy(command);
+    }
+
+// ---------------------------------------------------------------------------
+// Deletes the file from the file system then deletes it from the collection
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::DeleteL()
+    {
+    MPX_FUNC("CMPXDeleteHelper::DeleteL()");
+    // Close the item that we are about to delete
+    //
+    RArray<TMPXItemId> selections;
+    CleanupClosePushL(selections);
+    iDeletePath->SelectionL(selections);
+
+    TMPXItemId mediaId(0);
+    if (selections.Count())
+        {
+        // If more than one item
+        mediaId = selections[0];
+        }
+    else
+        {
+        mediaId = iDeletePath->Id(iDeletePath->Levels() - 1);
+        }
+
+    CleanupStack::PopAndDestroy(&selections);
+
+    // Send the real id to playback engine for deletion
+    iPbUtil->CommandL( EPbCmdCloseItem, mediaId );
+
+    //
+    // delete the media file from the file system and harvester's database first
+    // before deleting it from the collection
+    //
+    if (DeleteFileL())
+        {
+        //
+        // set up the command to send to the collection
+        //
+        CMPXCommand* command = CMPXMedia::NewL();
+        CleanupStack::PushL(command);
+
+        command->SetTObjectValueL<TMPXCommandId>(
+            TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralId), KMPXCommandIdCollectionRemove);
+        command->SetTObjectValueL<TBool>(
+            TMPXAttribute(KMPXCommandContentIdGeneral, EMPXCommandGeneralDoSync), ETrue);
+        command->SetCObjectValueL(
+            TMPXAttribute(KMPXCommandIdCollectionRemove,EMPXCommandCollectionRemovePath),
+            iDeletePath);
+        command->SetTObjectValueL<TInt>(
+            TMPXAttribute(KMPXCommandIdCollectionRemove, EMPXCommandCollectionRemoveMediaCount), 1);
+        command->SetTObjectValueL<TBool>(KMPXCommandCollectionRemoveSuppressMsgs,ETrue);
+        command->SetCObjectValueL<CMPXMessageArray>(KMPXCommandCollectionChangeMsgs, iMessageArray);
+        // send sync remove command
+        MPX_PERF_START( MPX_PERF_DELETE_COLLECTION );
+        iCollectionUtil.Collection().CommandL(*command);
+		MPX_PERF_END( MPX_PERF_DELETE_COLLECTION );
+
+        //
+        // return command should contain error, completed and media Id information
+        //
+        if (!command->IsSupported(TMPXAttribute(KMPXCommandIdCollectionRemove, EMPXCommandCollectionRemoveError)) ||
+            !command->IsSupported(TMPXAttribute(KMPXCommandIdCollectionRemove, EMPXCommandCollectionRemoveCompleted)))
+            {
+            User::Leave(KErrAbort);
+            }
+
+        //
+        // abandon operation if an error occured removing a media from the collection
+        //
+        TInt error =
+             command->ValueTObjectL<TInt>(
+                TMPXAttribute(KMPXCommandIdCollectionRemove, EMPXCommandCollectionRemoveError));
+        User::LeaveIfError(error);
+
+        //
+        // require to send async remove command again if command completed is EFalse
+        //
+        TBool completed =
+             command->ValueTObjectL<TBool>(
+                TMPXAttribute(KMPXCommandIdCollectionRemove, EMPXCommandCollectionRemoveCompleted));
+        iMoreToDo = !completed;
+
+        //
+        // retrieve the updated path with the removed media deselected and use this
+        // path for the next remove command
+        //
+        delete iDeletePath;
+        iDeletePath = NULL;
+        iDeletePath =
+            command->ValueCObjectL<CMPXCollectionPath>(
+                TMPXAttribute(KMPXCommandIdCollectionRemove, EMPXCommandCollectionRemovePath));
+
+        CleanupStack::PopAndDestroy(command);
+
+        if (iFiles->MdcaCount())
+            {
+            iFiles->Delete(0);
+            }
+
+        // Commit every 100 items deleted, message array ownership passed to engine
+        //
+        iDeleteCount++;
+        if( iDeleteCount%KBatchCommit == 0 )
+            {
+			// Commit Harvester DB
+            TRAP_IGNORE( iHarvester.CloseTransactionL() );
+
+            // Commit Collection DB
+            CMPXCommand* cmd = CMPXCommand::NewL();
+            CleanupStack::PushL( cmd );
+            cmd->SetTObjectValueL(KMPXCommandGeneralId,KMPXCommandIdCollectionCompleteDelete);
+            cmd->SetTObjectValueL(KMPXCommandGeneralDoSync, ETrue);
+            cmd->SetTObjectValueL(KMPXCommandCollectionDeleteCompactDb, ETrue);
+            cmd->SetCObjectValueL(KMPXCommandCollectionDeleteMsgArray, iMessageArray);
+            iCollectionUtil.Collection().CommandL(*cmd);
+
+            delete iMessageArray;
+            iMessageArray = NULL;
+            iMessageArray = CMPXMessageArray::NewL();
+            CleanupStack::PopAndDestroy( cmd );
+            }
+        }
+    //
+    // File not deleted from the file system, skip to the next
+    //
+    else
+        {
+        TArray<TInt> selectionIndices = iDeletePath->Selection();
+        if (selectionIndices.Count())
+            {
+            iDeletePath->Deselect(selectionIndices[0]);
+            }
+
+        iFiles->Delete(0);
+        }
+    
+    if (iFiles->MdcaCount() == 0)
+        {
+        if (iRetrievedItemsCount >= iItemsCount)
+            {
+            iMoreToDo = EFalse;    
+            iRetrievedItemsCount = 0;
+            }
+        else
+            {
+            iState = EMPXPreparation;
+            }
+        }
+    
+    // Send delete status when necessary.
+    TInt deleteThreshold = ((iDeletePercent+iDeleteIncFactor)*iItemsCount)/100;
+    if ( deleteThreshold > iItemsCount )
+        {
+        deleteThreshold = iItemsCount;
+        }
+    if ( iDeleteCount >= deleteThreshold )
+        {
+        iDeletePercent += iDeleteIncFactor;
+        if ( (iDeletePercent > 100) || (iDeleteCount == iItemsCount) )
+            {
+            iDeletePercent = 100;
+            }
+        CMPXMedia* media = CMPXMedia::NewL();
+        CleanupStack::PushL( media );
+        media->SetTObjectValueL( KMPXMediaGeneralCount, iDeletePercent );
+        iObserver.HandleOperationCompleteL( EDeleteStatusOp, KErrNone, media );
+        CleanupStack::Pop( media );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Deletes the file from the file system and harvester's database
+// ---------------------------------------------------------------------------
+//
+TBool CMPXDeleteHelper::DeleteFileL()
+    {
+    TBool deleted(ETrue);
+
+    if (iFiles->MdcaCount() > 0)
+        {
+        TPtrC uri = iFiles->MdcaPoint(0);
+
+        if( uri.Length() > 0 )
+            {
+            // For playlist files, it's possible that we are deleting the file which
+            // is not where the playlist is originated from. e.g. Playlist has been
+            // renamed to Playlist(01) in the collection, after deleting Playlist(01)
+            // from the collection, we are now attempting to delete Playlist(01).m3u
+            // which is not the originating file. This is a known risk.
+            CDesCArrayFlat* files = new (ELeave)CDesCArrayFlat(1);
+            CleanupStack::PushL(files);
+            files->AppendL(uri);
+
+			MPX_PERF_START( MPX_PERF_DELHELPER_HARVESTER_DELETE );
+            TRAPD(err, iHarvester.DeleteFilesL(*files, EFalse)); // to-do: create a sync DeleteFileL in harvester
+			MPX_PERF_END( MPX_PERF_DELHELPER_HARVESTER_DELETE );
+
+            // if the file cannot be found or is currently in use, skip to the next
+            // media removal, but inform the client at the end that one of the files
+            // is in use should that be the case
+            if (err == KErrInUse)
+                {
+                iHadInUse = ETrue;
+                deleted = EFalse;
+                }
+            else if ( err == KErrNotFound ||
+                      err == KErrPathNotFound )
+                {
+                // Cleanup harvester for broken links
+                // Have to trap ignore because .vir virtual playlists
+                // do not exist and we do not know the file is a playlist
+                // Since it is already KErrNotFound or KErrPathNotFound,
+                //
+                TRAP_IGNORE(iHarvester.RemoveFilesL(*files));
+                }
+            else
+                {
+                User::LeaveIfError(err);
+                }
+
+            CleanupStack::PopAndDestroy(files);  //lint !e961
+#ifdef RD_MPX_TNM_INTEGRATION
+            const TDesC& file = iFiles->MdcaPoint(0);
+            // remove from thumbnail manager
+            CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC(
+                    file, KImageFileType );
+            iTNManager->DeleteThumbnails( *source );
+            CleanupStack::PopAndDestroy( source );
+            // remove from local drive
+#endif //RD_MPX_TNM_INTEGRATION
+            }
+        }
+    return deleted;
+    }
+
+// ---------------------------------------------------------------------------
+// Stop deleting
+// ---------------------------------------------------------------------------
+//
+void CMPXDeleteHelper::Stop()
+    {
+    if ( iState != EMPXIdle )
+        {
+        iMoreToDo = EFalse;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Callback but not used here
+// ---------------------------------------------------------------------------
+void CMPXDeleteHelper::ThumbnailPreviewReady( 
+        MThumbnailData& /*aThumbnail*/, TThumbnailRequestId /*aId*/ )
+    {
+    }
+        
+
+// ---------------------------------------------------------------------------
+// Callback but not used here
+// ---------------------------------------------------------------------------
+void CMPXDeleteHelper::ThumbnailReady( TInt /*aError*/, 
+        MThumbnailData& /*aThumbnail*/, TThumbnailRequestId /*aId*/ )
+    {
+    }
+    
+// ---------------------------------------------------------------------------
+// CMPXDeleteHelper::ConnectUsbMan
+// ---------------------------------------------------------------------------
+void CMPXDeleteHelper::ConnectUsbMan()
+    {
+    MPX_FUNC("CMPXDeleteHelper::ConnectUsbMan()");
+    if ( iUsbMan.Connect() == KErrNone )
+        {
+        iUsbManConnected = ETrue;
+        }
+    }
+
+// END OF FILE