--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/clfwrapper/ClientSrc/CCLFDefaultOperation.cpp Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,529 @@
+/*
+* Copyright (c) 2002-2009 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:
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "CCLFDefaultOperation.h"
+#include <MCLFSortingStyle.h>
+#include <MCLFModifiableItem.h>
+#include <ContentListingFactory.h>
+#include <collate.h>
+#include <badesca.h>
+#include "MGDebugPrint.h"
+
+// CONSTANTS
+const TInt KCLFGroupedItemArrayGranularity( 4 );
+const TInt KCLFSortingStyleArrayGranularity( 3 );
+
+// CLASS DECLARATION
+
+/**
+* Internal helper class for sorting
+*/
+class TCLFSortingItem
+ {
+ public:
+ TCLFSortingItem()
+ : iData( KNullDesC ),
+ iIntData( 0 ),
+ iTimeData( 0 ),
+ iItem( NULL )
+ {
+ }
+
+ TPtrC iData;
+ TInt32 iIntData;
+ TTime iTimeData;
+ MCLFItem* iItem;
+ };
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CompareAlphaAscending
+// -----------------------------------------------------------------------------
+//
+TInt CompareAlphaAscending( const TCLFSortingItem& aFirst,
+ const TCLFSortingItem& aSecond )
+ {
+ // get the standard method
+ TCollationMethod m = *Mem::CollationMethodByIndex( 0 );
+ m.iFlags |= TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase;
+ return aFirst.iData.CompareC( aSecond.iData, 3, &m );
+ }
+
+// -----------------------------------------------------------------------------
+// CompareIntAscending
+// -----------------------------------------------------------------------------
+//
+TInt CompareIntAscending( const TCLFSortingItem& aFirst,
+ const TCLFSortingItem& aSecond )
+ {
+ return aFirst.iIntData - aSecond.iIntData;
+ }
+
+// -----------------------------------------------------------------------------
+// CompareTimeAscending
+// -----------------------------------------------------------------------------
+//
+TInt CompareTimeAscending( const TCLFSortingItem& aFirst,
+ const TCLFSortingItem& aSecond )
+ {
+ if ( aFirst.iTimeData > aSecond.iTimeData )
+ {
+ return 1;
+ }
+ else if ( aFirst.iTimeData < aSecond.iTimeData )
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// AppendItemsArrayL
+// -----------------------------------------------------------------------------
+//
+void AppendItemsToArrayL( const TArray<MCLFItem*>& aSourceArray,
+ RPointerArray<MCLFItem>& aDestArray )
+ {
+ const TInt count( aSourceArray.Count() );
+ for( TInt i = 0 ; i < count ; ++i )
+ {
+ aDestArray.AppendL( aSourceArray[ i ] );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// AppendItemsToArrayL
+// append aSourceArray items to aDestArray
+// -----------------------------------------------------------------------------
+//
+void AppendItemsToArrayL( const TArray<MCLFItem*>& aSourceArray,
+ RPointerArray<MCLFItem>& aDestArray,
+ TCLFUndefinedItemPosition aPosition,
+ TInt& aItemIndex,
+ TInt& aLastAddedItemCount )
+ {
+ if( aPosition == ECLFSortingStyleUndefinedFirst )
+ {
+ aItemIndex = aItemIndex - aLastAddedItemCount;
+ }
+
+ aLastAddedItemCount = aSourceArray.Count();
+ for( TInt i = 0 ; i < aLastAddedItemCount ; ++i )
+ {
+ aDestArray.InsertL( aSourceArray[i], aItemIndex );
+ ++aItemIndex;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// AppendSortingItemsArrayL
+// -----------------------------------------------------------------------------
+//
+void AppendSortingItemsToArrayL( const TArray<TCLFSortingItem>& aSourceArray,
+ RPointerArray<MCLFItem>& aDestArray )
+ {
+ const TInt count( aSourceArray.Count() );
+ for( TInt i = 0 ; i < count ; ++i )
+ {
+ aDestArray.AppendL( aSourceArray[i].iItem );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// AppendSortingItemsArrayReverseL
+// -----------------------------------------------------------------------------
+//
+void AppendSortingItemsToArrayReverseL(
+ const TArray<TCLFSortingItem>& aSourceArray,
+ RPointerArray<MCLFItem>& aDestArray )
+ {
+ for( TInt i = aSourceArray.Count() - 1 ; i > -1 ; --i )
+ {
+ aDestArray.AppendL( aSourceArray[i].iItem );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// MakeSortingItemsL
+// Add/Make items to sorting item array and undefined items to
+// undefined item array
+// -----------------------------------------------------------------------------
+//
+void MakeSortingItemsL( RArray<TCLFSortingItem>& aSortingItemArray,
+ RPointerArray<MCLFItem>& aUndefinedItemArray,
+ const TArray<MCLFItem*>& aItemArray,
+ const TArray<TCLFFieldId> aSortFields,
+ TCLFItemDataType aSortingDataType )
+ {
+ MG_DEBUG1( MSI1, "MakeSortingItemsL start" );
+
+ const TInt sortingFieldsCount( aSortFields.Count() );
+ const TInt count( aItemArray.Count() );
+ for( TInt i = 0 ; i < count ; ++i )
+ {
+ MCLFItem* seItem = aItemArray[i];
+ TCLFSortingItem sortingItem;
+ TInt fieldIdIndex( -1 );
+ TInt error( KErrNone );
+ do
+ {
+ ++fieldIdIndex;
+ TCLFFieldId fieldId( aSortFields[fieldIdIndex] );
+ switch( aSortingDataType )
+ {
+ case ECLFItemDataTypeDesC:
+ {
+ error = seItem->GetField( fieldId, sortingItem.iData );
+ break;
+ }
+ case ECLFItemDataTypeTInt32:
+ {
+ error = seItem->GetField( fieldId, sortingItem.iIntData );
+ break;
+ }
+ case ECLFItemDataTypeTTime:
+ default:
+ {
+ error = seItem->GetField( fieldId, sortingItem.iTimeData );
+ break;
+ }
+ }
+ } while( ( error != KErrNone ) &&
+ ( fieldIdIndex < ( sortingFieldsCount - 1 ) ) );
+ if( error == KErrNone )
+ {
+ sortingItem.iItem = seItem;
+ aSortingItemArray.AppendL( sortingItem );
+ }
+ else
+ { // field not found -> undefined item
+ aUndefinedItemArray.AppendL( seItem );
+ }
+ }
+
+ MG_DEBUG1( MSI2, "MakeSortingItemsL end" );
+ }
+
+// -----------------------------------------------------------------------------
+// SortSortingItemsL
+// Select correct sortign operation
+// -----------------------------------------------------------------------------
+//
+void SortSortingItemsL( RArray<TCLFSortingItem>& aItemArray,
+ TCLFItemDataType aSortingDataType )
+ {
+ TLinearOrder<TCLFSortingItem>* sorter = NULL;
+
+ switch ( aSortingDataType )
+ {
+ case ECLFItemDataTypeDesC:
+ {
+ sorter = new ( ELeave ) TLinearOrder<TCLFSortingItem>
+ ( CompareAlphaAscending );
+ break;
+ }
+ case ECLFItemDataTypeTInt32:
+ {
+ sorter = new ( ELeave ) TLinearOrder<TCLFSortingItem>
+ ( CompareIntAscending );
+ break;
+ }
+ case ECLFItemDataTypeTTime:
+ default:
+ {
+ sorter = new ( ELeave ) TLinearOrder<TCLFSortingItem>
+ ( CompareTimeAscending );
+ break;
+ }
+ }
+
+ aItemArray.Sort( *sorter );
+ delete sorter;
+ sorter = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// SortItemsBySortingStyleL
+// sort aItemArray with aSortingStyle
+// add undefined items to aUndefinedItemArray
+// -----------------------------------------------------------------------------
+//
+void SortItemsBySortingStyleL( RPointerArray<MCLFItem>& aItemArray,
+ MCLFSortingStyle& aSortingStyle,
+ RPointerArray<MCLFItem>& aUndefinedItemArray )
+ {
+ RArray<TCLFFieldId> sortingFields;
+ CleanupClosePushL( sortingFields );
+ aSortingStyle.GetFieldsL( sortingFields );
+ const TInt sortingFieldsCount( sortingFields.Count() );
+ if( sortingFieldsCount ) // sort only if there are sorting fields
+ {
+ TCLFItemDataType sortingDataType( aSortingStyle.SortingDataType() );
+
+ RArray<TCLFSortingItem> sortingArray;
+ CleanupClosePushL( sortingArray );
+ MakeSortingItemsL( sortingArray,
+ aUndefinedItemArray,
+ aItemArray.Array(),
+ sortingFields.Array(),
+ sortingDataType );
+
+ SortSortingItemsL( sortingArray, sortingDataType );
+
+ aItemArray.Reset();
+ if( aSortingStyle.Ordering() == ECLFOrderingAscending )
+ {
+ AppendSortingItemsToArrayL( sortingArray.Array(),
+ aItemArray );
+ }
+ else
+ {
+ AppendSortingItemsToArrayReverseL( sortingArray.Array(),
+ aItemArray );
+ }
+
+ CleanupStack::PopAndDestroy( &sortingArray ); // sortingArray.Close
+ }
+ CleanupStack::PopAndDestroy( &sortingFields ); // sortingFields.Close
+ }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::CCLFDefaultOperation
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CCLFDefaultOperation::CCLFDefaultOperation()
+ : iSortingStyle( NULL ),
+ iSortingStyleArray( KCLFSortingStyleArrayGranularity ),
+ iGrouping( ECLFNoGrouping ),
+ iGroupedItemList( KCLFGroupedItemArrayGranularity )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCLFDefaultOperation* CCLFDefaultOperation::NewL()
+ {
+ return new( ELeave ) CCLFDefaultOperation;
+ }
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::NewL
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CCLFDefaultOperation::~CCLFDefaultOperation()
+ {
+ iGroupedItemList.ResetAndDestroy();
+ iSortingStyleArray.Close();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::SetSortingStyle
+// -----------------------------------------------------------------------------
+//
+void CCLFDefaultOperation::SetSortingStyle( MCLFSortingStyle* aSortingStyle )
+ {
+ iSortingStyle = aSortingStyle;
+ iSortingStyleArray.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::AppendSortingStyleL
+// -----------------------------------------------------------------------------
+//
+void CCLFDefaultOperation::AppendSortingStyleL(
+ MCLFSortingStyle& aSortingStyle )
+ {
+ iSortingStyleArray.AppendL( &aSortingStyle );
+ }
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::SetGrouping
+// -----------------------------------------------------------------------------
+//
+void CCLFDefaultOperation::SetGrouping( TCLFGrouping aGrouping )
+ {
+ iGrouping = aGrouping;
+ }
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::FilterItemsL
+// -----------------------------------------------------------------------------
+//
+void CCLFDefaultOperation::FilterItemsL( const TArray<MCLFItem*>& aItemList,
+ RPointerArray<MCLFItem>& aFilteredItemList )
+ {
+ AppendItemsToArrayL( aItemList, aFilteredItemList );
+ }
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::GroupItemsL
+// -----------------------------------------------------------------------------
+//
+void CCLFDefaultOperation::GroupItemsL( const TArray<MCLFItem*>& aSourceList,
+ RPointerArray<MCLFItem>& aGroupedList )
+ {
+ MG_DEBUG1( GI1, "CCLFDefaultOperation::GroupItemsL start" );
+
+ iGroupedItemList.ResetAndDestroy();
+ switch ( iGrouping )
+ {
+ case ECLFMusicAlbumGrouping:
+ {
+ DoMusicAlbumGroupingL( aSourceList, aGroupedList );
+ break;
+ }
+ case ECLFNoGrouping:
+ default:
+ {
+ AppendItemsToArrayL( aSourceList, aGroupedList );
+ break;
+ }
+ }
+
+ MG_DEBUG1( GI2, "CCLFDefaultOperation::GroupItemsL end" );
+ }
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::SortItemsL
+// -----------------------------------------------------------------------------
+//
+void CCLFDefaultOperation::SortItemsL( RPointerArray<MCLFItem>& aItemArray )
+ {
+ if( iSortingStyle )
+ {
+ RPointerArray<MCLFItem> array;
+ CleanupClosePushL( array );
+ RPointerArray<MCLFItem> array1;
+ CleanupClosePushL( array1 );
+ RPointerArray<MCLFItem>* undefinedItemArray = &array;
+ RPointerArray<MCLFItem>* newUndefinedItemArray = &array1;
+
+ SortItemsBySortingStyleL( aItemArray,
+ *iSortingStyle,
+ *undefinedItemArray );
+ TInt lastAddedItemCount( aItemArray.Count() );
+ TInt nextItemIndex( lastAddedItemCount );
+ TCLFUndefinedItemPosition position(
+ iSortingStyle->UndefinedItemPosition() );
+
+ const TInt secondarySorterCount( iSortingStyleArray.Count() );
+ for( TInt i = 0 ; i < secondarySorterCount ; ++i )
+ {
+ MCLFSortingStyle& sortingStyle = *iSortingStyleArray[i];
+
+ newUndefinedItemArray->Reset();
+ // sort undefined items
+ SortItemsBySortingStyleL( *undefinedItemArray,
+ sortingStyle,
+ *newUndefinedItemArray );
+
+ // append sorted items to aItemArray
+ AppendItemsToArrayL( undefinedItemArray->Array(),
+ aItemArray,
+ position,
+ nextItemIndex,
+ lastAddedItemCount );
+
+
+ position = sortingStyle.UndefinedItemPosition();
+
+ // change pointers
+ RPointerArray<MCLFItem>* tmp = undefinedItemArray;
+ undefinedItemArray = newUndefinedItemArray;
+ newUndefinedItemArray = tmp;
+ }
+
+
+ // copy rest undefined items to correct position
+ AppendItemsToArrayL( undefinedItemArray->Array(),
+ aItemArray,
+ position,
+ nextItemIndex,
+ lastAddedItemCount );
+
+ // close undefined arrays
+ CleanupStack::PopAndDestroy( 2, &array );
+ }
+ // else no sorting
+ }
+
+
+// -----------------------------------------------------------------------------
+// CCLFDefaultOperation::DoMusicAlbumGroupingL
+// -----------------------------------------------------------------------------
+//
+void CCLFDefaultOperation::DoMusicAlbumGroupingL(
+ const TArray<MCLFItem*>& aSourceList,
+ RPointerArray<MCLFItem>& aGroupedList )
+ {
+ MG_DEBUG1( DMAG1, "CCLFDefaultOperation::DoMusicAlbumGroupingL start" );
+
+ CDesCArray* tempAlbumNameArray =
+ new (ELeave) CDesCArraySeg( KCLFGroupedItemArrayGranularity );
+ CleanupStack::PushL( tempAlbumNameArray );
+
+ const TInt count( aSourceList.Count() );
+ for( TInt i = 0 ; i < count ; ++i )
+ {
+ const MCLFItem* item = aSourceList[i];
+ TPtrC albumName;
+ if( item->GetField( ECLFFieldIdAlbum, albumName ) == KErrNone )
+ {
+ TInt pos( 0 );
+ if( tempAlbumNameArray->Find( albumName, pos ) )
+ {
+ // not found
+ tempAlbumNameArray->AppendL( albumName );
+
+ // make new item
+ MCLFModifiableItem* newItem =
+ ContentListingFactory::NewModifiableItemLC();
+ newItem->AddFieldL( ECLFFieldIdAlbum, albumName );
+ iGroupedItemList.AppendL( newItem ); // takes ownership
+ CleanupStack::Pop(); // newItem
+
+ TPtrC artistName;
+ if( item->GetField( ECLFFieldIdArtist, artistName ) == KErrNone )
+ {
+ newItem->AddFieldL( ECLFFieldIdArtist, artistName );
+ }
+
+ // add new item to grouper list
+ aGroupedList.AppendL( newItem );
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy( tempAlbumNameArray );
+
+ MG_DEBUG1( DMAG2, "CCLFDefaultOperation::DoMusicAlbumGroupingL end" );
+ }
+
+// End of File