filemanager/src/inc/fmutils.cpp
branchRCL_3
changeset 20 491b3ed49290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filemanager/src/inc/fmutils.cpp	Tue Aug 31 15:06:05 2010 +0300
@@ -0,0 +1,412 @@
+/*
+* 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:
+*     Zhiqiang Yang <zhiqiang.yang@nokia.com>
+* 
+* Description:
+*     The source file of the file manager utilities
+*/
+
+#include "fmutils.h"
+
+#include <QDir>
+#include <QFileInfo>
+
+#include <hbglobal.h>
+
+/*!
+    Used to get drive type for convenience.
+*/
+FmDriverInfo::DriveType FmDriverInfo::driveType()
+{
+    FmDriverInfo::DriveType driveType;
+    if( mDriveState & FmDriverInfo::EDriveRemovable ) {
+        // if drive is removable, it may be mass, usb, or remote drive
+        if( mDriveState & FmDriverInfo::EDriveMassStorage ) {
+            driveType = FmDriverInfo::EDriveTypeMassStorage;
+        } else if( mDriveState & FmDriverInfo::EDriveUsbMemory ) {
+            driveType = FmDriverInfo::EDriveTypeUsbMemory;
+        } else if( mDriveState & FmDriverInfo::EDriveRemote ){
+            driveType = FmDriverInfo::EDriveTypeRemote;
+        } else {
+            driveType = FmDriverInfo::EDriveTypeMemoryCard;
+        }
+    } else if( mDriveState & FmDriverInfo::EDriveRom ) {
+        driveType = FmDriverInfo::EDriveTypeRom;
+    } else if( mDriveState & FmDriverInfo::EDriveRam ) {
+        driveType = FmDriverInfo::EDriveTypeRam;
+    } else {
+        // if drive type is not recognized in previous condition,
+        // it should be an un-existed drive or phone memory
+        if( mDriveState & EDriveNotPresent ){
+            // if come here, means 2 conditions:
+            //  1 this drive is not exist( FmUtils::queryDriverInfo will give EDriveNotPresent to mDriveState )
+            //  2 un-mounted removable drive
+            // removable drive filted in previous condifiton. So, give EDriveTypeNotExist 
+            driveType = FmDriverInfo::EDriveTypeNotExist;
+        } else {
+            // drive is existed, only remain the type of EDriveTypePhoneMemory
+            driveType = FmDriverInfo::EDriveTypePhoneMemory;
+        }
+    }
+    
+    return driveType;
+}
+
+/*!
+    return drive name for \a path
+*/
+QString FmUtils::getDriveNameFromPath( const QString &path )
+{
+    // fillPathWithSplash make sure path length will be at least 3 if it is not empty.
+    QString checkedPath( fillPathWithSplash( path ) );
+    if( checkedPath.length() < 3 ) {
+        return QString();
+    }
+    return checkedPath.left( 3 );
+}
+
+/*!
+    return drive letter for \a path
+*/
+QString FmUtils::getDriveLetterFromPath( const QString &path )
+{
+	if( path.length() <2 ) {
+        return QString();
+    }
+    return path.left( 1 );
+}
+
+/*!
+    return formatted string for size.
+*/
+QString FmUtils::formatStorageSize( quint64 size )
+{
+	if ( size < 1000 ) {
+		return QString::number( size ) + " B";
+	} else if ( size < 1000 * 1000 ) {
+		return QString::number( size / 1024.0, 'f', 2 ) + " KB";
+	} else if ( size < 1000 * 1000 * 1000 ) {
+		return QString::number( size / (1024.0 * 1024.0), 'f', 1 ) + " MB";
+	} else {
+	    return QString::number( size / ( 1024.0 * 1024.0 * 1024.0 ), 'f', 1 ) + " GB";	    
+	}
+}
+
+/*!
+    Judge if a path is drive path, not a folder or a file.
+    For example, true for C:\ while false for C:\data
+*/
+bool FmUtils::isDrive( const QString &path )
+{
+   bool ret( false );
+   if( path.length() <= 3 && path.length() >=2 ) {
+       ret = true;
+   }
+   
+   return ret;   
+}
+
+/*!
+    All "/" and "\" in \a path will be changed to QDir::separator
+    \sa fillPathWithSplash, fillPathWithSplash will append QDir::separator in the end
+*/
+QString FmUtils::formatPath( const QString &path  )
+{
+    QString formatPath;
+    if( path.isEmpty() ) {
+        return formatPath;
+    }
+    
+    foreach( const QChar &ch, path ) {
+        if( ch == QChar('\\') || ch == QChar('/') ) {
+            formatPath.append( QDir::separator() );
+        } else {
+            formatPath.append( ch );
+        }
+    }
+
+    return formatPath;
+}
+
+/*!
+    Fill splash in the end of \a filePath. And all "/" and "\" will be changed to QDir::separator
+    Please do not call this function if path is a file.
+    Use \a formatPath instead, \a formatPath will not append QDir::separator in the end.
+    \sa formatPath only changed "/" and "\" to QDir::separator
+*/
+QString FmUtils::fillPathWithSplash( const QString &filePath )
+{
+    QString newFilePath;
+    if( filePath.isEmpty() ) {
+        return newFilePath;
+    }
+
+    newFilePath = formatPath( filePath );
+    
+    if( newFilePath.right( 1 )!= QDir::separator() ){
+        newFilePath.append( QDir::separator() );
+    }
+    return newFilePath;
+}
+
+/*!
+    Remove splash in the end of \a filePath.
+*/
+QString FmUtils::removePathSplash( const QString &filePath )
+{
+    QString newFilePath( filePath );
+    if( filePath.right( 1 ) == QChar( '/' ) || filePath.right(1) == QString( "\\" ) ) {
+        newFilePath = filePath.left( filePath.length() - 1 );
+    }
+    return newFilePath;
+}
+
+/*!
+    fill \a driveList of drives can be shown in driveListView
+*/
+void FmUtils::getDriveList( QStringList &driveList, bool isHideUnAvailableDrive )
+{
+    if( isHideUnAvailableDrive ) {
+        FM_LOG( QString( "getDriveList HideUnAvailableDrive_true" ) );
+    } else {
+        FM_LOG( QString( "getDriveList HideUnAvailableDrive_false" ) );
+    }
+    QFileInfoList infoList = QDir::drives();
+
+    foreach( const QFileInfo &fileInfo, infoList ) {
+        QString driveName = fileInfo.absolutePath();
+        if( checkDriveAccessFilter( driveName ) ) {
+            if( !isHideUnAvailableDrive ) {
+                driveList.append( driveName );
+            }
+            else if ( isDriveAvailable( driveName ) ) {
+                driveList.append( driveName );
+            }
+        }
+    }
+    return;
+}
+
+/*!
+    return the combined string of drive name and volume( e.g. C: Phone memory for C drive)
+    \a driveName the drive name.
+    If set \a isFillWithDefaultVolume true, fill result with default volume if drive volume is empty.
+*/
+QString FmUtils::fillDriveVolume( QString driveName, bool isFillWithDefaultVolume )
+{
+    QString ret;
+    if( driveName.isEmpty() ) {
+        return ret;
+    }
+    QString tempDriveName = fillPathWithSplash( driveName );
+
+    QString checkedDriveName( removePathSplash( driveName ) );
+    
+    FmDriverInfo driverInfo = FmUtils::queryDriverInfo( tempDriveName );
+    QString volumeName = driverInfo.volumeName();
+    
+    if( volumeName.isEmpty() && isFillWithDefaultVolume ){
+        switch ( driverInfo.driveType() )
+            {
+            case FmDriverInfo::EDriveTypeMassStorage:
+                ret = hbTrId( "txt_fmgr_dblist_1_mass_storage" ).arg( checkedDriveName );
+                break;
+            case FmDriverInfo::EDriveTypeUsbMemory:
+                ret = hbTrId( "txt_fmgr_dblist_1_usb_memory" ).arg( checkedDriveName );
+                break;
+            case FmDriverInfo::EDriveTypeMemoryCard:
+                ret = hbTrId( "txt_fmgr_dblist_1_memory_card" ).arg( checkedDriveName );
+                break;
+            case FmDriverInfo::EDriveTypePhoneMemory:
+                ret = hbTrId( "txt_fmgr_dblist_1_device_memory" ).arg( checkedDriveName );
+                break;
+            case FmDriverInfo::EDriveTypeNotExist:// no such drive
+            default:// do not need get volume for other drive types, e.g. Ram, Rom
+                break;
+            }    
+    }
+    
+    if( ret.isEmpty() ) {
+        // ret is not got. fill ret as default method
+        // txt_fmgr_dblist_1_2 is not correct, can not use.
+        ret = hbTrId( "%1 %2" ).arg( checkedDriveName ).arg( volumeName );
+    }
+    return ret;
+}
+
+/*!
+    return the default volume for drive
+    \a driveName the drive.
+    \sa getVolumeNameWithDefaultNameIfNull
+*/
+QString FmUtils::getDefaultVolumeName( const QString &driveName )
+{
+    QString defaultVolumeName;
+    FmDriverInfo driverInfo = FmUtils::queryDriverInfo( driveName );
+          
+    switch ( driverInfo.driveType() )
+        {
+        case FmDriverInfo::EDriveTypeMassStorage:
+            defaultVolumeName = hbTrId("Mass storage"); 
+            break;
+        case FmDriverInfo::EDriveTypeUsbMemory:
+            defaultVolumeName = hbTrId("USB memory"); 
+            break;
+        case FmDriverInfo::EDriveTypeMemoryCard:
+            defaultVolumeName = hbTrId("Memory card");
+            break;
+        case FmDriverInfo::EDriveTypePhoneMemory:
+            defaultVolumeName = hbTrId("Device memory");
+            break;
+        case FmDriverInfo::EDriveTypeNotExist:// no such drive, break and return empty string
+        default:// do not have default volume for other drive types, e.g. Ram, Rom
+            break;
+        }   
+    return defaultVolumeName;
+}
+
+/*!
+    get the volume name of the drive, if it is null, then return the default name.
+    \a driveName the drive letter.
+    \a defaultName whether it is the default name.
+    return the volume name.
+*/
+QString FmUtils::getVolumeNameWithDefaultNameIfNull( const QString &driveName, bool &defaultName )
+{
+    // do not re-use FmUtils::getDefaultVolumeName to save one time for call FmUtils::queryDriverInfo
+    FmDriverInfo driverInfo = FmUtils::queryDriverInfo( driveName );
+          
+    QString volumeName = driverInfo.volumeName();    
+    //save the volume status, whether it is default name
+    defaultName = false;
+    //volume name may be null if not set, it will be set at least for one time in the following while cycling.
+    if ( volumeName.isEmpty() ) {
+        switch ( driverInfo.driveType() )
+            {
+            case FmDriverInfo::EDriveTypeMassStorage:
+                volumeName = hbTrId("Mass storage"); 
+                break;
+            case FmDriverInfo::EDriveTypeUsbMemory:
+                volumeName = hbTrId("USB memory"); 
+                break;
+            case FmDriverInfo::EDriveTypeMemoryCard:
+                volumeName = hbTrId("Memory card");
+                break;
+            case FmDriverInfo::EDriveTypePhoneMemory:
+                volumeName = hbTrId("Device memory");
+                break;
+            case FmDriverInfo::EDriveTypeNotExist:// no such drive
+            default:// do not need get volume for other drive types, e.g. Ram, Rom
+                break;
+            }   
+        if( !volumeName.isEmpty() ) {
+             defaultName = true;
+        }
+    }
+    return volumeName;
+}
+
+/*!
+    Check if two path are the same.
+*/
+bool FmUtils::isPathEqual( const QString &pathFst, const QString &pathLast )
+{
+    QString fst( fillPathWithSplash( pathFst ) );
+    QString last( fillPathWithSplash( pathLast ) );
+    if( fst.compare( last, Qt::CaseInsensitive ) == 0 ) {
+        return true;
+    }
+    return false;
+}
+
+/*!
+    Check if a name is illegal for folder/file naming rule.
+*/
+bool FmUtils::checkFolderFileName( const QString& name )
+{
+    // trim space firest, because there may be some spaces after "." ,  it is also not valid
+    QString trimmedName( name.trimmed() );
+	if( trimmedName.isEmpty() ) {
+		return false;
+	}
+    if( trimmedName.endsWith( QChar('.'),  Qt::CaseInsensitive ) ) {
+        return false;
+    }
+    if( trimmedName.contains( QChar('\\'), Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar('/'),  Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar(':'),  Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar('*'),  Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar('?'),  Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar('\"'), Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar('<'),  Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar('>'),  Qt::CaseInsensitive ) ||
+        trimmedName.contains( QChar('|'),  Qt::CaseInsensitive ) ){
+        return false;
+    }
+    // use original name to exam max size of file name
+    if( name.length() > getMaxFileNameLength() ) {
+        return false;
+    }
+    return true;
+}
+
+/*!
+    check file or folder path is illegal or not.
+    \a fileName file/folder name, used to check illegal characters
+    \a path file/folder path, used to check if path is available to use.
+    \a errString if return false, errString will be set for error note.
+    return true for not illegal and false for illegal path.
+*/
+bool FmUtils::checkNewFolderOrFile( const QString &fileName, const QString &path, QString &errString )
+{
+    // first check if fileName is valid, then check if path length is valid, and check if file/foler is existed at last
+    QFileInfo fileInfo( path );
+    bool ret( true );   
+    if (!FmUtils::checkFolderFileName( fileName ) ) {
+        errString = hbTrId( "Invalid file or folder name!" );
+        ret = false;
+    } else if( !FmUtils::checkMaxPathLength( path ) ) {
+        errString = hbTrId( "the path you specified is too long!" );
+        ret = false;
+    } else if (fileInfo.exists()) {
+        errString = hbTrId( "%1 already exist!" ).arg( fileInfo.fileName() );
+        ret = false;
+    }
+    return ret;
+}
+
+/*!
+    Check if \a dest is sub level path of \a src
+    Used to check True/False when copy a folder to itself or its subfolder
+    For example, c:\data\test is sub path of c:\data.
+    But c:\data123\test is not sub path of c:\data.
+    So after got right part of path, the first char must be \ or /
+*/
+bool FmUtils::isSubLevelPath( const QString &src, const QString &dest )
+{
+    FM_LOG("FmUtils::isSubFolder: src=" + src + " dest=" + dest);
+    QString checkedSrc( FmUtils::fillPathWithSplash( src ) );
+    QString checkedDest( FmUtils::fillPathWithSplash( dest ) );
+    
+    if( checkedDest.contains( checkedSrc, Qt::CaseInsensitive) &&
+            checkedDest.length() > checkedSrc.length() ) {
+        // for example c:\data\ vs c:\data\123\ 
+        FM_LOG("FmUtils::isSubFolder: true");
+        return true;
+    }
+    // for example c:\data\ vs c:\data\ 
+    // for example c:\data\ vs c:\data123\ 
+
+    FM_LOG("FmUtils::isSubFolder: false");
+    return false;
+}