filemanager/src/inc/fmutils.cpp
changeset 41 fc4654ce4fcb
child 46 d58987eac7e8
equal deleted inserted replaced
35:060d0b1ab845 41:fc4654ce4fcb
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *     Zhiqiang Yang <zhiqiang.yang@nokia.com>
       
    14 * 
       
    15 * Description:
       
    16 *     The source file of the file manager utilities
       
    17 */
       
    18 
       
    19 #include "fmutils.h"
       
    20 
       
    21 #include <QDir>
       
    22 #include <QFileInfo>
       
    23 
       
    24 #include <hbglobal.h>
       
    25 
       
    26 /*!
       
    27     Used to get drive type for convenience.
       
    28 */
       
    29 FmDriverInfo::DriveType FmDriverInfo::driveType()
       
    30 {
       
    31     FmDriverInfo::DriveType driveType;
       
    32     if( mDriveState & FmDriverInfo::EDriveRemovable ) {
       
    33         // if drive is removable, it may be mass, usb, or remote drive
       
    34         if( mDriveState & FmDriverInfo::EDriveMassStorage ) {
       
    35             driveType = FmDriverInfo::EDriveTypeMassStorage;
       
    36         } else if( mDriveState & FmDriverInfo::EDriveUsbMemory ) {
       
    37             driveType = FmDriverInfo::EDriveTypeUsbMemory;
       
    38         } else if( mDriveState & FmDriverInfo::EDriveRemote ){
       
    39             driveType = FmDriverInfo::EDriveTypeRemote;
       
    40         } else {
       
    41             driveType = FmDriverInfo::EDriveTypeMemoryCard;
       
    42         }
       
    43     } else if( mDriveState & FmDriverInfo::EDriveRom ) {
       
    44         driveType = FmDriverInfo::EDriveTypeRom;
       
    45     } else if( mDriveState & FmDriverInfo::EDriveRam ) {
       
    46         driveType = FmDriverInfo::EDriveTypeRam;
       
    47     } else {
       
    48         // if drive type is not recognized in previous condition,
       
    49         // it should be an un-existed drive or phone memory
       
    50         if( mDriveState & EDriveNotPresent ){
       
    51             // if come here, means 2 conditions:
       
    52             //  1 this drive is not exist( FmUtils::queryDriverInfo will give EDriveNotPresent to mDriveState )
       
    53             //  2 un-mounted removable drive
       
    54             // removable drive filted in previous condifiton. So, give EDriveTypeNotExist 
       
    55             driveType = FmDriverInfo::EDriveTypeNotExist;
       
    56         } else {
       
    57             // drive is existed, only remain the type of EDriveTypePhoneMemory
       
    58             driveType = FmDriverInfo::EDriveTypePhoneMemory;
       
    59         }
       
    60     }
       
    61     
       
    62     return driveType;
       
    63 }
       
    64 
       
    65 /*!
       
    66     return drive name for \a path
       
    67 */
       
    68 QString FmUtils::getDriveNameFromPath( const QString &path )
       
    69 {
       
    70     // fillPathWithSplash make sure path length will be at least 3 if it is not empty.
       
    71     QString checkedPath( fillPathWithSplash( path ) );
       
    72     if( checkedPath.length() < 3 ) {
       
    73         return QString();
       
    74     }
       
    75     return checkedPath.left( 3 );
       
    76 }
       
    77 
       
    78 /*!
       
    79     return drive letter for \a path
       
    80 */
       
    81 QString FmUtils::getDriveLetterFromPath( const QString &path )
       
    82 {
       
    83 	if( path.length() <2 ) {
       
    84         return QString();
       
    85     }
       
    86     return path.left( 1 );
       
    87 }
       
    88 
       
    89 /*!
       
    90     return formatted string for size.
       
    91 */
       
    92 QString FmUtils::formatStorageSize( quint64 size )
       
    93 {
       
    94 	if ( size < 1000 ) {
       
    95 		return QString::number( size ) + " B";
       
    96 	} else if ( size < 1000 * 1000 ) {
       
    97 		return QString::number( size / 1024.0, 'f', 2 ) + " KB";
       
    98 	} else if ( size < 1000 * 1000 * 1000 ) {
       
    99 		return QString::number( size / (1024.0 * 1024.0), 'f', 1 ) + " MB";
       
   100 	} else {
       
   101 	    return QString::number( size / ( 1024.0 * 1024.0 * 1024.0 ), 'f', 1 ) + " GB";	    
       
   102 	}
       
   103 }
       
   104 
       
   105 /*!
       
   106     Judge if a path is drive path, not a folder or a file.
       
   107     For example, true for C:\ while false for C:\data
       
   108 */
       
   109 bool FmUtils::isDrive( const QString &path )
       
   110 {
       
   111    bool ret( false );
       
   112    if( path.length() <= 3 && path.length() >=2 ) {
       
   113        ret = true;
       
   114    }
       
   115    
       
   116    return ret;   
       
   117 }
       
   118 
       
   119 /*!
       
   120     All "/" and "\" in \a path will be changed to QDir::separator
       
   121     \sa fillPathWithSplash, fillPathWithSplash will append QDir::separator in the end
       
   122 */
       
   123 QString FmUtils::formatPath( const QString &path  )
       
   124 {
       
   125     QString formatPath;
       
   126     if( path.isEmpty() ) {
       
   127         return formatPath;
       
   128     }
       
   129     
       
   130     foreach( const QChar &ch, path ) {
       
   131         if( ch == QChar('\\') || ch == QChar('/') ) {
       
   132             formatPath.append( QDir::separator() );
       
   133         } else {
       
   134             formatPath.append( ch );
       
   135         }
       
   136     }
       
   137 
       
   138     return formatPath;
       
   139 }
       
   140 
       
   141 /*!
       
   142     Fill splash in the end of \a filePath. And all "/" and "\" will be changed to QDir::separator
       
   143     Please do not call this function if path is a file.
       
   144     Use \a formatPath instead, \a formatPath will not append QDir::separator in the end.
       
   145     \sa formatPath only changed "/" and "\" to QDir::separator
       
   146 */
       
   147 QString FmUtils::fillPathWithSplash( const QString &filePath )
       
   148 {
       
   149     QString newFilePath;
       
   150     if( filePath.isEmpty() ) {
       
   151         return newFilePath;
       
   152     }
       
   153 
       
   154     newFilePath = formatPath( filePath );
       
   155     
       
   156     if( newFilePath.right( 1 )!= QDir::separator() ){
       
   157         newFilePath.append( QDir::separator() );
       
   158     }
       
   159     return newFilePath;
       
   160 }
       
   161 
       
   162 /*!
       
   163     Remove splash in the end of \a filePath.
       
   164 */
       
   165 QString FmUtils::removePathSplash( const QString &filePath )
       
   166 {
       
   167     QString newFilePath( filePath );
       
   168     if( filePath.right( 1 ) == QChar( '/' ) || filePath.right(1) == QString( "\\" ) ) {
       
   169         newFilePath = filePath.left( filePath.length() - 1 );
       
   170     }
       
   171     return newFilePath;
       
   172 }
       
   173 
       
   174 /*!
       
   175     fill \a driveList of drives can be shown in driveListView
       
   176 */
       
   177 void FmUtils::getDriveList( QStringList &driveList, bool isHideUnAvailableDrive )
       
   178 {
       
   179     if( isHideUnAvailableDrive ) {
       
   180         FM_LOG( QString( "getDriveList HideUnAvailableDrive_true" ) );
       
   181     } else {
       
   182         FM_LOG( QString( "getDriveList HideUnAvailableDrive_false" ) );
       
   183     }
       
   184     QFileInfoList infoList = QDir::drives();
       
   185 
       
   186     foreach( const QFileInfo &fileInfo, infoList ) {
       
   187         QString driveName = fileInfo.absolutePath();
       
   188         if( checkDriveAccessFilter( driveName ) ) {
       
   189             if( !isHideUnAvailableDrive ) {
       
   190                 driveList.append( driveName );
       
   191             }
       
   192             else if ( isDriveAvailable( driveName ) ) {
       
   193                 driveList.append( driveName );
       
   194             }
       
   195         }
       
   196     }
       
   197     return;
       
   198 }
       
   199 
       
   200 /*!
       
   201     return the combined string of drive name and volume( e.g. C: Phone memory for C drive)
       
   202     \a driveName the drive name.
       
   203     If set \a isFillWithDefaultVolume true, fill result with default volume if drive volume is empty.
       
   204 */
       
   205 QString FmUtils::fillDriveVolume( QString driveName, bool isFillWithDefaultVolume )
       
   206 {
       
   207     QString ret;
       
   208     if( driveName.isEmpty() ) {
       
   209         return ret;
       
   210     }
       
   211     QString tempDriveName = fillPathWithSplash( driveName );
       
   212 
       
   213     QString checkedDriveName( removePathSplash( driveName ) );
       
   214     
       
   215     FmDriverInfo driverInfo = FmUtils::queryDriverInfo( tempDriveName );
       
   216     QString volumeName = driverInfo.volumeName();
       
   217     
       
   218     if( volumeName.isEmpty() && isFillWithDefaultVolume ){
       
   219         switch ( driverInfo.driveType() )
       
   220             {
       
   221             case FmDriverInfo::EDriveTypeMassStorage:
       
   222                 ret = hbTrId( "txt_fmgr_dblist_1_mass_storage" ).arg( checkedDriveName );
       
   223                 break;
       
   224             case FmDriverInfo::EDriveTypeUsbMemory:
       
   225                 ret = hbTrId( "txt_fmgr_dblist_1_usb_memory" ).arg( checkedDriveName );
       
   226                 break;
       
   227             case FmDriverInfo::EDriveTypeMemoryCard:
       
   228                 ret = hbTrId( "txt_fmgr_dblist_1_memory_card" ).arg( checkedDriveName );
       
   229                 break;
       
   230             case FmDriverInfo::EDriveTypePhoneMemory:
       
   231                 ret = hbTrId( "txt_fmgr_dblist_1_device_memory" ).arg( checkedDriveName );
       
   232                 break;
       
   233             case FmDriverInfo::EDriveTypeNotExist:// no such drive
       
   234             default:// do not need get volume for other drive types, e.g. Ram, Rom
       
   235                 break;
       
   236             }    
       
   237     }
       
   238     
       
   239     if( ret.isEmpty() ) {
       
   240         // ret is not got. fill ret as default method
       
   241         // txt_fmgr_dblist_1_2 is not correct, can not use.
       
   242         ret = hbTrId( "%1 %2" ).arg( checkedDriveName ).arg( volumeName );
       
   243     }
       
   244     return ret;
       
   245 }
       
   246 
       
   247 /*!
       
   248     return the default volume for drive
       
   249     \a driveName the drive.
       
   250     \sa getVolumeNameWithDefaultNameIfNull
       
   251 */
       
   252 QString FmUtils::getDefaultVolumeName( const QString &driveName )
       
   253 {
       
   254     QString defaultVolumeName;
       
   255     FmDriverInfo driverInfo = FmUtils::queryDriverInfo( driveName );
       
   256           
       
   257     switch ( driverInfo.driveType() )
       
   258         {
       
   259         case FmDriverInfo::EDriveTypeMassStorage:
       
   260             defaultVolumeName = hbTrId("Mass storage"); 
       
   261             break;
       
   262         case FmDriverInfo::EDriveTypeUsbMemory:
       
   263             defaultVolumeName = hbTrId("USB memory"); 
       
   264             break;
       
   265         case FmDriverInfo::EDriveTypeMemoryCard:
       
   266             defaultVolumeName = hbTrId("Memory card");
       
   267             break;
       
   268         case FmDriverInfo::EDriveTypePhoneMemory:
       
   269             defaultVolumeName = hbTrId("Device memory");
       
   270             break;
       
   271         case FmDriverInfo::EDriveTypeNotExist:// no such drive, break and return empty string
       
   272         default:// do not have default volume for other drive types, e.g. Ram, Rom
       
   273             break;
       
   274         }   
       
   275     return defaultVolumeName;
       
   276 }
       
   277 
       
   278 /*!
       
   279     get the volume name of the drive, if it is null, then return the default name.
       
   280     \a driveName the drive letter.
       
   281     \a defaultName whether it is the default name.
       
   282     return the volume name.
       
   283 */
       
   284 QString FmUtils::getVolumeNameWithDefaultNameIfNull( const QString &driveName, bool &defaultName )
       
   285 {
       
   286     // do not re-use FmUtils::getDefaultVolumeName to save one time for call FmUtils::queryDriverInfo
       
   287     FmDriverInfo driverInfo = FmUtils::queryDriverInfo( driveName );
       
   288           
       
   289     QString volumeName = driverInfo.volumeName();    
       
   290     //save the volume status, whether it is default name
       
   291     defaultName = false;
       
   292     //volume name may be null if not set, it will be set at least for one time in the following while cycling.
       
   293     if ( volumeName.isEmpty() ) {
       
   294         switch ( driverInfo.driveType() )
       
   295             {
       
   296             case FmDriverInfo::EDriveTypeMassStorage:
       
   297                 volumeName = hbTrId("Mass storage"); 
       
   298                 break;
       
   299             case FmDriverInfo::EDriveTypeUsbMemory:
       
   300                 volumeName = hbTrId("USB memory"); 
       
   301                 break;
       
   302             case FmDriverInfo::EDriveTypeMemoryCard:
       
   303                 volumeName = hbTrId("Memory card");
       
   304                 break;
       
   305             case FmDriverInfo::EDriveTypePhoneMemory:
       
   306                 volumeName = hbTrId("Device memory");
       
   307                 break;
       
   308             case FmDriverInfo::EDriveTypeNotExist:// no such drive
       
   309             default:// do not need get volume for other drive types, e.g. Ram, Rom
       
   310                 break;
       
   311             }   
       
   312         if( !volumeName.isEmpty() ) {
       
   313              defaultName = true;
       
   314         }
       
   315     }
       
   316     return volumeName;
       
   317 }
       
   318 
       
   319 /*!
       
   320     Check if two path are the same.
       
   321 */
       
   322 bool FmUtils::isPathEqual( const QString &pathFst, const QString &pathLast )
       
   323 {
       
   324     QString fst( fillPathWithSplash( pathFst ) );
       
   325     QString last( fillPathWithSplash( pathLast ) );
       
   326     if( fst.compare( last, Qt::CaseInsensitive ) == 0 ) {
       
   327         return true;
       
   328     }
       
   329     return false;
       
   330 }
       
   331 
       
   332 /*!
       
   333     Check if a name is illegal for folder/file naming rule.
       
   334 */
       
   335 bool FmUtils::checkFolderFileName( const QString& name )
       
   336 {
       
   337     // trim space firest, because there may be some spaces after "." ,  it is also not valid
       
   338     QString trimmedName( name.trimmed() );
       
   339 	if( trimmedName.isEmpty() ) {
       
   340 		return false;
       
   341 	}
       
   342     if( trimmedName.endsWith( QChar('.'),  Qt::CaseInsensitive ) ) {
       
   343         return false;
       
   344     }
       
   345     if( trimmedName.contains( QChar('\\'), Qt::CaseInsensitive ) ||
       
   346         trimmedName.contains( QChar('/'),  Qt::CaseInsensitive ) ||
       
   347         trimmedName.contains( QChar(':'),  Qt::CaseInsensitive ) ||
       
   348         trimmedName.contains( QChar('*'),  Qt::CaseInsensitive ) ||
       
   349         trimmedName.contains( QChar('?'),  Qt::CaseInsensitive ) ||
       
   350         trimmedName.contains( QChar('\"'), Qt::CaseInsensitive ) ||
       
   351         trimmedName.contains( QChar('<'),  Qt::CaseInsensitive ) ||
       
   352         trimmedName.contains( QChar('>'),  Qt::CaseInsensitive ) ||
       
   353         trimmedName.contains( QChar('|'),  Qt::CaseInsensitive ) ){
       
   354         return false;
       
   355     }
       
   356     // use original name to exam max size of file name
       
   357     if( name.length() > getMaxFileNameLength() ) {
       
   358         return false;
       
   359     }
       
   360     return true;
       
   361 }
       
   362 
       
   363 /*!
       
   364     check file or folder path is illegal or not.
       
   365     \a fileName file/folder name, used to check illegal characters
       
   366     \a path file/folder path, used to check if path is available to use.
       
   367     \a errString if return false, errString will be set for error note.
       
   368     return true for not illegal and false for illegal path.
       
   369 */
       
   370 bool FmUtils::checkNewFolderOrFile( const QString &fileName, const QString &path, QString &errString )
       
   371 {
       
   372     // first check if fileName is valid, then check if path length is valid, and check if file/foler is existed at last
       
   373     QFileInfo fileInfo( path );
       
   374     bool ret( true );   
       
   375     if (!FmUtils::checkFolderFileName( fileName ) ) {
       
   376         errString = hbTrId( "Invalid file or folder name!" );
       
   377         ret = false;
       
   378     } else if( !FmUtils::checkMaxPathLength( path ) ) {
       
   379         errString = hbTrId( "the path you specified is too long!" );
       
   380         ret = false;
       
   381     } else if (fileInfo.exists()) {
       
   382         errString = hbTrId( "%1 already exist!" ).arg( fileInfo.fileName() );
       
   383         ret = false;
       
   384     }
       
   385     return ret;
       
   386 }
       
   387 
       
   388 /*!
       
   389     Check if \a dest is sub level path of \a src
       
   390     Used to check True/False when copy a folder to itself or its subfolder
       
   391     For example, c:\data\test is sub path of c:\data.
       
   392     But c:\data123\test is not sub path of c:\data.
       
   393     So after got right part of path, the first char must be \ or /
       
   394 */
       
   395 bool FmUtils::isSubLevelPath( const QString &src, const QString &dest )
       
   396 {
       
   397     FM_LOG("FmUtils::isSubFolder: src=" + src + " dest=" + dest);
       
   398     QString checkedSrc( FmUtils::fillPathWithSplash( src ) );
       
   399     QString checkedDest( FmUtils::fillPathWithSplash( dest ) );
       
   400     
       
   401     if( checkedDest.contains( checkedSrc, Qt::CaseInsensitive) &&
       
   402             checkedDest.length() > checkedSrc.length() ) {
       
   403         // for example c:\data\ vs c:\data\123\ 
       
   404         FM_LOG("FmUtils::isSubFolder: true");
       
   405         return true;
       
   406     }
       
   407     // for example c:\data\ vs c:\data\ 
       
   408     // for example c:\data\ vs c:\data123\ 
       
   409 
       
   410     FM_LOG("FmUtils::isSubFolder: false");
       
   411     return false;
       
   412 }