--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mpx/collectionframework/collectionutility/src/mpxcollectionopenutility.cpp Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,969 @@
+/*
+* Copyright (c) 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: Incremental OpenL() utility
+*
+*/
+
+
+#include <e32base.h>
+#include <mpxmessage.h>
+#include <mpxcollectionpath.h>
+#include <mpxcollectionutility.h>
+#include <mpxcollectionmessagedefs.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxincrementalopendefs.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxcollectionmessage.h>
+#include <mpxlog.h>
+#include <mpxcollectionopenlresultdef.h>
+#include <mpxcollectioncommanddefs.h>
+#include "mpxcollectionopenutility.h"
+#include <e32math.h>
+
+// CONSTANTS
+const TInt KArrayGranularity = 5;
+
+// ---------------------------------------------------------------------------
+// static function to compare two datablock items
+// used for sorting datablocks
+// ---------------------------------------------------------------------------
+//
+static TInt CompareAsc( const TMPXOpenDataBlock& aFirst,
+ const TMPXOpenDataBlock& aSecond )
+ {
+ return aFirst.iOffset > aSecond.iOffset;
+ }
+
+// ---------------------------------------------------------------------------
+// static function to compare two datablock items
+// used for sorting datablocks
+// ---------------------------------------------------------------------------
+//
+static TInt CompareDsc( const TMPXOpenDataBlock& aFirst,
+ const TMPXOpenDataBlock& aSecond )
+ {
+ return aFirst.iOffset < aSecond.iOffset;
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXCollectionOpenUtility::CMPXCollectionOpenUtility( MMPXCollectionObserver* aObs,
+ TUid aMode )
+ : iFetchStep(EFetchNone),
+ iObs( aObs ),
+ iIncrementalChunks(KArrayGranularity),
+ iMode( aMode )
+
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// 2nd Phase Constructor
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::ConstructL()
+ {
+ iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Two-Phased Constructor
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionOpenUtility* CMPXCollectionOpenUtility::NewL(
+ MMPXCollectionObserver* aObs,
+ TUid aMode )
+ {
+ CMPXCollectionOpenUtility* self =
+ new( ELeave ) CMPXCollectionOpenUtility( aObs, aMode );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMPXCollectionOpenUtility::~CMPXCollectionOpenUtility()
+ {
+ if( iCollection )
+ {
+ iCollection->Close();
+ }
+
+ if( iTimer )
+ {
+ iTimer->Cancel();
+ delete iTimer;
+ }
+
+ iIncrementalChunks.Close();
+ delete iPath;
+ delete iMedia;
+ }
+
+// ---------------------------------------------------------------------------
+// Start the incremental fetching operation
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionOpenUtility::StartL( TArray<TMPXAttribute> /*aAttrs*/,
+ TInt aChunkSize,
+ TInt aOffset,
+ TDirection aDirection,
+ TMPXAttribute aKeyAttribute )
+ {
+ // Assert we are idle
+ ASSERT( iFetchStep == EFetchNone );
+ MPX_DEBUG1("CMPXCollectionOpenUtility::StartL <---");
+ // Copy the operation data
+ iFetchInfo.iSize = aChunkSize;
+ iFetchInfo.iOffset = aOffset;
+ iFetchDirection = aDirection;
+ iKeyAttribute = aKeyAttribute;
+ iData = NULL;
+ delete iMedia;
+ iMedia = NULL;
+ delete iPath;
+ iPath = NULL;
+ // Start reading
+ iFetchStep = EFetchCount;
+ RunNext();
+ MPX_DEBUG1("CMPXCollectionOpenUtility::StartL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Start the incremental fetching operation
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionOpenUtility::StartL( const CMPXCollectionPath& aPath,
+ TArray<TMPXAttribute> /*aAttrs*/,
+ TInt aChunkSize,
+ TInt aOffset,
+ TDirection aDirection,
+ TMPXAttribute aKeyAttribute )
+ {
+ // Assert we are idle and isolated mode
+ MPX_ASSERT( iFetchStep == EFetchNone );
+ MPX_ASSERT( iMode == KMcModeIsolated || iMode == KMcModePlaylist );
+ MPX_DEBUG1("CMPXCollectionOpenUtility::StartL aPath <---");
+ if( !iCollection )
+ {
+ iCollection = MMPXCollectionUtility::NewL( this, iMode );
+ }
+
+ // Copy the operation data
+ MPX_DEBUG_PATH( aPath );
+ iFetchInfo.iSize = aChunkSize;
+ iFetchInfo.iOffset = aOffset;
+ iFetchDirection = aDirection;
+ iKeyAttribute = aKeyAttribute;
+ iData = NULL;
+ delete iMedia;
+ iMedia = NULL;
+
+ delete iPath;
+ iPath = NULL;
+ iPath = CMPXCollectionPath::NewL( aPath );
+
+ // Start the fetch operation by setting up the context
+ // to the correct path
+ //
+ iFetchStep = EFetchPath;
+ RunNext();
+
+ MPX_DEBUG1("CMPXCollectionOpenUtility::StartL --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Stop the incremental fetching operation
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionOpenUtility::Stop()
+ {
+ // Cancel all outstanding collection open requests
+ MPX_DEBUG1("CMPXCollectionOpenUtility::Stop <---");
+ if( iCollection )
+ {
+ iCollection->Collection().CancelRequest();
+ }
+ iTimer->Cancel();
+ iIncrementalChunks.Reset();
+ delete iMedia;
+ iMedia = NULL;
+ iData = NULL;
+ iFetchStep = EFetchNone;
+ MPX_DEBUG1("CMPXCollectionOpenUtility::Stop --->");
+ }
+
+// ---------------------------------------------------------------------------
+// Set the direction of the incremental fetching algorithm
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionOpenUtility::SetDirection( TDirection aDirection )
+ {
+ iFetchDirection = aDirection;
+
+ if( iFetchStep == EFetchItems || iFetchStep == EFetchCommand )
+ {
+ TBool skipFirst = iFetchStep == EFetchCommand ? ETrue : EFalse;
+
+ if( iFetchDirection == EFetchDown )
+ {
+ DoSortAscend( skipFirst );
+ }
+ else if( iFetchDirection == EFetchUp )
+ {
+ DoSortDescend( skipFirst );
+ }
+ else if( iFetchDirection == EFetchNormal )
+ {
+ TRAP_IGNORE( DoSortNormalL( skipFirst ) );
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Set the fetching delay
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionOpenUtility::SetDelay( TInt aDelay )
+ {
+ iFetchDelay = aDelay;
+ }
+
+// ---------------------------------------------------------------------------
+// Get the current path
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPath* CMPXCollectionOpenUtility::PathL()
+ {
+ CMPXCollectionPath* p(NULL);
+
+ if( iCollection )
+ {
+ p = iCollection->Collection().PathL();
+ }
+ return p;
+ }
+
+// ---------------------------------------------------------------------------
+// Handle Collection Message
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::HandleCollectionMessage(CMPXMessage* aMsg, TInt aErr)
+ {
+ if( aErr == KErrNone && aMsg )
+ {
+ TRAP_IGNORE( DoHandleCollectionMessageL( *aMsg ) );
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // HandleOpenL
+ // ---------------------------------------------------------------------------
+ //
+void CMPXCollectionOpenUtility::HandleOpenL(const CMPXMedia& aEntries,
+ TInt aIndex,
+ TBool aComplete,
+ TInt aError)
+ {
+ if( iFetchStep == EFetchCount )
+ {
+ DoHandleCountL( aEntries, aIndex, aError );
+ }
+ else if( iFetchStep == EFetchItems )
+ {
+ DoHandleFetchItemsL( aEntries, aIndex, aError );
+ }
+ else
+ {
+ MPX_DEBUG1("CMPXCollectionOpenUtility::HandleOpenL EFetchPath/EFetchNone");
+ iFetchStep = EFetchNone;
+ iObs->HandleOpenL( aEntries, aIndex, aComplete, aError );
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // HandleOpenL
+ // ---------------------------------------------------------------------------
+ //
+void CMPXCollectionOpenUtility::HandleOpenL(const CMPXCollectionPlaylist& aPlaylist,
+ TInt aError)
+ {
+ iObs->HandleOpenL( aPlaylist, aError );
+ }
+
+ // ---------------------------------------------------------------------------
+ // Handle Command Complete
+ // ---------------------------------------------------------------------------
+ //
+void CMPXCollectionOpenUtility::HandleCommandComplete(CMPXCommand* aCommandResult,
+ TInt aError )
+ {
+ // Continue fetching items
+ iFetchStep = EFetchItems;
+ TRAP_IGNORE( DoHandleCommandCompleteL( *aCommandResult, aError ) );
+ }
+
+ // ---------------------------------------------------------------------------
+ // Handle Collection Media
+ // ---------------------------------------------------------------------------
+ //
+void CMPXCollectionOpenUtility::HandleCollectionMediaL(const CMPXMedia& /*aMedia*/,
+ TInt /*aError*/)
+ {
+ // Do Nothing
+ }
+
+// ---------------------------------------------------------------------------
+// Handle Collection Messages
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoHandleCollectionMessageL( const CMPXMessage& aMsg )
+ {
+ TMPXMessageId id( aMsg.ValueTObjectL<TMPXMessageId>( KMPXMessageGeneralId ) );
+ if ( KMPXMessageGeneral == id &&
+ iFetchStep == EFetchPath )
+ {
+ TInt event( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) );
+ TInt type( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralType ) );
+ TInt data( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralData) );
+ if ( event == TMPXCollectionMessage::EPathChanged &&
+ type == EMcPathChangedByOpen )
+ {
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleCollectionMessageL -- path opened");
+
+ if( data == EMcContainerOpened)
+ {
+ iFetchStep = EFetchCount;
+ RunNext();
+ }
+ else if( data == EMcItemOpened ) // only 2 cases
+ {
+ // Playlist, simply forward back to the observer
+ iCollection->Collection().OpenL();
+ iFetchStep = EFetchNone;
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Handle Command complete
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoHandleCommandCompleteL(CMPXCommand& /*aCommandResult*/,
+ TInt aError)
+ {
+ if( iSelecting )
+ {
+ iSelecting = EFalse;
+ }
+ else if( aError == KErrNone )
+ {
+ // Get the data to return to the client, callback at HandleOpen()
+ //
+ // Implemented because the command tells the plugin to fetch the
+ // next block of data. However, the actual media object containing
+ // the current browse data may have been re-allocated. We cannot
+ // assume that the data pointer remains the same. Therefore, it is
+ // safer to refetch the data from the collection via OpenL()
+ // This call should be FAST because the data has already been read at this point
+ //
+ MPX_DEBUG1("CMPXCollectionOpenUtility::HandleCommandComplete OpenL <---");
+ if( iIncrementalChunks.Count() == 1 || iFirstOpen )
+ {
+ DoSelectIndexL();
+ }
+ iCollection->Collection().OpenL();
+ }
+ else if( aError == KErrNotReady )
+ {
+ // Cache was deleted, need to restart the fetching operation
+ Stop();
+ iFetchStep = EFetchCount;
+ iCollection->Collection().OpenL();
+ }
+ else // aError != KErrNone
+ {
+ // Error occured, such as not supported
+ MPX_DEBUG2("CMPXCollectionOpenUtility::HandleCommandComplete Error %i <---", aError);
+ iFetchStep = EFetchNone;
+
+ CMPXMedia* temp = CMPXMedia::NewL();
+ CleanupStack::PushL( temp );
+ iObs->HandleOpenL( *temp, 0, ETrue, aError );
+ CleanupStack::PopAndDestroy( temp );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Fetch count step
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoFetchCountL()
+ {
+ if( !iCollection )
+ {
+ iCollection = MMPXCollectionUtility::NewL( this, iMode );
+ }
+
+ // Ask for the total item count
+ // Cache current iPath
+ delete iPath;
+ iPath = NULL;
+ iPath = iCollection->Collection().PathL();
+
+ iCollection->Collection().OpenL();
+ }
+
+// ---------------------------------------------------------------------------
+// Handle the count step
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoHandleCountL(const CMPXMedia& aEntries,
+ TInt aIndex,
+ TInt aError)
+ {
+ ASSERT( iFetchStep == EFetchCount );
+
+ MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleCountL error %i <---", aError);
+ TBool done(EFalse);
+ if( aError == KErrNone )
+ {
+ // Do we support incremental for this OpenL()?
+ //
+ TBool supportIncremental(EFalse);
+ if( aEntries.IsSupported( KMPXCollectionOpenLSupportsIncremental ) )
+ {
+ supportIncremental = aEntries.ValueTObjectL<TBool>(
+ KMPXCollectionOpenLSupportsIncremental );
+ }
+
+ if( supportIncremental )
+ {
+ TInt count(0);
+ if( aEntries.IsSupported(KMPXMediaArrayCount) )
+ {
+ count = aEntries.ValueTObjectL<TInt>(KMPXMediaArrayCount);
+ }
+
+ if( iFetchInfo.iOffset == KErrNotFound )
+ {
+ // If the client did not specify an offset
+ // we use the index the collection is pointing to
+ // as the starting offset
+ //
+ iFetchInfo.iOffset = aIndex;
+ }
+ if( count > 0 )
+ {
+ // Perform the chunking here
+ DoSetupChunksL( count );
+ DoCompactTaskListL( aEntries );
+
+ MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleCountL count %i", iIncrementalChunks.Count() );
+ if( iIncrementalChunks.Count() )
+ {
+ // Start running the fetching algorithm
+ iFetchStep = EFetchItems;
+ iFirstOpen = ETrue;
+
+ // Sync up the path, as there could have been items deleted
+ delete iPath;
+ iPath = NULL;
+ iPath = iCollection->Collection().PathL();
+
+ if( iObs )
+ {
+ iObs->HandleOpenL( aEntries, aIndex, EFalse, aError );
+ }
+ RunNext();
+ }
+ else
+ {
+ // Update index before returning
+ DoSelectIndexL();
+ iFetchStep = EFetchNone;
+ iCollection->Collection().OpenL();
+ done = EFalse;
+ }
+ }
+ else
+ {
+ done = ETrue;
+ }
+ }
+ else // !supportIncremental
+ {
+ // Just return the results
+ //
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleCountL incremental not supported");
+ done = ETrue;
+ }
+
+ }
+ if( (aError != KErrNone) || done )
+ {
+ // Stop the OpenL() operation
+ iFetchStep = EFetchNone;
+ if( iObs )
+ {
+ iObs->HandleOpenL( aEntries, aIndex, ETrue, aError );
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Fetch items step
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoFetchItemsL()
+ {
+ // Construct a command to fetch the next chunk
+ //
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoFetchItemsL <---" );
+ if( iIncrementalChunks.Count() > 0 )
+ {
+ CMPXCommand* command = CMPXCommand::NewL();
+ CleanupStack::PushL( command );
+
+ // Construct the command
+ //
+ TInt colId( iPath->Id(0) );
+ TInt offset( iIncrementalChunks[0].iOffset );
+ command->SetTObjectValueL( KMPXCommandGeneralId,
+ KMPXCommandIdIncrementalOpenL );
+ command->SetTObjectValueL( KMPXCommandGeneralCollectionId,
+ colId );
+ command->SetCObjectValueL(KMPXCollectionCommandIdIncOpenLPath,iPath );
+ command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLOffset,
+ offset );
+ command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLNumItems, iFetchInfo.iSize);
+
+ // If some partial data is available
+ // try to optimize this by using the ascending or decending keys
+ //
+ if( iData )
+ {
+ if( offset-1 > 0 && offset-1 < iData->Count() &&
+ iData->AtL(offset-1)->IsSupported(iKeyAttribute) )
+ {
+ command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLAscDsc, EReadAscending);
+ const TDesC& key = iData->AtL(offset-1)->ValueText(iKeyAttribute);
+ command->SetTextValueL(KMPXCollectionCommandIdIncOpenLKeyItem,key);
+ }
+ else if( offset+iFetchInfo.iSize < iData->Count() &&
+ iData->AtL(offset+iFetchInfo.iSize)->IsSupported(iKeyAttribute) )
+ {
+ command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLAscDsc, EReadDescending);
+ const TDesC& key = iData->AtL(offset+iFetchInfo.iSize)->ValueText(iKeyAttribute);
+ command->SetTextValueL(KMPXCollectionCommandIdIncOpenLKeyItem,key);
+ }
+ }
+
+ // Command sent to the collection, callback HandleCommandComplete()
+ //
+ MPX_DEBUG2("CMPXCollectionOpenUtility::DoFetchItemsL offset %i <---", offset );
+ iFetchStep = EFetchCommand;
+ iCollection->Collection().CommandL( *command );
+ CleanupStack::PopAndDestroy( command );
+ }
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoFetchItemsL --->" );
+ }
+
+// ---------------------------------------------------------------------------
+// Handle Completion of fetch items step
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoHandleFetchItemsL( const CMPXMedia& aEntries,
+ TInt aIndex,
+ TInt aError )
+ {
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL <---" );
+ // Task is done, and compact the list
+ //
+ TInt curOffset(0);
+ if( iIncrementalChunks.Count() )
+ {
+ curOffset = iIncrementalChunks[0].iOffset;
+ iIncrementalChunks.Remove(0);
+ DoCompactTaskListL( aEntries );
+ }
+ else
+ {
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL No more chunks" );
+ }
+
+ TBool complete = iIncrementalChunks.Count() == 0 ? ETrue : EFalse;
+
+ // Keep a reference here
+ //
+ delete iMedia;
+ iMedia = NULL;
+ iMedia = CMPXMedia::NewL( aEntries );
+ iData = NULL;
+ if( aEntries.IsSupported( KMPXMediaArrayContents ) )
+ {
+ iData = aEntries.Value<CMPXMediaArray>( KMPXMediaArrayContents );
+ User::LeaveIfNull(iData);
+ }
+
+ // Run the next step of the fetching algorithm
+ // Do not run if stopped
+ //
+ TInt count(iIncrementalChunks.Count());
+ if( count != 0 && iFetchStep != EFetchNone )
+ {
+ // Update the path, as the item IDs will be filled
+ //
+ MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleFetchItemsL run next %i", count );
+ delete iPath;
+ iPath = NULL;
+ iPath = iCollection->Collection().PathL();
+
+ // Command to fetch next chunk
+ //
+ RunNext();
+ }
+ else
+ {
+ // All done
+ iFetchStep = EFetchNone;
+ }
+
+ // Callback to observer with some treshold to avoid over redrawing
+ // Playlists need every handle open to update the path
+ //
+ if( iObs &&
+ (Abs<TInt>(aIndex-curOffset) < iFetchInfo.iSize ||
+ iFirstOpen || iMode == KMcModePlaylist || complete ) )
+ {
+ iFirstOpen = EFalse;
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL callback" );
+ iObs->HandleOpenL( aEntries, aIndex, complete, aError );
+ }
+
+ MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL -->" );
+ }
+
+// ---------------------------------------------------------------------------
+// Run the next step
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::RunNext()
+ {
+ TCallBack cb( Callback,this );
+ iTimer->Cancel();
+ iTimer->Start( TTimeIntervalMicroSeconds32( iFetchDelay ),
+ TTimeIntervalMicroSeconds32( iFetchDelay ),
+ cb);
+ }
+
+// ---------------------------------------------------------------------------
+// Set some callback
+// ---------------------------------------------------------------------------
+//
+TInt CMPXCollectionOpenUtility::Callback( TAny* aAny )
+ {
+ TRAP_IGNORE( ((CMPXCollectionOpenUtility*)aAny)->HandleCallbackL() );
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// HandleCallback from iTimer
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::HandleCallbackL()
+ {
+ switch( iFetchStep )
+ {
+ case EFetchPath:
+ {
+ iCollection->Collection().OpenL( *iPath );
+ break;
+ }
+ case EFetchCount:
+ {
+ DoFetchCountL();
+ break;
+ }
+ case EFetchItems:
+ {
+ DoFetchItemsL();
+ break;
+ }
+ case EFetchNone:
+ {
+ break; // do nothing
+ }
+ default:
+ {
+ MPX_ASSERT(0);
+ break;
+ }
+ }
+ // Run once only
+ iTimer->Cancel();
+ }
+
+// ---------------------------------------------------------------------------
+// Setup the chunks
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoSetupChunksL( TInt aCount )
+ {
+ // Number of chunks we are going to have
+ // And the chunk the offset is going to be at
+ //
+ iIncrementalChunks.Reset();
+
+ TInt numChunks(0);
+ if( aCount > 0 )
+ {
+ // Truncate and add 1 if any modulus, no Ceil() function
+ numChunks = (TInt)aCount/iFetchInfo.iSize;
+ if( aCount % iFetchInfo.iSize )
+ {
+ numChunks++;
+ }
+ }
+ TInt offSetChunk = (TInt) iFetchInfo.iOffset / iFetchInfo.iSize ;
+
+ // First chunk
+ TMPXOpenDataBlock chunk;
+ chunk.iOffset = offSetChunk*iFetchInfo.iSize;
+ chunk.iSize = iFetchInfo.iSize;
+ iIncrementalChunks.AppendL( chunk );
+
+ // Left and right of the first chunk
+ TInt left = offSetChunk-1;
+ TInt right = offSetChunk+1;
+ TInt count(numChunks-1);
+ while( count > 0 )
+ {
+ // Append Left Chunk
+ //
+ TInt temp(left);
+ if( left < 0 )
+ {
+ // Wrap around to end of the list
+ temp = numChunks + left;
+ }
+ chunk.iOffset = temp*iFetchInfo.iSize;
+ iIncrementalChunks.AppendL( chunk );
+ MPX_DEBUG2("Adding Chunk %i", temp);
+
+ count--;
+ left--;
+
+ // Append Right Chunk
+ if( temp != right%numChunks )
+ {
+ chunk.iOffset = (right%numChunks)*iFetchInfo.iSize;
+ iIncrementalChunks.AppendL( chunk );
+ MPX_DEBUG2("Adding Chunk %i", right%numChunks);
+
+ count--;
+ right++;
+ }
+ }
+
+ // Set the direction and re-order as necessary
+ SetDirection( iFetchDirection );
+ }
+
+// ---------------------------------------------------------------------------
+// Sort the internal array ascending
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoSortAscend( TBool aSkipFirst )
+ {
+ if( iIncrementalChunks.Count() > 0 )
+ {
+ TMPXOpenDataBlock tmp;
+ if( aSkipFirst )
+ {
+ tmp = iIncrementalChunks[0];
+ iIncrementalChunks.Remove(0);
+ }
+ iIncrementalChunks.Sort( CompareAsc );
+
+ if( aSkipFirst )
+ {
+ iIncrementalChunks.Insert( tmp, 0 );
+ }
+ }
+
+#ifdef _DEBUG
+ TInt c=iIncrementalChunks.Count();
+ for( TInt i=0; i<c; ++i )
+ {
+ MPX_DEBUG2("Order %i", iIncrementalChunks[i].iOffset);
+ }
+#endif // _DEBUG
+ }
+
+// ---------------------------------------------------------------------------
+// Sort the internal array decending
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoSortDescend( TBool aSkipFirst )
+ {
+ if( iIncrementalChunks.Count() > 0 )
+ {
+ TMPXOpenDataBlock tmp;
+ if( aSkipFirst )
+ {
+ tmp = iIncrementalChunks[0];
+ iIncrementalChunks.Remove(0);
+ }
+ iIncrementalChunks.Sort( CompareDsc );
+
+ if( aSkipFirst )
+ {
+ iIncrementalChunks.Insert( tmp, 0 );
+ }
+ }
+
+#ifdef _DEBUG
+ TInt c=iIncrementalChunks.Count();
+ for( TInt i=0; i<c; ++i )
+ {
+ MPX_DEBUG2("Order %i", iIncrementalChunks[i].iOffset);
+ }
+#endif // _DEBUG
+ }
+
+// ---------------------------------------------------------------------------
+// Sort the internal array in normal form
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoSortNormalL( TBool aSkipFirst )
+ {
+ DoSortAscend( aSkipFirst );
+
+ RArray<TMPXOpenDataBlock> temp;
+ CleanupClosePushL( temp );
+
+ TBool start = aSkipFirst ? 1:0;
+ TInt count( iIncrementalChunks.Count() );
+ TInt c(count);
+ if( aSkipFirst )
+ {
+ temp.AppendL( iIncrementalChunks[0] );
+ count--;
+ }
+
+ TInt left(iIncrementalChunks.Count()/2);
+ TInt right = left+1;
+ while( count > 0)
+ {
+ if( left>=start )
+ {
+ temp.AppendL( iIncrementalChunks[left] );
+ left--;
+ count--;
+ }
+ if( right<c )
+ {
+ temp.AppendL( iIncrementalChunks[right] );
+ right++;
+ count--;
+ }
+ }
+
+ // Copy the results
+ iIncrementalChunks.Reset();
+ c= temp.Count();
+ for( TInt i=0; i<c; ++i )
+ {
+ iIncrementalChunks.AppendL( temp[i] );
+ }
+ CleanupStack::PopAndDestroy( &temp );
+ }
+
+// ---------------------------------------------------------------------------
+// Compact the internal task list
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoCompactTaskListL( const CMPXMedia& aMedia )
+ {
+ RArray<TMPXOpenDataBlock> datablocks;
+ CleanupClosePushL( datablocks );
+
+ TInt c( iIncrementalChunks.Count() );
+
+ if( aMedia.IsSupported(KMPXCollectionOpenLAllResultRange) )
+ {
+ // De-serialize from global data
+ //
+ const TDesC& buf = aMedia.ValueText(KMPXCollectionOpenLAllResultRange);
+ CBufBase* buffer(NULL);
+ MPXUser::CreateBufferL( buf, buffer );
+ CleanupStack::PushL( buffer );
+ ::CreateFromBufferL( *buffer, datablocks );
+ CleanupStack::PopAndDestroy( buffer );
+
+ // Remove un-necessary fetches
+ TInt c2( datablocks.Count() );
+ for( TInt i=c-1; i>=0; --i )
+ {
+ TMPXOpenDataBlock& chunk = iIncrementalChunks[i];
+ for( TInt j=0; j<c2; ++j )
+ {
+ TMPXOpenDataBlock b = datablocks[j];
+
+ if( chunk.iOffset >= b.iOffset &&
+ chunk.iOffset+chunk.iSize <= b.iOffset+b.iSize )
+ {
+ // Don't need to fetch what is already
+ // available
+ //
+ iIncrementalChunks.Remove( i );
+ break;
+ }
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &datablocks );
+ }
+
+// ---------------------------------------------------------------------------
+// Update the selection index
+// ---------------------------------------------------------------------------
+//
+void CMPXCollectionOpenUtility::DoSelectIndexL()
+ {
+ CMPXCommand* command = CMPXCommand::NewL();
+ CleanupStack::PushL( command );
+
+ // Construct the command
+ //
+ command->SetTObjectValueL( KMPXCommandGeneralId,
+ KMPXCommandIdCollectionSelect );
+ iCollection->Collection().CommandL( *command );
+ iSelecting = ETrue;
+ CleanupStack::PopAndDestroy( command );
+ }
+// END OF FILE