diff -r 491b3ed49290 -r 65326cf895ed filemanager/GFLM/src/CGflmFileListModel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/filemanager/GFLM/src/CGflmFileListModel.cpp Wed Sep 01 12:31:07 2010 +0100 @@ -0,0 +1,686 @@ +/* +* 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: File list model +* +*/ + + + +// INCLUDE FILES +#include "CGflmFileListModel.h" +#include "MGflmItemGroup.h" +#include "CGflmItemGroupImpl.h" +#include "CGflmDirectoryListingCache.h" +#include "CGflmFileRecognizer.h" +#include "CGflmDriveResolver.h" +#include "CGflmItemLocalizer.h" +#include "CGflmFileSystemItem.h" +#include "CGflmGlobalActionItem.h" +#include "CGflmFileFinder.h" +#include "MGflmItemFilter.h" +#include "GflmUtils.h" +#include "GFLMConsts.h" +#include "GFLM.hrh" +#include +#include +#include + + +// CONSTANTS + +// Granularity of iGroups array +const TInt KItemGroupArrayGranularity = 3; + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::CGflmFileListModel +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CGflmFileListModel::CGflmFileListModel( RFs& aFs ) : + CActive( CActive::EPriorityStandard ), + iFs( aFs ) + { + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CGflmFileListModel* CGflmFileListModel::NewL( RFs& aFs ) + { + CGflmFileListModel* self = new( ELeave ) CGflmFileListModel( aFs ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CGflmFileListModel::ConstructL() + { + FUNC_LOG + + CActiveScheduler::Add( this ); + + iGroups = new( ELeave ) + CArrayPtrSeg< CGflmItemGroupImpl > + ( KItemGroupArrayGranularity ); + iListingCache = CGflmDirectoryListingCache::NewL( iFs, iCanceled ); + iDriveResolver = CGflmDriveResolver::NewL( iFs ); + iFileRecognizer = CGflmFileRecognizer::NewL( + iFs, KGFLMFileRecognizerCacheSize, iDriveResolver ); + iItemLocalizer = CGflmItemLocalizer::NewL(); + iFileFinder = CGflmFileFinder::NewL( + iFs, *iItemLocalizer, *iDriveResolver, iCanceled ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::~CGflmFileListModel +// +// ----------------------------------------------------------------------------- +// +CGflmFileListModel::~CGflmFileListModel() + { + FUNC_LOG + + Cancel(); + if ( iGroups ) + { + iGroups->ResetAndDestroy(); + delete iGroups; + } + delete iFileFinder; + delete iListingCache; + delete iFileRecognizer; + delete iItemLocalizer; + delete iDriveResolver; + iSemaphore.Close(); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::RefreshListL() +// Creates and starts the work thread that refreshes the model +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::RefreshListL( + TRequestStatus& aStatus, TGflmRefreshMode aRefreshMode ) + { + FUNC_LOG + + if ( aStatus == KRequestPending ) + { + return; + } + + iCorrupt = ETrue; + iClientStatus = &aStatus; + *iClientStatus = KRequestPending; + iClientId = RThread().Id(); + + if ( iShutdown ) + { + // Ensure client completion + NotifyClient( KErrNone ); + return; + } + + iCanceled = EFalse; + + if ( !IsActive() ) + { + // Create the work thread to do refresh + iSemaphore.Close(); + User::LeaveIfError( iSemaphore.CreateLocal( 0 ) ); + + RThread workThread; + TInt err( workThread.Create( + KGFLMWorkThreadName, + WorkThreadStart, + KGFLMWorkThreadStackSize, + NULL, + this ) ); + LOG_IF_ERROR1( err, "CGflmFileListModel::RefreshListL-err1=%d", err ) + User::LeaveIfError( err ); + workThread.SetPriority( EPriorityLess ); + workThread.Logon( iStatus ); + SetActive(); + iRefreshMode = aRefreshMode; + workThread.Resume(); + workThread.Close(); + } + else + { + // Signal the work thread to do refresh + iRefreshMode = aRefreshMode; + iSemaphore.Signal(); + } + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::WorkThreadStart() +// An entry point function for the work thread +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CGflmFileListModel::WorkThreadStart( TAny* aPtr ) + { + FUNC_LOG + + CGflmFileListModel* self = static_cast< CGflmFileListModel* >( aPtr ); + CTrapCleanup* cleanupStack = CTrapCleanup::New(); + if ( !cleanupStack ) + { + ERROR_LOG1( + "CGflmFileListModel::WorkThreadStart-err1=%d", KErrNoMemory ) + return KErrNoMemory; + } + + TRAPD( err, self->iItemLocalizer->SetupWorkThreadLocalizerL() ); + LOG_IF_ERROR1( err, "CGflmFileListModel::WorkThreadStart-err2=%d", err ) + + self->WorkThread(); + self->iItemLocalizer->ReleaseWorkThreadLocalizer(); + delete cleanupStack; + + return err; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::WorkThread() +// ----------------------------------------------------------------------------- +// +void CGflmFileListModel::WorkThread() + { + TInt err( KErrNone ); + do + { + + // Do refresh + iCorrupt = ETrue; + err = KErrNone; + + TRAP( err, DoRefreshL() ); + if ( err == KErrNone ) + { + iCorrupt = EFalse; + } + + LOG_IF_ERROR1( err, "CGflmFileListModel::WorkThread-err=%d", err ) + + NotifyClient( err ); + + iSemaphore.Wait(); // Wait for refresh signal from main thread + + } while ( !iShutdown ); + + if ( iShutdown ) + { + // Disable list usage and ensure client completion + iCorrupt = ETrue; + NotifyClient( err ); + } + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::NotifyClient() +// ----------------------------------------------------------------------------- +// +void CGflmFileListModel::NotifyClient( TInt aErr ) + { + FUNC_LOG + + if ( iClientStatus ) + { + RThread client; + if ( client.Open( iClientId ) == KErrNone ) + { + client.RequestComplete( iClientStatus, aErr ); + client.Close(); + } + } + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::DoRefreshL() +// This method does the actual refreshing. It's not static so it can access +// member data and it can leave as it's trap harnessed in RefreshAndNotify() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CGflmFileListModel::DoRefreshL() + { + TIMESTAMP( "GFLM refresh files and folders started: " ) + + INFO_LOG1( + "CGflmFileListModel::DoRefreshL-iSearchEnabled=%d", + iSearchEnabled ) + + if ( iSearchEnabled ) + { + User::LeaveIfError( iDriveResolver->RefreshDrives( iFilter ) ); + iFileFinder->RefreshL( iFilter, iSearchSortMethod, iRefreshMode ); + } + else + { + if ( iRefreshMode == ERefreshItems ) + { + iListingCache->ClearCache(); + } + User::LeaveIfError( iDriveResolver->RefreshDrives( iFilter ) ); + + TInt groupCount( iGroups->Count() ); + for ( TInt i( 0 ); i < groupCount; i++ ) + { + iGroups->At( i )->RefreshL( iFilter, iSortMethod, iRefreshMode ); + } + } + + TIMESTAMP( "GFLM refresh files and folders ended: " ) + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::CancelRefresh() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::CancelRefresh() + { + FUNC_LOG + + iCanceled = ETrue; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::MdcaCount() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CGflmFileListModel::MdcaCount() const + { + if ( iCorrupt ) + { + return 0; + } + if ( iSearchEnabled ) + { + return iFileFinder->ItemCount(); + } + + // Count the total number of items in groups + TInt groupCount( iGroups->Count() ); + TInt itemCount( 0 ); + for( TInt i( 0 ); i < groupCount; i++ ) + { + itemCount += iGroups->At( i )->ItemCount(); + } + return itemCount; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::MdcaPoint() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TPtrC CGflmFileListModel::MdcaPoint( TInt aIndex ) const + { + if ( iSearchEnabled ) + { + return iFileFinder->Item( aIndex )->Name(); + } + + // Return the formatted presentation by global index + MGflmItemGroup* group = NULL; + TInt localIndex( 0 ); + GetGroupAndLocalIndex( aIndex, localIndex, group ); + return group->Item( localIndex )->Name(); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::GetGroupAndLocalIndex() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CGflmFileListModel::GetGroupAndLocalIndex( + const TInt aGlobalIndex, + TInt& aLocalIndex, + MGflmItemGroup*& aGroup ) const + { + // Calculate the group and the requested item's local index + // from a global index + TInt groupCount( iGroups->Count() ); + TInt offset( 0 ); + for( TInt i( 0 ); i < groupCount; i++ ) + { + MGflmItemGroup* currentGroup = iGroups->At( i ); + TInt itemsInGroup( currentGroup->ItemCount() ); + if ( aGlobalIndex < itemsInGroup + offset ) + { + // The global index resides in this group + aGroup = iGroups->At( i ); + aLocalIndex = aGlobalIndex - offset; + return; + } + offset += itemsInGroup; + } + + // Group not found + User::Panic( KGFLMPanicText, EGlobalIndexOutOfBounds ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::Item() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C CGflmGroupItem* CGflmFileListModel::Item( TInt aIndex ) const + { + if ( iSearchEnabled ) + { + return iFileFinder->Item( aIndex ); + } + // Return the formatted presentation by global index + MGflmItemGroup* group = NULL; + TInt localIndex( 0 ); + GetGroupAndLocalIndex( aIndex, localIndex, group ); + return group->Item( localIndex ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::ResetModel() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::ResetModel() + { + iGroups->ResetAndDestroy(); + iListingCache->ClearCache(); + iDriveResolver->ClearDrives(); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::FindGroupById() +// Used to provide clients with CGflmItemGroupImpl objects downcasted to +// CGflmItemGroup. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C MGflmItemGroup* CGflmFileListModel::FindGroupById( TInt aId ) + { + TInt groupCount( iGroups->Count() ); + + for( TInt i( 0 ); i < groupCount; i++ ) + { + CGflmItemGroupImpl* group = iGroups->At( i ); + if ( aId == group->Id() ) + { + return group; + } + } + + // Group not found + User::Panic( KGFLMPanicText, EInvalidGroupId ); + + // Execution never reaches this point + // following line keeps the compiler happy + return NULL; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::CreateGroupL() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +EXPORT_C MGflmItemGroup* CGflmFileListModel::CreateGroupL( TInt aId ) + { + // Scan the list of groups for identical IDs + TInt groupCount( iGroups->Count() ); + for ( TInt i( 0 ); i < groupCount; i++ ) + { + if ( iGroups->At( i )->Id() == aId ) + { + User::Leave( KErrAlreadyExists ); + } + } + + CGflmItemGroupImpl* newGroup = CGflmItemGroupImpl::NewLC( + aId, + iFs, + *iListingCache, + *iItemLocalizer, + *iDriveResolver ); + + iGroups->AppendL( newGroup ); + CleanupStack::Pop( newGroup ); + return newGroup; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::CreateGroupL() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +EXPORT_C MGflmItemGroup* CGflmFileListModel::CreateGroupL( + TInt aId, TUint aInclusion ) + { + MGflmItemGroup* newGroup = CreateGroupL( aId ); + newGroup->SetInclusion( aInclusion ); + return newGroup; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::SetCustomFilter() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +EXPORT_C void CGflmFileListModel::SetCustomFilter( MGflmItemFilter* aFilter ) + { + iFilter = aFilter; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::ResolveMimeTypeL() +// Uses the internal file recognition cache +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +EXPORT_C TPtrC CGflmFileListModel::ResolveMimeTypeL( const TDesC& aFilename ) + { + return iFileRecognizer->RecognizeL( aFilename ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::IsCorrupt() +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +EXPORT_C TBool CGflmFileListModel::IsCorrupt() const + { + return iCorrupt; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::LocalizedName() +// ----------------------------------------------------------------------------- +// +EXPORT_C TPtrC CGflmFileListModel::LocalizedName( const TDesC& aPath ) const + { + return iItemLocalizer->Localize( aPath ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::ClearCache() +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::ClearCache() + { + iListingCache->ClearCache(); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::ClearDriveInfo() +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::ClearDriveInfo() + { + iDriveResolver->ClearDrives(); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::DriveFromPath() +// ----------------------------------------------------------------------------- +// +EXPORT_C CGflmDriveItem* CGflmFileListModel::DriveFromPath( + const TDesC& aPath ) const + { + if ( !iDriveResolver->DriveCount() ) + { + ERROR_LOG( "CGflmFileListModel::DriveFromPath-Forced drive refresh" ) + iDriveResolver->RefreshDrives( iFilter ); + } + return iDriveResolver->DriveFromPath( aPath ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::RunL() +// ----------------------------------------------------------------------------- +// +void CGflmFileListModel::RunL() + { + FUNC_LOG + + NotifyClient( iStatus.Int() ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::RunError +// ----------------------------------------------------------------------------- +// +TInt CGflmFileListModel::RunError( TInt /*aError*/ ) + { + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::DoCancel +// ----------------------------------------------------------------------------- +// +void CGflmFileListModel::DoCancel() + { + FUNC_LOG + + iShutdown = ETrue; + iSemaphore.Signal(); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::DriveFromId +// ----------------------------------------------------------------------------- +// +EXPORT_C CGflmDriveItem* CGflmFileListModel::DriveFromId( + const TInt aDrive ) const + { + if ( !iDriveResolver->DriveCount() ) + { + ERROR_LOG( "CGflmFileListModel::DriveFromId-Forced drive refresh" ) + iDriveResolver->RefreshDrives( iFilter ); + } + return iDriveResolver->DriveFromId( aDrive ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::EnableSearchMode +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::EnableSearchMode( const TBool aEnabled ) + { + iSearchEnabled = aEnabled; + if ( iSearchEnabled ) + { + iSearchSortMethod = EByMatch; // Default for search + } + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::SearchMode +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CGflmFileListModel::SearchMode() + { + return iSearchEnabled; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::SetSearchStringL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::SetSearchStringL( const TDesC& aSearchString ) + { + iFileFinder->SetSearchStringL( aSearchString ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::SetSearchFolderL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::SetSearchFolderL( const TDesC& aSearchFolder ) + { + iFileFinder->SetSearchFolderL( aSearchFolder ); + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::SetSortMethod +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::SetSortMethod( TGflmSortMethod aSortMethod ) + { + if ( iSearchEnabled ) + { + iSearchSortMethod = aSortMethod; + } + else if ( aSortMethod != EByMatch ) // EByMatch is allowed only for search + { + iSortMethod = aSortMethod; + } + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::SortMethod +// ----------------------------------------------------------------------------- +// +EXPORT_C TGflmSortMethod CGflmFileListModel::SortMethod() const + { + if ( iSearchEnabled ) + { + return iSearchSortMethod; + } + return iSortMethod; + } + +// ----------------------------------------------------------------------------- +// CGflmFileListModel::FlushCache() +// ----------------------------------------------------------------------------- +// +EXPORT_C void CGflmFileListModel::FlushCache() + { + iFileRecognizer->FlushCache(); + } + +// End of File