filemanager/src/filemanager/src/operationservice/fmoperationmove.cpp
author hgs
Fri, 25 Jun 2010 17:08:34 +0800
changeset 25 b7bfdea70ca2
parent 16 ada7962b4308
permissions -rw-r--r--
201025

/*
* Copyright (c) 2009 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: 
*
*/

#include "fmoperationmove.h"
#include "fmcommon.h"
#include "fmoperationbase.h"
#include "fmdrivedetailstype.h"
#include "fmutils.h"

#include <QDir>
#include <QFileInfo>
#include <QStringList>
#include <QStack>

FmOperationMove::FmOperationMove( QObject *parent, QStringList sourceList, QString targetPath  ) :
        FmOperationBase( parent, FmOperationService::EOperationTypeMove ),
        mSourceList( sourceList ), mTargetPath( targetPath ),
        mStop( 0 ), mTotalSize( 0 ), mErrString( 0 ), mMovedSize( 0 ), mTotalSteps( 100 ), mCurrentStep( 0 )
{
}

FmOperationMove::~FmOperationMove()
{
}

QStringList FmOperationMove::sourceList()
{
    return mSourceList;
}
QString     FmOperationMove::targetPath()
{
    return mTargetPath;
}

int FmOperationMove::start(  volatile bool *isStopped, QString *errString )
{
    mStop = isStopped;
    mErrString = errString;

    mTotalSize   = 0;
    mMovedSize  = 0;
    mCurrentStep = 0;

    
    if( mSourceList.empty() ) {
        return FmErrWrongParam;
    }

    emit notifyPreparing( true );

    int numofFolders = 0;
    int numofFiles      = 0;

    int ret = FmFolderDetails::queryDetailOfContentList( mSourceList, numofFolders, 
        numofFiles, mTotalSize, mStop, true );
    if( ret != FmErrNone ) {
        return ret;
    }

    emit notifyStart( true, mTotalSteps );
    foreach( const QString& source, mSourceList ) {
        QFileInfo fi( source );
        if( !fi.exists() ) {
            *mErrString = source;
            ret = FmErrSrcPathDoNotExist;
            return ret;
        }
        QString newName;
        bool isAcceptReplace = false;
        QFileInfo destFi( mTargetPath + fi.fileName() );
        // while for duplicated file/dir
        while( destFi.exists() ) {
            if( destFi.isFile() && destFi.absoluteFilePath().compare( fi.absoluteFilePath(), Qt::CaseInsensitive ) != 0  ) {
                emit askForReplace( destFi.absoluteFilePath(), fi.absoluteFilePath(), &isAcceptReplace );
                if( isAcceptReplace ) {
                    //delete src file
                    if( !QFile::remove( destFi.absoluteFilePath() ) ) {
                        *mErrString = destFi.absoluteFilePath();
                        ret = FmErrCannotRemove;
                        break;
                    }
                    destFi.setFile( destFi.absoluteFilePath() );
                } else {
                    queryForRename( destFi.absoluteFilePath(), &newName );
                    if( newName.isEmpty() ) {
                        ret = FmErrCancel;
                        break;
                    }
                    QString targetName = mTargetPath + newName;
                    destFi.setFile( targetName );
                }
            } else{
                // destination is dir
                queryForRename( destFi.absoluteFilePath(), &newName );
                if( newName.isEmpty() ) {
                    ret = FmErrCancel;
                    break;
                }
                QString targetName = mTargetPath + newName;
                destFi.setFile( targetName );
            }
        }
        if( ret != FmErrNone ) {
            return ret;
        }

        int ret = move( source, mTargetPath, newName );
        if( ret != FmErrNone ) {
            return ret;
        }
    }
    return FmErrNone;
}

