--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filemanager/GFLM/src/CGflmFileListModel.cpp Mon Jan 18 20:09:41 2010 +0200
@@ -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 <e32base.h>
+#include <e32std.h>
+#include <badesca.h>
+
+
+// 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