filemanager/Engine/src/CfilemanageractiveDelete.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:31:07 +0100
branchRCL_3
changeset 39 65326cf895ed
parent 0 6a9f87576119
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2002-2008 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:  Deletes files
*
*/


// INCLUDE FILES
#include "Cfilemanageractivedelete.h"
#include "MFileManagerProcessObserver.h"
#include "CFileManagerEngine.h"
#include "CFileManagerCommonDefinitions.h"
#include "CFileManagerUtils.h"
#include "FileManagerDebug.h"
//#include <cmgxfilemanager.h>

// CONSTANTS
const TInt KFileManagerDeletionPerStep = 20;
const TInt64 KFileManagerMaxStepTime = 1000000; // 1s
const TInt KFileManagerNotificationArrayGranularity = 64;


// ============================ LOCAL FUNCTIONS ================================
// -----------------------------------------------------------------------------
// GetTimeStamp
// -----------------------------------------------------------------------------
//
static TInt64 GetTimeStamp()
    {
    TTime time;
    time.UniversalTime();
    return time.Int64();
    }

// -----------------------------------------------------------------------------
// IsTimedOut
// -----------------------------------------------------------------------------
//
static TBool IsTimedOut( const TInt64& aStartTime )
    {
    TInt64 time( GetTimeStamp() );
    TBool ret( time - aStartTime > KFileManagerMaxStepTime );
    if ( ret )
        {
        INFO_LOG("CFileManagerActiveDelete-TimedOut");
        }
    return ret;
    }


// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::CFileManagerActiveDelete
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CFileManagerActiveDelete::CFileManagerActiveDelete(
        RFs& aFs,
        CArrayFixFlat< TInt >& aIndexList,
        CFileManagerEngine& aEngine,
        CFileManagerUtils& aUtils ) :
    iFs( aFs ),
    iIndexList( aIndexList ),
    iError( KErrNone ),
    iEngine( aEngine ),
    iUtils( aUtils )
    {
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CFileManagerActiveDelete* CFileManagerActiveDelete::NewL(
        CArrayFixFlat< TInt >& aIndexList,
        CFileManagerEngine& aEngine,
        CFileManagerUtils& aUtils )
    {
    CFileManagerActiveDelete* self = new( ELeave ) CFileManagerActiveDelete(
        aEngine.Fs(), aIndexList, aEngine, aUtils );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::ConstructL
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerActiveDelete::ConstructL()
    {
    iStringBuffer = HBufC::NewL( KMaxFileName );
    //MG2 notification object
    //iMgxFileManager = &iEngine.MGXFileManagerL();
    iRemovedItems = new( ELeave ) CDesCArrayFlat(
        KFileManagerNotificationArrayGranularity );
    iIsRemoteDrive = iUtils.IsRemoteDrive( iEngine.CurrentDirectory() );
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::~CFileManagerActiveDelete
// Destructor
// -----------------------------------------------------------------------------
// 
EXPORT_C CFileManagerActiveDelete::~CFileManagerActiveDelete()
    {
    delete iStringBuffer;
    delete iFullPath;
    delete iDirScan;
    delete iDir;
    delete iRemovedItems;
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::IsProcessDone
// 
// -----------------------------------------------------------------------------
// 
TBool CFileManagerActiveDelete::IsProcessDone() const
    {
    return iProcessDone;
    }

// -----------------------------------------------------------------------------
// CFileManagerEngine::DeleteItemsInDirectoryL
// -----------------------------------------------------------------------------
//
TBool CFileManagerActiveDelete::DeleteItemsInDirectoryL()
    {
    if ( !iDirScan )
        {
        iDirScan = CDirScan::NewL( iFs );
        // Set scanning from current directory, take all files
        // No sorting needed
        iDirScan->SetScanDataL( *iFullPath,
            KEntryAttNormal | KEntryAttHidden | KEntryAttSystem,
            ESortNone );
        }

    if ( iDir && iFileIndex < iDir->Count() )
        {
        // Delete file item
        const TEntry& item = ( *iDir )[ iFileIndex ];
        TPtr ptr( iStringBuffer->Des() );
        CFileManagerUtils::GetFullPath(
            iDirScan->FullPath(), item, ptr );
        CFileManagerUtils::RemoveReadOnlyAttribute( iFs, ptr, item );
        DeleteFileL( ptr, ETrue );
        ++iFileIndex;
        }
    else
        {
        // Fetch next directory
        delete iDir;
        iDir = NULL;
        iDirScan->NextL( iDir );
        iFileIndex = 0;

        if ( iDir )
            {
            CFileManagerUtils::RemoveReadOnlyAttribute(
                iFs, iDirScan->FullPath() );
            }
        }

    if ( !iDir )
        {
        // Items are deleted now, report done
        if ( !iNotDeletedItems )
            {
            // Delete all directories
            CFileMan* fileMan = CFileMan::NewL( iFs );
            SetError( fileMan->RmDir( *iFullPath ), *iFullPath );
            delete fileMan;
            }
        return ETrue;
        }
    return EFalse; // Still items left
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::StepL
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerActiveDelete::StepL()
    {
    FUNC_LOG

    TInt64 startTime( GetTimeStamp() );
    TInt indexCount( iIndexList.Count() );
    TInt i( KFileManagerDeletionPerStep );
    TBool timedOut( EFalse );

    while ( iCurrentIndex < indexCount && i && !timedOut )
        {
        TBool isItemDone( EFalse );

        // Fetch item path if missing
        if ( !iFullPath )
            {
            iFullPath = iEngine.IndexToFullPathL(
                iIndexList.At( iCurrentIndex ) );
            if ( IsDir( *iFullPath ) )
                {
                // Ignore default folders
                if ( iUtils.DefaultFolder( *iFullPath ) )
                    {
                    SetError( KErrFmgrDefaultFolder, *iFullPath );
                    isItemDone = ETrue;
                    }
                }
            }
        // Delete item
        if ( !isItemDone )
            {
            if ( IsDir( *iFullPath ) )
                {
                // Delete directory item
                while ( iCurrentIndex < indexCount && i && !isItemDone && !timedOut )
                    {
                    isItemDone = DeleteItemsInDirectoryL();
                    --i;

                    // Adjust amount of deleted files per step by consumed time. 
                    // This is an attempt to avoid long periods of time, 
                    // where the UI does not respond to user activity.
                    timedOut = IsTimedOut( startTime );
                    }
                }
            else
                {
                // Delete file item
                DeleteFileL( *iFullPath );
                isItemDone = ETrue;
                --i;

                // Adjust amount of deleted files per step by consumed time. 
                // This is an attempt to avoid long periods of time, 
                // where the UI does not respond to user activity.
                timedOut = IsTimedOut( startTime );
                }
            }

        // Move to next item if done
        if ( isItemDone )
            {
            delete iFullPath;
            iFullPath = NULL;
            ++iCurrentIndex;
            }
        }

    if ( iCurrentIndex >= indexCount )
        {
        iProcessDone = ETrue;
        FlushNotifications();
        }
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::DialogDismissedL
//
// -----------------------------------------------------------------------------
//
void CFileManagerActiveDelete::DialogDismissedL( TInt aButtonId )
    {
    if ( aButtonId == EAknSoftkeyCancel )
        {
        FlushNotifications();
        }
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::GetError
// 
// -----------------------------------------------------------------------------
// 
EXPORT_C TInt CFileManagerActiveDelete::GetError( TDes& aFileName )
    {
    if( iFileName.Length() > 0)
        {
        aFileName.Zero();
        aFileName.Append( iFileName );
        }
    if ( iOpenFiles > 1 )
        {
        iError = KErrFmgrSeveralFilesInUse;
        }
    return iError;
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::DeletedDrmItems
// 
// -----------------------------------------------------------------------------
// 
EXPORT_C TInt CFileManagerActiveDelete::DeletedDrmItems(TInt& aTotalCount )
    {
    aTotalCount = iDeletedItems;
    return iDeletedDrmItems;
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::DeleteFileL
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerActiveDelete::DeleteFileL(
        const TDesC& aFullPath, const TBool aReadOnlyChecked )
    {
#ifndef RD_DRM_RIGHTS_MANAGER_REMOVAL
    TBool isLocalDataFile( EFalse );
    TBool isDrmProtected( EFalse );
    if ( !iIsRemoteDrive )
        {
        // Check DRM protection
        isDrmProtected = iUtils.IsDrmProtectedFile( aFullPath );
        if ( isDrmProtected )
            {
            isLocalDataFile = iUtils.IsDrmLocalDataFile( aFullPath );
            }
        }
#endif // RD_DRM_RIGHTS_MANAGER_REMOVAL

    TInt err( iFs.Delete( aFullPath ) );
    if ( err == KErrAccessDenied && !aReadOnlyChecked )
        {
        // Remove readonly and retry
        TEntry entry;
        if( iFs.Entry( aFullPath, entry ) == KErrNone )
            {
            CFileManagerUtils::RemoveReadOnlyAttribute(
                iFs, aFullPath, entry );
            err = iFs.Delete( aFullPath );
            }
        }
    if ( !IsError( err ) )
        {
        ++iDeletedItems;
        // Notification is relevant only for local drives
        if ( !iIsRemoteDrive )
            {
            TRAPD( err2, iRemovedItems->AppendL( aFullPath ) );
            if ( err2 != KErrNone )
                {
                ERROR_LOG1(
                    "CFileManagerActiveExecute::DeleteFileL-NotificationAppend-err=%d",
                    err2 )
                }
            }
#ifndef RD_DRM_RIGHTS_MANAGER_REMOVAL
        // Inform deletion of DRM protected files except local data files
        if( isDrmProtected && !isLocalDataFile )
            {
            ++iDeletedDrmItems;
            SetName( aFullPath );
            }
#endif // RD_DRM_RIGHTS_MANAGER_REMOVAL
        }
    else
        {
        // Delete failed, update error info
        SetError( err, aFullPath );
        if ( err == KErrInUse )
            {
            ++iOpenFiles;
            }
        ++iNotDeletedItems;
        }
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::IsDir
// 
// -----------------------------------------------------------------------------
// 
TBool CFileManagerActiveDelete::IsDir( const TDesC& aFullPath )
    {
    return CFileManagerUtils::HasFinalBackslash( aFullPath );
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::SetName
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerActiveDelete::SetName( const TDesC& aFullPath,
        TBool aOverWrite )
    {
    if ( !aOverWrite && iFileName.Length() )
        {
        return;
        }
    iFileName.Zero();
    if ( aFullPath.Length() )
        {
        if ( IsDir( aFullPath ) )
            {
            TParsePtrC parse( aFullPath.Left( aFullPath.Length() - 1 ) );
            iFileName.Append( parse.Name() );
            }
        else
            {
            TParsePtrC parse( aFullPath );
            iFileName.Append( parse.NameAndExt() );
            }
        }
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::IsError
// 
// -----------------------------------------------------------------------------
// 
TBool CFileManagerActiveDelete::IsError( TInt aErr )
    {
    return ( aErr != KErrNone &&
            aErr != KErrCorrupt &&
            aErr != KErrNotFound &&
            aErr != KErrPathNotFound );
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::SetError
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerActiveDelete::SetError( TInt aErr, const TDesC& aFullPath )
    {
    if ( iError == KErrNone && IsError( aErr ) )
        {
        iError = aErr;
        SetName( aFullPath, ETrue );
        }
    }

// -----------------------------------------------------------------------------
// CFileManagerActiveDelete::FlushNotifications
// -----------------------------------------------------------------------------
//
void CFileManagerActiveDelete::FlushNotifications()
    {
    if ( iRemovedItems->MdcaCount() > 0 )
        {
        //TRAP_IGNORE( iMgxFileManager->UpdateL( *iRemovedItems ) );
        iRemovedItems->Reset();
        }
    }

// End of file