int FmOperationMove::move( const QString &source, const QString &targetPath, const QString &newTargetName )
{
    if( *mStop ) {
        return FmErrCancel;
    }

    QFileInfo fi( source );
    if( !fi.exists() ) {
        *mErrString = source;
        return FmErrSrcPathDoNotExist;
    }
    QString newName;
    if( !newTargetName.isEmpty() ) {
        newName = targetPath + newTargetName;
    } else {
        newName = targetPath + fi.fileName();
    }

    int ret = FmErrNone;
    if (fi.isFile()) {
        int fileSize = fi.size();
        if ( !QFile::copy( source, newName )) {
            *mErrString = source;
            ret = FmErrCannotCopy;
        }
        if( !QFile::remove( source ) ) {
            *mErrString = source;
            ret = FmErrCannotRemove;
        }
        increaseProgress( fileSize );
    } else if (fi.isDir()) {
        if( FmUtils::isDefaultFolder( source ) ){
            ret = FmErrRemoveDefaultFolder;
        }
        else{
            ret = moveDirInsideContent( source, newName );
        }
        
        if( ret!= FmErrNone ) {
            return ret;
        }
        if ( !fi.dir().rmdir( fi.absoluteFilePath() ) ) {
            *mErrString = fi.absolutePath();
            return FmErrCannotRemove;
        }
    } else {
        qWarning( "Things other than file and directory are not copied" );
        ret = FmErrIsNotFileOrFolder;
    }

    return ret;
}
int FmOperationMove::moveDirInsideContent( const QString &srcPath, const QString &destPath )
{
    QFileInfo srcInfo( srcPath );
    QFileInfo destInfo( destPath );
        
    QString destUpPath = FmUtils::fillPathWithSplash( destInfo.absolutePath() );
    if( destUpPath.contains( srcPath, Qt::CaseInsensitive ) ) {
        *mErrString = destPath;
        return FmErrMoveDestToSubFolderInSrc;
    }
    
    if( !srcInfo.isDir() || !srcInfo.exists() ) {
        *mErrString = srcPath;
        return FmErrSrcPathDoNotExist;
    }
    
    if( !destInfo.exists() ) {
        if( !destInfo.dir().mkdir( destInfo.absoluteFilePath() ) ) {
            *mErrString = destPath;
            return FmErrCannotMakeDir;
        }
    }
    if( !srcInfo.isDir() ) {
        *mErrString = destPath;
        return FmErrCannotMakeDir;
    }

    //start to move
    QFileInfoList infoList = QDir( srcPath ).entryInfoList( QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden | QDir::System  );
    while( !infoList.isEmpty() ) {
        if( *mStop ) {
            return FmErrCancel;
        }

        QFileInfo fileInfo = infoList.takeFirst();
        if( fileInfo.isFile() ){
            //copy file
            quint64 fileSize = fileInfo.size();
            QString newFilePath = destPath + fileInfo.absoluteFilePath().mid( srcPath.length() );
            if (!QFile::copy( fileInfo.absoluteFilePath(), newFilePath ) ) {
                 *mErrString = fileInfo.absoluteFilePath();
                return FmErrCannotCopy;
            }
            if( !QFile::remove( fileInfo.absoluteFilePath() ) ) {
                *mErrString = fileInfo.absoluteFilePath();
                return FmErrCannotRemove;
            }
            increaseProgress( fileSize );
        } else if( fileInfo.isDir() ) {
            //makedir
            QString newDirPath = destPath + fileInfo.absoluteFilePath().mid( srcPath.length() );
            if( !QDir( newDirPath ).exists() && !QDir( destPath ).mkdir( newDirPath ) ) {
                *mErrString = newDirPath;
                return FmErrCannotMakeDir;
            }
            // add dir content to list.
            QFileInfoList infoListDir = QDir( fileInfo.absoluteFilePath() ).entryInfoList(
                QDir::NoDotAndDotDot | QDir::AllEntries );
            if( infoListDir.isEmpty() ) {
                if ( !fileInfo.dir().rmdir( fileInfo.absoluteFilePath() ) ) {
                    *mErrString = fileInfo.absolutePath();
                    return FmErrCannotRemove;
                }
            } else {
                infoList.push_front( fileInfo );
            }
            while( !infoListDir.isEmpty() ) {
                infoList.push_front( infoListDir.takeLast() );
            }

        } else {
            *mErrString = fileInfo.absoluteFilePath();
            return FmErrIsNotFileOrFolder;
        }

    }

    return FmErrNone;
}

void FmOperationMove::increaseProgress( quint64 size )
{
    if( mTotalSize <=0 ) {
        return;
    }
    mMovedSize += size;
    int step = ( mMovedSize * 100 ) / mTotalSize;
    if( step > mCurrentStep ) {
        mCurrentStep = step;
        emit notifyProgress( mCurrentStep );
    }
}

void FmOperationMove::queryForRename( const QString &srcFile, QString *destFile )
{
    emit askForRename( srcFile, destFile );
}