filemanager/App/src/CFileManagerStringCache.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 25 May 2010 12:28:34 +0300
branchRCL_3
changeset 20 efe289f793e7
parent 0 6a9f87576119
permissions -rw-r--r--
Revision: 201019 Kit: 2010121

/*
* Copyright (c) 2002-2007 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:  Cache for strings
*
*/


// INCLUDES
#include <AknUtils.h>
#include <StringLoader.h>
#include <filemanager.rsg>
#include <CFileManagerEngine.h>
#include <CFileManagerItemProperties.h>
#include <CFileManagerCommonDefinitions.h>
#include <CFileManagerFeatureManager.h>
#include "CFileManagerStringCache.h"
#include "CFileManagerIconArray.h"

// CONSTANTS
const TInt KFmgrMaximumSizeOfIconIdString = 3;
_LIT( KIconStr, "%d" );
const TInt KMaxSizeString = 16;
const TInt64 KKileByte = 1024;
const TInt64 KMegaByte = 1048576;
const TInt64 KGigaByte = 1073741824;
const TInt64 KKileByteLowLimit = 100; // 100 bytes
const TInt64 KMegaByteLowLimit = 1048576; // 1MB
const TInt64 KGigaByteLowLimit = 1073741824; // 1GB
const TInt KSizeDecimals = 1;
const TInt KSizeTextArrayLen = 2;

_LIT( KDateFormat1, "%1" );
_LIT( KDateFormat2, "%2" );
_LIT( KDateFormat3, "%3" );
const TUint KSecondSeparator = 1;
const TUint KThirdSeparator = 2;
const TInt KDateStrMax = 20;


// ============================ LOCAL FUNCTIONS ================================

// -----------------------------------------------------------------------------
// GetUnitAndFormatSize
// -----------------------------------------------------------------------------
//
static TInt GetUnitAndFormatSize( TDes& aDes, const TInt64& aSize )
    {
    TRealFormat sizeFormat( aDes.MaxLength(), KSizeDecimals );
    sizeFormat.iType |= KDoNotUseTriads;
    TInt ret( R_QTN_FMGR_UNITS_BYTE );
    if ( aSize >= KGigaByteLowLimit )
        {
        // Format in GBs with decimals
        TReal size( I64REAL( aSize ) / I64REAL( KGigaByte ) );
        aDes.AppendNum( size, sizeFormat );
        ret = R_QTN_FMGR_UNITS_GIGABYTE;
        }
    else if ( aSize >= KMegaByteLowLimit )
        {
        // Format in MBs with decimals
        TReal size( I64REAL( aSize ) / I64REAL( KMegaByte ) );
        aDes.AppendNum( size, sizeFormat );
        ret = R_QTN_FMGR_UNITS_MEGABYTE;
        }
    else if ( aSize >= KKileByteLowLimit )
        {
        // Format in kBs with decimals
        TReal size( I64REAL( aSize ) / I64REAL( KKileByte ) );
        aDes.AppendNum( size, sizeFormat );
        ret = R_QTN_FMGR_UNITS_KILOBYTE;
        }
    else
        {
        // Format in bytes
        aDes.AppendNum( aSize );
        }
    AknTextUtils::LanguageSpecificNumberConversion( aDes );
    return ret;
    }

// -----------------------------------------------------------------------------
// GetFreeSpaceStringL
// -----------------------------------------------------------------------------
//
static HBufC* GetFreeSpaceStringL( const TInt64& aSize )
    {
    CDesCArray* sizeTexts = new ( ELeave ) CDesCArrayFlat( KSizeTextArrayLen );
    CleanupStack::PushL( sizeTexts );
    TBuf< KMaxSizeString > size;
    HBufC* unit = StringLoader::LoadLC( GetUnitAndFormatSize( size, aSize ) );
    sizeTexts->AppendL( size );
    sizeTexts->AppendL( *unit );
    CleanupStack::PopAndDestroy( unit );
    HBufC* ret = StringLoader::LoadL( R_QTN_FMGR_FREE_MEMORY_VAR_UNITS,
        *sizeTexts );
    CleanupStack::PopAndDestroy( sizeTexts );
    return ret;
    }

// -----------------------------------------------------------------------------
// DateStringL
// -----------------------------------------------------------------------------
//
static HBufC* DateStringL( const TTime& aTime )
    {
    TBuf< KDateStrMax > dateStr;
    TBuf< KDateStrMax > dateStrFormat;
    TLocale local;
    dateStrFormat.Append( KDateFormat1 );
    dateStrFormat.Append( local.DateSeparator( KSecondSeparator ) );
    dateStrFormat.Append( KDateFormat2 );
    dateStrFormat.Append( local.DateSeparator( KThirdSeparator ) );
    dateStrFormat.Append( KDateFormat3 );
    aTime.FormatL( dateStr, dateStrFormat );
    return dateStr.AllocL();
    }

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

