clfwrapper/ClientSrc/CCLFDefaultOperation.cpp
changeset 0 c53acadfccc6
child 14 646a02f170b9
--- /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