// -----------------------------------------------------------------------------
// CFileManagerStringCache::CFileManagerStringCache
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CFileManagerStringCache::CFileManagerStringCache(
        CFileManagerEngine& aEngine,
        CFileManagerIconArray& aIconArray ) :
    iEngine( aEngine ),
    iIconArray( aIconArray )
    {
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CFileManagerStringCache* CFileManagerStringCache::NewL(
        CFileManagerEngine& aEngine,
        CFileManagerIconArray& aIconArray )
    {
    CFileManagerStringCache* self = new( ELeave )
        CFileManagerStringCache( aEngine, aIconArray );
    
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );

    return self;
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::ConstructL
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerStringCache::ConstructL()
    {
    Clear();
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::~CFileManagerStringCache
// Destructor
// -----------------------------------------------------------------------------
// 
CFileManagerStringCache::~CFileManagerStringCache()
    {
    Clear();
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::MdcaCount
// 
// -----------------------------------------------------------------------------
// 
TInt CFileManagerStringCache::MdcaCount() const
    {
    return iEngine.FileList()->MdcaCount();
    }
        
// -----------------------------------------------------------------------------
// CFileManagerStringCache::MdcaPoint
// 
// -----------------------------------------------------------------------------
// 
TPtrC CFileManagerStringCache::MdcaPoint( TInt aIndex ) const
    {
    TInt err( KErrNone );
    TInt index( FormattedStringFound( aIndex ) );

    if ( index >= 0 )
        {
        return FormattedString( index );
        }

    iFormatString.Zero();

    // Get icon
    TInt iconId( EFileManagerOtherFileIcon );
    TRAP( err, iconId = iEngine.IconIdL( aIndex ) );
    if ( err != KErrNone )
        {
        iconId = EFileManagerOtherFileIcon;
        SetError( err );
        }
    // Get name
    CFileManagerItemProperties* prop = NULL;
    TRAP( err, prop = iEngine.GetItemInfoL( aIndex ) );
    if ( err == KErrNone )
        {
        TPtrC ptr( prop->LocalizedName() );
        if ( iconId != EFileManagerFolderIcon &&
             iconId != EFileManagerFolderSubIcon &&
             iconId != EFileManagerFolderEmptyIcon )
            {
            // Append file name with conversion
            HBufC* buffer = NULL;
            TRAP( err,  buffer = AknTextUtils::ConvertFileNameL( ptr ) );
            if ( err == KErrNone )
                {
                iFormatString.Append( *buffer );
                }
            else
                {
                // Put file name without any convertion, its better than nothing
                iFormatString.Append( ptr );
                SetError( err );
                }
            delete buffer;
            }
        else
            {
            // Append folder name
            iFormatString.Append( ptr );
            }
        }
    else
        {
        SetError( err );
        }
    // Remove all other possible tabs in string than the icon separator,
    // so that listbox won't get broken
    AknTextUtils::StripCharacters( iFormatString, KFmgrTab );

    AknTextUtils::ReplaceCharacters( iFormatString, KFmgrLineFeed, KFmgrSpace()[0] );
    AknTextUtils::ReplaceCharacters( iFormatString, KFmgrParagraphSeparator, KFmgrSpace()[0] );

    TInt iconIndex( iIconArray.FindIcon( iconId ) );
    if ( iconIndex >= 0 )
        {
        iFormatString.Insert( 0, KFmgrTab );
        TBuf<KFmgrMaximumSizeOfIconIdString> numBuf;
        numBuf.Copy( KIconStr );
        numBuf.Format( KIconStr, iconIndex );
        iFormatString.Insert( 0, numBuf );
        }
    else
        {
        SetError( iconIndex );
        }

    if ( err == KErrNone && prop && prop->IsDrive() )
        {
        TFileManagerDriveInfo drvInfo;
        TRAP( err, iEngine.GetDriveInfoL( prop->DriveId(), drvInfo ) );
        if ( err == KErrNone )
            {
            // Show free space for accessible local drives
            if ( ( drvInfo.iState & TFileManagerDriveInfo::EDrivePresent ) &&
                 !( drvInfo.iState & ( TFileManagerDriveInfo::EDriveRemote |
                                       TFileManagerDriveInfo::EDriveCorrupted |
                                       TFileManagerDriveInfo::EDriveLocked |
                                       TFileManagerDriveInfo::EDriveInUse ) ) )
                {
                HBufC* freeSpace = NULL;
                TRAP( err, freeSpace = GetFreeSpaceStringL( drvInfo.iSpaceFree ) );
                if ( err == KErrNone )
                    {
                    iFormatString.Append( KFmgrTab );
                    iFormatString.Append( *freeSpace );
                    }
                else
                    {
                    SetError( err );
                    }
                delete freeSpace;
                }
            // Show connection icon for connected remote drives
            else if ( ( drvInfo.iState & TFileManagerDriveInfo::EDriveRemote ) &&
                      ( drvInfo.iState & TFileManagerDriveInfo::EDriveConnected ) )
                {
                iconIndex = iIconArray.FindIcon(
                    EFileManagerRemoteDriveConnectedIcon );
                if ( iconIndex >= 0 )
                    {
                    iFormatString.Append( KFmgrTab );
                    iFormatString.Append( KFmgrTab );
                    iFormatString.AppendNum( iconIndex );
                    }
                else if ( iconIndex != KErrNotFound )
                    {
                    SetError( iconIndex );
                    }
                }
            }
        }
    else if ( err == KErrNone && prop && !prop->FullPath().Length() )
        {
        // Show the latest backup date
        TTime time( 0 );
        if( prop->ModifiedLocalDate( time ) == KErrNone )
            {
            HBufC* date = NULL;
            if ( !(time.DateTime().Year()) )
            	{
            	iFormatString.Append( KFmgrTab );
            	iFormatString.Append( KNullDesC );
            	}
            else
            	{
	            
	            TRAPD( err2, date = DateStringL( time ) );
	            if ( err2 == KErrNone )
	                {
	                iFormatString.Append( KFmgrTab );
	                iFormatString.Append( *date );
	                delete date;
	                }
            	}
            }
        }

    delete prop;

    TRAP( err, StoreFormattedStringL( aIndex ) );
    if( err != KErrNone )
        {
        Clear();
        SetError( err );
        }

    return iFormatString;
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::Clear
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerStringCache::Clear() const
    {
    for ( TInt i( 0 ); i < KNumStringCacheItems; i++ )
        {
        Clear( i );
        }
    iError = KErrNone;
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::FormattedStringFound
// 
// -----------------------------------------------------------------------------
// 
TInt CFileManagerStringCache::FormattedStringFound( TInt aIndex ) const
    {
    for ( TInt i( 0 ); i < KNumStringCacheItems; i++ )
        {
        if ( iFormattedItems[ i ].iIndex == aIndex )
            {
            return i;
            }
        }
    return KErrNotFound;
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::FormattedString
// 
// -----------------------------------------------------------------------------
// 
TPtrC CFileManagerStringCache::FormattedString( TInt aIndex ) const 
    {
    TCacheItem& item = iFormattedItems[ aIndex ];
    if ( item.iString )
        {
        return item.iString->Des();
        }
    return TPtrC( KNullDesC );
    }
 
// -----------------------------------------------------------------------------
// CFileManagerStringCache::StoreFormattedString
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerStringCache::StoreFormattedStringL( TInt aIndex ) const
    {
    TInt count( MdcaCount() );
    TInt replace( 0 );
    TInt maxDist( 0 );

    // Find index to be replaced for cyclic list scroll
    for ( TInt i( 0 ); i < KNumStringCacheItems; i++ )
        {
        TCacheItem& item = iFormattedItems[ i ];
        if ( item.iIndex != KErrNotFound )
            {
            TInt dist( Min( Abs( item.iIndex - aIndex ),
                ( count - aIndex ) + item.iIndex ) );
            if ( dist > maxDist )
                {
                maxDist = dist;
                replace = i;
                }
            }
        else
            {
            replace = i;
            break;
            }
        }
    // Setup new cached item
    Clear( replace );
    TCacheItem& item = iFormattedItems[ replace ];
    item.iString = iFormatString.AllocL();
    item.iIndex = aIndex;
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::Clear
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerStringCache::Clear( TInt aIndex ) const
    {
    TCacheItem& item = iFormattedItems[ aIndex ];
    delete item.iString;
    item.iString = NULL;
    item.iIndex = KErrNotFound;
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::LastError
// 
// -----------------------------------------------------------------------------
// 
TInt CFileManagerStringCache::LastError() const
    {
    return iError;
    }

// -----------------------------------------------------------------------------
// CFileManagerStringCache::SetError
// 
// -----------------------------------------------------------------------------
// 
void CFileManagerStringCache::SetError( TInt aError ) const
    {
    if ( aError == KErrNoMemory ||
        ( aError != KErrNone && iError == KErrNone ) )
        {
        iError = aError;
        }
    }

// End of File