mpxplugins/viewplugins/views/addtracksdialog/src/mpxaddtracksdialog.cpp
changeset 0 ff3acec5bc43
child 2 b70d77332e66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxplugins/viewplugins/views/addtracksdialog/src/mpxaddtracksdialog.cpp	Thu Dec 17 08:45:05 2009 +0200
@@ -0,0 +1,1795 @@
+/*
+* Copyright (c) 2006 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:  Implementation of mpxaddtracksdialogimp
+*
+*/
+
+
+// INCLUDE FILES
+#include <eikclb.h>
+#include <eikclbd.h>
+#include <eikimage.h>
+#include <eiktxlbx.h>
+#include <aknappui.h>
+#include <aknnavi.h>
+#include <aknnavide.h>
+#include <akntitle.h>
+#include <akncontext.h>
+#include <aknlists.h>
+#include <aknsfld.h>
+#include <gulicon.h>
+#include <AknIconArray.h>
+#include <AknIconUtils.h>
+#include <StringLoader.h>
+#include <aknnotewrappers.h>
+#include <e32base.h>
+#include <barsread.h>
+#include <bautils.h>
+#include <aknnavilabel.h>
+#include <data_caging_path_literals.hrh>
+#include <textresolver.h>
+
+#include <mpxlog.h>
+#include <mpxcollectionutility.h>
+#include <mpxcollectionplaylist.h>
+#include <mpxaddtracksdialog.rsg>
+#include <mpxaddtracksdialog.mbg>
+
+#include <mpxcollectionhelperfactory.h>
+#include <mpxcollectionplaylist.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxmedia.h>
+#include <mpxmediamusicdefs.h>
+#include <mpxmediaarray.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxcollectionmessage.h>
+#include <mpxuser.h>
+
+#include "mpxcommonuihelper.h"
+#include "mpxaddtracksdialogcommon.h"
+#include "mpxaddtracksdialog.hrh"
+#include "mpxaddtracksdialog.h"
+#include "mpxaddtrackslistmodel.h"
+#include "mpxaddtrackslbxarray.h"
+#include <mpxlbxextendedfeatures.h>
+
+// CONSTANTS
+const TInt KMPXATMaxExpandedGroupNum = 1;
+
+// Animation timer defined in UI spec
+const TInt KAnimationFrame1Timer = 50000;
+const TInt KAnimationFrame2Timer = 100000;
+const TInt KAnimationFrame3Timer = 100000;
+const TInt KAnimationFrame4Timer = 500000;
+const TInt KAnimationFrameTimerInterval = 1;
+
+const TInt KMaxTitleLength = 261;  // 255 + 6 for tab
+
+_LIT( KMPXAddTracksDialogRscPath, "mpxaddtracksdialog.rsc" );
+_LIT(KMPXSpace," ");
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXAddTracksDialog* CMPXAddTracksDialog::NewL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::NewL" );
+    CMPXAddTracksDialog* self = CMPXAddTracksDialog::NewLC();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXAddTracksDialog* CMPXAddTracksDialog::NewLC()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::NewLC" );
+    CMPXAddTracksDialog* self = new ( ELeave ) CMPXAddTracksDialog();
+    CleanupStack::PushL( self );
+    self->LoadResourceL();
+    self->ConstructL( R_AVKON_SOFTKEYS_EMPTY );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXAddTracksDialog::~CMPXAddTracksDialog()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::~CMPXAddTracksDialog" );
+
+    TRAP_IGNORE( RestorePreviousStatusPaneL() );
+
+    if ( iCollectionUtility )
+        {
+        iCollectionUtility->Close();
+        }
+    if ( iCollectionUiHelper )
+        {
+        iCollectionUiHelper->Close();
+        }
+    if ( iOrigIcon )
+        {
+        delete iOrigIcon;
+        }
+    if ( iNewIcon )
+        {
+        delete iNewIcon;
+        }
+    if ( iLastFindTxt )
+        {
+        delete iLastFindTxt;
+        }
+    iMatchedSongArray.Reset();
+    iMatchedGroupArray.Reset();
+
+    delete iNaviDecorator;
+    delete iOrigTitle;
+    delete iNaviLabelPane;
+    delete iListModel;
+    delete iNoSongText;
+    delete iNoMatchText;
+
+    if( iPeriodic )
+        {
+        delete iPeriodic;
+        }
+    delete iLbxExtFeat;
+
+    if ( iResourceOffset )
+        {
+        iEikonEnv->DeleteResourceFile( iResourceOffset );
+        }
+
+    if ( iCategoryArray )
+        {
+        iCategoryArray->Reset();
+        delete iCategoryArray;
+        }
+
+    if ( iAllSongsArray )
+        {
+        iAllSongsArray->Reset();
+        delete iAllSongsArray;
+        }
+
+    delete iCommonUiHelper;
+    delete iIdle;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::CMPXAddTracksDialog
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMPXAddTracksDialog::CMPXAddTracksDialog():
+    CAknSelectionListDialog( iLastIndex, NULL, 0 ),
+    iAnimIconIndex( 0 ),
+    iSongAllGroupExist( ETrue )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::ConstructL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::ConstructL( TInt aResource )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::ConstructL" );
+    CAknSelectionListDialog::ConstructL( aResource );
+    iCollectionUtility = MMPXCollectionUtility::NewL( this, KMcModeDefault );
+    iCollectionUiHelper = CMPXCollectionHelperFactory::NewCollectionUiHelperL();
+    iCommonUiHelper = CMPXCommonUiHelper::NewL();
+    iNoSongText = StringLoader::LoadL( R_MPX_CUI_CATEGORY_ADDSONGVIEW_LBX_NOSONGTEXT );
+    iNoMatchText = StringLoader::LoadL( R_MPX_CUI_CATEGORY_ADDSONGVIEW_LBX_EMPTYTEXT );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::BackupPreviousStatusPaneL()
+// Backup previous status pane to internal members.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::BackupPreviousStatusPaneL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::BackupPreviousStatusPaneL" );
+    CEikStatusPane* sp = iAvkonAppUi->StatusPane();
+
+    // Backup navi pane
+    iNaviPane = static_cast<CAknNavigationControlContainer*>
+        ( sp->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) );
+    iOrigNaviPane = iNaviPane->Top();
+
+    iNaviPane->PushDefaultL();
+
+    // Backup title pane
+    iTitlePane = static_cast<CAknTitlePane*>
+        ( sp->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) );
+    iOrigTitle = iTitlePane->Text()->AllocL();
+
+    // Backup context pane only if new context icon is created
+    if ( iNewIcon )
+        {
+        iContextPane = static_cast<CAknContextPane*>
+            ( sp->ControlL( TUid::Uid( EEikStatusPaneUidContext ) ) );
+        iOrigIcon = iContextPane->SwapPicture( iNewIcon );
+        iNewIcon = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::RestorePreviousStatusPaneL()
+// Restore previous status pane from internal members.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::RestorePreviousStatusPaneL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::RestorePreviousStatusPaneL" );
+    if ( iOrigTitle )
+        {
+        // Set original title pane
+        iTitlePane->SetTextL( *iOrigTitle );
+        }
+
+    // Set original navi pane
+    iNaviPane->Pop( iNaviLabelPane );
+    if ( iOrigNaviPane )
+        {
+        iNaviPane->PushL( *iOrigNaviPane );
+        }
+    else
+        {
+        iNaviPane->PushDefaultL();
+        }
+
+    // Restore original context icon
+    if ( iOrigIcon )
+        {
+        iNewIcon = iContextPane->SwapPicture( iOrigIcon );
+        iOrigIcon = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::CreateContextIconL()
+// Create context icon for add tracks dialog.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::CreateContextIconL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::CreateContextIconL" );
+    TParse parse;
+    parse.Set( KMPXAddTracksBmpFile, &KDC_APP_RESOURCE_DIR, NULL );
+    TFileName iconFile( parse.FullName() );
+    User::LeaveIfError( MPXUser::CompleteWithDllPath( iconFile ) );
+
+    MAknsSkinInstance* skin( AknsUtils::SkinInstance() );
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* mask = NULL;
+
+    AknsUtils::CreateIconLC(
+            skin,
+            KAknsIIDNone,
+            bitmap,
+            mask,
+            iconFile,
+            EMbmMpxaddtracksdialogQgn_graf_mup_ctx_addsong,
+            EMbmMpxaddtracksdialogQgn_graf_mup_ctx_addsong_mask );
+
+    iNewIcon = new ( ELeave ) CEikImage();
+    iNewIcon->SetPicture( bitmap, mask );
+    iNewIcon->SetPictureOwnedExternally( EFalse );
+
+    CleanupStack::Pop( 2 ); // bitmap, mask
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::UpdateSoftkeyL()
+// Update softkey.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::UpdateSoftkeyL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::UpdateSoftkeyL" );
+    TInt resId( 0 );
+    TInt index = CurrentLbxItemIndex();
+    CAknSearchField* findBox = FindBox();
+    TBool findBoxVisible = ( findBox->IsVisible() ) && ( findBox->IsFocused() );
+
+    MPX_DEBUG2( "CMPXAddTracksDialog::UpdateSoftkeyL index = %d", index);
+
+    iListBox->View()->SetListEmptyTextL(
+        findBoxVisible? *iNoMatchText : *iNoSongText );
+    if ( iListBox->Model()->NumberOfItems() == 0 )
+        {
+        // redraw empty text
+        iListBox->DrawDeferred();
+        }
+
+    if ( index == KErrNotFound )
+        {
+        resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_EMPTY_DONE;
+        if ( findBoxVisible )
+            {
+            resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_EMPTY_CANCEL;
+            }
+        }
+    else
+        {
+        TInt id = iListModel->TrackTypeL( index );
+        if ( id == EMPXGroup )
+            {
+            resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_EXPAND_DONE;
+            if ( findBoxVisible )
+                {
+                resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_EXPAND_CANCEL;
+                }
+            if ( iListModel->IsExpandedIndex( index ) )
+                {
+                resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_COLLAPSE_DONE;
+                if ( findBoxVisible )
+                    {
+                    resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_COLLAPSE_CANCEL;
+                    }
+                }
+            }
+        else
+            {
+            resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_ADD_DONE;
+            if ( findBoxVisible )
+                {
+                resId = R_MPX_CUI_ADDTRACKS_SOFTKEYS_ADD_CANCEL;
+                }
+            }
+        }
+    ButtonGroupContainer().SetCommandSetL( resId );
+    
+    // A temporary RSK command observer is registered so that FindBox 
+    // cannot register its own RSK command observer. This way it will
+    // not handle the RSK but the ProcessCommandL method in this dialog
+    // will do it. The observer must not be removed, because if there 
+    // is no observer registered when the find box is closed, then 
+    // the execution of CAknSearchField::RestorePopupCBA will raise a
+    // panic.
+   	if( !ButtonGroupContainer().UpdatedCommandObserverExists( 
+		CEikButtonGroupContainer::ERightSoftkeyPosition ) )
+   		{
+   		MPX_DEBUG1( "CMPXAddTracksDialog::UpdateSoftkeyL: Adding RSK observer" );
+   		ButtonGroupContainer().UpdateCommandObserverL( 2, *this );
+   		}
+    ButtonGroupContainer().DrawDeferred();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::UpdateListboxByCategoryL()
+// Update listbox content by category.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::UpdateListboxByCategoryL( const CMPXMedia& aMedia  )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::UpdateListboxByCategoryL" );
+    // Reset tracks list
+    iListModel->ResetTracksList();
+
+    // Insert "Songs (all)" to model
+    CMPXMediaArray* media =
+        const_cast<CMPXMediaArray*>(aMedia.Value<CMPXMediaArray>(
+        KMPXMediaArrayContents ) );
+    User::LeaveIfNull( media );
+
+    delete iCategoryArray;
+    iCategoryArray = NULL;
+    iCategoryArray = CMPXMediaArray::NewL();
+    TInt count = media->Count();
+    for ( TInt i = 0; i < count; i++ )
+        {
+        CMPXMedia* orig( media->AtL( i ) );
+        User::LeaveIfNull( orig );
+        CMPXMedia* copy( CMPXMedia::NewL( *orig ) );
+        CleanupStack::PushL( copy );
+        iCategoryArray->AppendL( copy );
+        CleanupStack::Pop( copy );
+        }
+    if ( count > 0 )
+        {
+        // change display text to unknown if the last entry is null
+        CMPXMedia* aryMedia( media->AtL( count - 1 ) );
+        User::LeaveIfNull( aryMedia );
+        if ( aryMedia->ValueText( KMPXMediaGeneralTitle ).Length() == 0 )
+            {
+            HBufC* text = StringLoader::LoadLC(
+                R_MPX_QTN_MP_UNKNOWN );
+            CMPXMedia* catMedia( iCategoryArray->AtL( count - 1 ) );
+            User::LeaveIfNull( catMedia );
+            catMedia->SetTextValueL( KMPXMediaGeneralTitle, *text );
+            aryMedia->SetTextValueL( KMPXMediaGeneralTitle, *text );
+            CleanupStack::PopAndDestroy( text );
+            }
+        CMPXMedia* entry = CMPXMedia::NewL();
+        CleanupStack::PushL( entry );
+        HBufC* string =
+            StringLoader::LoadLC( R_MPX_CUI_ADDSONGS_ADD_ALLSONGS_TXT );
+        entry->SetTextValueL(
+            KMPXMediaGeneralTitle, *string );
+        media->Insert( entry, 0 );
+        CleanupStack::PopAndDestroy( string );
+        CleanupStack::Pop( entry );
+        // Insert artists to model
+        iListModel->InsertGroupsL( *media, -1, EMPXSong );
+        HandleItemArrayChangeL();
+        iSongAllGroupExist = ETrue;
+        }
+    else
+        {
+        MPX_DEBUG1( "CMPXAddTracksDialog::UpdateListboxByCategoryL no song" );
+        // no song
+        iSongAllGroupExist = EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::UpdateListboxByCategoryforFindL()
+// Update listbox content by category after find.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::UpdateListboxByCategoryforFindL(
+    TBool aFind, TInt aSongNum)
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::UpdateListboxByCategoryforFindL" );
+    if( aFind )
+        {
+        if( aSongNum != 0 )
+            {
+            // Insert "Songs (%N)" to list box model, change "%N" to matched songs' number
+            CMPXMediaArray* media = CMPXMediaArray::NewL();
+            CleanupStack::PushL( media );
+            CMPXMedia* entry = CMPXMedia::NewL();
+            CleanupStack::PushL( entry );
+            HBufC* string = string = StringLoader::LoadLC(
+                            R_MPX_CUI_ADDSONGS_ADD_SONGS_NUM_TXT, aSongNum );
+            entry->SetTextValueL( KMPXMediaGeneralTitle, *string );
+            media->AppendL( entry );
+            iListModel->InsertGroupsL( *media, 0, EMPXSong );
+            CleanupStack::PopAndDestroy( string );
+            CleanupStack::Pop( entry );
+            CleanupStack::PopAndDestroy( media );
+            iSongAllGroupExist = ETrue;
+            }
+        else
+            {
+            iSongAllGroupExist = EFalse;
+            }
+
+        // Insert found groups
+        TInt matchedGroupCount = iMatchedGroupArray.Count();
+        if( matchedGroupCount > 0 )
+            {
+            CMPXMediaArray* media = CMPXMediaArray::NewL();
+            CleanupStack::PushL( media );
+            for ( TInt i = 0; i < matchedGroupCount; i++ )
+                {
+                TInt catIndex = iMatchedGroupArray[ i ];
+                CMPXMedia* catMedia( iCategoryArray->AtL( catIndex ) );
+                User::LeaveIfNull( catMedia );
+                CMPXMedia* entry = CMPXMedia::NewL( *catMedia  );
+                CleanupStack::PushL( entry );
+                media->AppendL( entry );
+                CleanupStack::Pop( entry );
+                }
+            if( !iSongAllGroupExist )
+                {
+                iListModel->InsertGroupsL( *media, 0 );
+                }
+            else
+                {
+                iListModel->InsertGroupsL( *media, 1 );
+                }
+            CleanupStack::PopAndDestroy( media );
+            }
+        }
+    else
+        {
+        iListModel->ResetTracksList();
+        }
+
+    HandleItemArrayChangeL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::CurrentLbxItemIndex
+// Gets current listbox item index.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMPXAddTracksDialog::CurrentLbxItemIndex() const
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::CurrentLbxItemIndex" );
+    CTextListBoxModel* lbxModel = iListBox->Model();
+    CAknSearchField* findBox = FindBox();
+    TInt currentItem = iListBox->CurrentItemIndex();
+    TInt count = lbxModel->NumberOfItems();
+
+    // Make sure there's at least one item in the listbox
+    if ( findBox && count )
+        {
+        CAknFilteredTextListBoxModel* filteredLbxModel =
+            static_cast<CAknFilteredTextListBoxModel*>( lbxModel );
+        CAknListBoxFilterItems* filterItems = filteredLbxModel->Filter();
+
+        // Get the real listbox index
+        currentItem = filterItems->FilteredItemIndex( currentItem );
+        }
+    return currentItem;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::CurrentListItemCount
+// Return number of listbox items shown in the current listbox.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMPXAddTracksDialog::CurrentListItemCount() const
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::CurrentListItemCount" );
+    CTextListBoxModel* lbxModel = iListBox->Model();
+    TInt count = lbxModel->NumberOfItems();
+    CAknSearchField* findBox = FindBox();
+
+    if ( findBox && count )
+        {
+        CAknFilteredTextListBoxModel* filteredLbxModel =
+            static_cast<CAknFilteredTextListBoxModel*>( lbxModel );
+        CAknListBoxFilterItems* filterItems = filteredLbxModel->Filter();
+
+        count = filterItems->FilteredNumberOfItems();
+        }
+    return count;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::HandleItemArrayChangeL
+// When you change the list item array you should call this method.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleItemArrayChangeL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::HandleItemArrayChangeL" );
+    TInt currentIdx = iListBox->CurrentItemIndex();
+    TInt topIdx = iListBox->TopItemIndex();
+    CListBoxView* lbxView = iListBox->View();
+    TInt offset =
+        lbxView->NumberOfItemsThatFitInRect( lbxView->ViewRect() ) - 1;
+
+    CAknFilteredTextListBoxModel* lbxModel =
+        static_cast<CAknFilteredTextListBoxModel*>( iListBox->Model() );
+    CAknSearchField* tempSearchField =
+        static_cast<CAknSearchField*>( lbxModel->Filter()->FindBox() );
+    lbxModel->Filter()->SetSearchField( NULL );//for find the items
+    // Update item array
+    iLbxFilterItems->HandleItemArrayChangeL();
+    lbxModel->Filter()->SetSearchField( tempSearchField );// for laylout of list
+
+    TInt itemCount = CurrentListItemCount();
+    if ( itemCount )
+        {
+        TInt lastItemIdx = itemCount - 1;
+        if ( topIdx + offset > lastItemIdx )
+            {
+            topIdx = lastItemIdx - offset;
+            }
+        if ( topIdx < 0 )
+            {
+            topIdx = 0;
+            }
+        if ( currentIdx < 0 )
+            {
+            currentIdx = 0;
+            }
+        if ( currentIdx > lastItemIdx )
+            {
+            currentIdx = lastItemIdx;
+            }
+
+        iListBox->SetTopItemIndex( topIdx );
+        iListBox->SetCurrentItemIndexAndDraw( currentIdx );
+        iListBox->DrawDeferred();
+        }
+    UpdateSoftkeyL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::HighlightListItem
+// Highlight list item.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HighlightListItem( TInt aIndex )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::HighlightListItem" );
+    const TInt KMPItemOffset = 1;
+    TInt itemCount = CurrentListItemCount();
+
+    if ( itemCount )
+        {
+        TInt bottomIdx = iListBox->BottomItemIndex();
+        TInt topIdx = iListBox->TopItemIndex();
+
+        // Rearrange the index if aIndex is the bottom item
+        if ( aIndex == bottomIdx )
+            {
+            TInt lastItemIdx = itemCount - 1;
+            if ( aIndex != lastItemIdx )
+                {
+                topIdx += KMPItemOffset;
+                if ( topIdx > lastItemIdx )
+                    {
+                    topIdx = lastItemIdx;
+                    }
+                }
+            }
+
+        if ( topIdx < 0 )
+            {
+            topIdx = 0;
+            }
+
+        iListBox->SetTopItemIndex( topIdx );
+        iListBox->SetCurrentItemIndexAndDraw( aIndex );
+        iListBox->DrawDeferred();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::ExpandCurrentGroupL()
+// Expand current group.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::ExpandCurrentGroupL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::ExpandCurrentGroupL" );
+    TInt index = -1;
+    if ( iExpandAllSongs )
+        {
+        index = EMPXAddTracksAddAllSongs;
+        }
+    else
+        {
+        index = CurrentLbxItemIndex();
+        }
+    TInt oldIndex = index;
+
+    // Make sure current item is expandable
+    if ( ( index != KErrNotFound ) &&
+        ( iListModel->TrackTypeL( index ) == EMPXGroup ) &&
+        ( !iListModel->IsExpandedIndex( index ) ) )
+        {
+        // Make sure the expanded group count is
+        // under KMPXATMaxExpandedGroupNum.
+        while ( iListModel->ExpandedGroupsCount() >=
+                KMPXATMaxExpandedGroupNum )
+            {
+            // Remove all tracks from the oldest expanded group
+            oldIndex = iListModel->OldestExpandedGroupIndex();
+            TInt count = iListModel->RemoveAllTracksFromGroupL( oldIndex );
+            // Update the index accordingly
+            if ( index > oldIndex )
+                {
+                index -= count;
+                }
+            }
+
+        if ( index == EMPXAddTracksAddAllSongs && iSongAllGroupExist )
+            {
+            if ( iAllSongsArray )
+                {
+                // Insert tracks for all songs
+                iExpandAllSongs = EFalse;
+                TInt matchedSongCount = iMatchedSongArray.Count();
+                if ( matchedSongCount == 0 )
+                    {
+                    iListModel->InsertTracksUnderGroupL( *iAllSongsArray, index );
+                    TInt diff = oldIndex - index;
+                    TInt newCurrentIdx = iListBox->CurrentItemIndex() - diff;
+                    if ( newCurrentIdx < 0 )
+                        {
+                        newCurrentIdx = 0;
+                        }
+                    TInt newTopIdx = iListBox->TopItemIndex() - diff;
+                    if ( newTopIdx < 0 )
+                        {
+                        newTopIdx = 0;
+                        }
+                    iListBox->SetTopItemIndex( newTopIdx );
+                    iListBox->SetCurrentItemIndex( newCurrentIdx );
+                    }
+                else
+                    {
+                    TInt matchedSongCount = iMatchedSongArray.Count();
+                    for ( TInt i = 0; i < matchedSongCount; i++ )
+                        {
+                        TInt songIndex = iMatchedSongArray[ i ];
+                        CMPXMedia* origMedia( iAllSongsArray->AtL( songIndex ) );
+                        User::LeaveIfNull( origMedia );
+                        iListModel->InsertTrackL( *origMedia, index + 1 + i );
+                        }
+                    iListModel->MarkExpandedL( index, matchedSongCount );
+                    }
+                HandleItemArrayChangeL();
+                HighlightListItem( index );
+                UpdateSoftkeyL();
+                }
+            else
+                {
+                MPX_DEBUG1( "CMPXAddTracksDialog::ExpandCurrentGroupL all songs NOT READY" );
+                iExpandAllSongs = ETrue;
+                HBufC* string = StringLoader::LoadLC(
+                    R_MPX_QTN_NMP_NOTE_OPENING );
+                iCommonUiHelper->ShowWaitNoteL( *string,
+                    R_AVKON_SOFTKEYS_EMPTY, EFalse, NULL );
+                CleanupStack::PopAndDestroy( string );
+                }
+            }
+        else
+            {
+            if ( iCurrentOp == EMPXOpIdle )
+                {
+                HandleItemArrayChangeL();
+                HBufC* string = StringLoader::LoadLC(
+                    R_MPX_QTN_NMP_NOTE_OPENING );
+                iCommonUiHelper->ShowWaitNoteL( *string,
+                    R_AVKON_SOFTKEYS_EMPTY, EFalse, NULL );
+                CleanupStack::PopAndDestroy( string );
+                CMPXMedia* media = CMPXMedia::NewL();
+                CleanupStack::PushL( media );
+                media->SetTObjectValueL<TMPXGeneralType>(
+                    KMPXMediaGeneralType, EMPXGroup );
+                media->SetTObjectValueL<TMPXGeneralCategory>(
+                    KMPXMediaGeneralCategory, EMPXSong );
+                media->SetTObjectValueL<TMPXItemId>(
+                    KMPXMediaGeneralId, iListModel->TrackIdL( index ) );
+                RArray<TMPXAttribute> attrs;
+                CleanupClosePushL( attrs );
+                attrs.Append(
+                    TMPXAttribute( KMPXMediaIdGeneral,
+                        EMPXMediaGeneralTitle | EMPXMediaGeneralId
+                        | EMPXMediaGeneralType |  EMPXMediaGeneralCategory |
+                        EMPXMediaGeneralFlags ) );
+                iCurrentOp = EMPXOpGetSongs;
+                iCurrentGroupIndex = index;
+                iCollectionUtility->Collection().FindAllL( *media, attrs.Array(), *this );
+                CleanupStack::PopAndDestroy( &attrs );
+                CleanupStack::PopAndDestroy( media );
+                }
+            else
+                {
+                MPX_DEBUG1( "CMPXAddTracksDialog::ExpandCurrentGroupL find all busy, ignoring" );
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::GotoClosestGroupL()
+// Goto the closest group.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::GotoClosestGroupL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::GotoClosestGroupL" );
+    // Get the closest expanded index
+    TInt origIndex = CurrentLbxItemIndex();
+    if ( origIndex != KErrNotFound )
+        {
+        TInt index = iListModel->ClosestExpandedGroupIdx( origIndex );
+        if ( index != KErrNotFound )
+            {
+            // Highlight on the group
+            HighlightListItem( index );
+
+            UpdateSoftkeyL();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::CollapseCurrentGroupL()
+// Collapse current group.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::CollapseCurrentGroupL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::CollapseCurrentGroupL" );
+    TInt index = CurrentLbxItemIndex();
+
+    if ( ( index != KErrNotFound ) &&
+        ( iListModel->IsExpandedIndex( index ) ) )
+        {
+        // Remove all tracks from this group
+        iListModel->RemoveAllTracksFromGroupL( index );
+
+        // Update listbox and softkey
+        HandleItemArrayChangeL();
+        HighlightListItem( index );
+        UpdateSoftkeyL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::AddCurrentTrackToPlaylistL()
+// Add current track to playlist.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::AddCurrentTrackToPlaylistL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::AddCurrentTrackToPlaylistL" );
+    TInt index = CurrentLbxItemIndex();
+    iSelectIndex = index;
+
+    if ( index != KErrNotFound && iPlaylistId != 0 )
+        {
+        CMPXMedia* media = CMPXMedia::NewL();
+        CleanupStack::PushL( media );
+        media->SetTObjectValueL<TMPXItemId>(
+            KMPXMediaGeneralId, iPlaylistId );
+        media->SetTObjectValueL<TMPXGeneralType>(
+            KMPXMediaGeneralType, EMPXItem );
+        media->SetTObjectValueL<TMPXGeneralCategory>(
+            KMPXMediaGeneralCategory, EMPXPlaylist );
+
+        CMPXMediaArray* mediaArray = CMPXMediaArray::NewL();
+        CleanupStack::PushL( mediaArray );
+        CMPXMedia* song = CMPXMedia::NewL( iListModel->MediaL( index ) );
+        CleanupStack::PushL( song );
+        mediaArray->AppendL( song );
+        CleanupStack::Pop( song );
+        media->SetCObjectValueL( KMPXMediaArrayContents, mediaArray );
+        media->SetTObjectValueL( KMPXMediaArrayCount, 1 );
+        iCollectionUiHelper->AddL( *media, this );
+        CleanupStack::PopAndDestroy( 2, media );
+
+        // Enable animation
+        // Animation icon index is 3 -> 5
+        iAnimIconIndex = CMPXAddTracksLbxArray::EMPXATLbxIconSongAddedAnim1;
+        iListModel->SetAnimationIconNum( iSelectIndex, iAnimIconIndex );
+        HighlightListItem( iSelectIndex );
+
+        // first icon animation
+        if ( iPeriodic->IsActive() )
+            {
+            iPeriodic->Cancel();
+            }
+        iPeriodic->Start( TTimeIntervalMicroSeconds32(KAnimationFrame1Timer),
+                            TTimeIntervalMicroSeconds32(KAnimationFrameTimerInterval),
+                            TCallBack( AnimExpireL, this ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::DoFindL
+// Execute find for group and songs.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::DoFindL( void )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::DoFindL" );
+
+    if ( !iAllSongsArray )
+        {
+        iDoFind = ETrue;
+        HBufC* string = StringLoader::LoadLC(
+            R_MPX_QTN_NMP_NOTE_OPENING );
+        iCommonUiHelper->ShowWaitNoteL( *string,
+            R_AVKON_SOFTKEYS_EMPTY, EFalse, NULL );
+        CleanupStack::PopAndDestroy( string );
+        return;
+        }
+
+    // reset all group to default state
+    iListModel->ResetTracksList();
+
+    iMatchedSongArray.Reset();
+    iMatchedGroupArray.Reset();
+
+    // start find
+    TInt searchTextNum = iLastFindTxt->Length();
+    TInt songAllMatchedNum = 0;
+
+    TBufC<KMaxTitleLength> bufSearchText;
+    TPtr searchText = bufSearchText.Des();
+    TBufC<KMaxTitleLength> bufSearchTextwithSpace;
+    TPtr searchTextwithSpace = bufSearchTextwithSpace.Des();
+    TBool find = EFalse;
+
+
+    // Reset find result
+    iListModel->SetFindSongsFlag( EFalse );
+    // current searching is to compare the text string with list box text
+    // if they are match, means found;otherwise, not found
+    // searching way can be changed if needed
+    if( searchTextNum != 0 )
+        {
+        TInt listCount = iCategoryArray->Count();
+        for( TInt i = 0; i < listCount; i ++ )
+            {
+            CMPXMedia* media( iCategoryArray->AtL( i ) );
+            User::LeaveIfNull( media );
+            const TDesC& constTitle = media->ValueText(
+                KMPXMediaGeneralTitle );
+            TBufC<KMaxTitleLength> titleBuf( constTitle );
+            TPtr title = titleBuf.Des();
+            searchText = iLastFindTxt->Left( searchTextNum );
+
+            title.LowerCase();
+            searchText.LowerCase();
+
+            if( title.Find( KMPXSpace ) != KErrNotFound )
+                {
+                searchTextwithSpace = searchText;
+                // insert space if there is not, to make every search same
+                searchTextwithSpace.Insert( 0, KMPXSpace );
+                }
+
+            // find way: match first several characters, if there is space in the
+            // middle of the track name, match the string also after the space
+            if ( ( ( searchTextwithSpace.Length() > 0 ) &&
+                ( title.Find( searchTextwithSpace ) != KErrNotFound ) ) ||
+                ( title.Left( searchTextNum ) == searchText ) )
+                {
+                iMatchedGroupArray.Append( i );
+                find = ETrue;
+                }
+            }
+
+        TInt songCount = iAllSongsArray->Count();
+        for ( TInt i = 0; i < songCount; i++ )
+            {
+            CMPXMedia* media( iAllSongsArray->AtL( i ) );
+            User::LeaveIfNull( media );
+            const TDesC& constTitle = media->ValueText(
+                KMPXMediaGeneralTitle );
+            TBufC<KMaxTitleLength> titleBuf( constTitle );
+            TPtr title = titleBuf.Des();
+            searchText = iLastFindTxt->Left( searchTextNum );
+
+            title.LowerCase();
+            searchText.LowerCase();
+
+            if( title.Find( KMPXSpace ) != KErrNotFound )
+                {
+                searchTextwithSpace = searchText;
+                // insert space if there is not, to make every search same
+                searchTextwithSpace.Insert( 0, KMPXSpace );
+                }
+
+            // find way: match first several characters, if there is space in the
+            // middle of the track name, match the string also after the space
+            if ( ( ( searchTextwithSpace.Length() > 0 ) &&
+                ( title.Find( searchTextwithSpace ) != KErrNotFound ) ) ||
+                ( title.Left( searchTextNum ) == searchText ) )
+                {
+                // matched songs
+                songAllMatchedNum ++;
+                iMatchedSongArray.Append( i );
+                find = ETrue;
+                iListModel->SetFindSongsFlag( ETrue );
+                }
+            }
+        // update according to searching result
+        UpdateListboxByCategoryforFindL( find, songAllMatchedNum );
+        }
+    else if ( iAllSongsArray->Count() > 0 )
+        {
+        // Songs(All) node is shown
+        iListModel->SetFindSongsFlag( ETrue );
+        CMPXMediaArray* media = CMPXMediaArray::NewL();
+        CleanupStack::PushL( media );
+        CMPXMedia* entry = CMPXMedia::NewL();
+        CleanupStack::PushL( entry );
+        HBufC* string =
+            StringLoader::LoadLC( R_MPX_CUI_ADDSONGS_ADD_ALLSONGS_TXT );
+        entry->SetTextValueL( KMPXMediaGeneralTitle, *string );
+        media->Insert( entry, 0 );
+        CleanupStack::PopAndDestroy( string );
+        CleanupStack::Pop( entry );
+        iListModel->InsertGroupsL( *media, 0, EMPXSong );
+        iListModel->InsertGroupsL( *iCategoryArray, 1 );
+        CleanupStack::PopAndDestroy( media );
+        iSongAllGroupExist = ETrue;
+        HandleItemArrayChangeL();
+        }
+
+    // Always highlight the first item
+    HighlightListItem( 0 );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::DoAnimL
+// Execute animation.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::DoAnimL(void)
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::DoAnimL" );
+    iPeriodic->Cancel();
+
+    // remove animation icon
+    if( iAnimIconIndex ==
+            CMPXAddTracksLbxArray::EMPXATLbxIconSongAddedAnim4 )
+        {
+        return;
+        }
+    iAnimIconIndex ++;
+    iListModel->SetAnimationIconNum( iSelectIndex, iAnimIconIndex );
+    HighlightListItem(iSelectIndex);
+
+    TTimeIntervalMicroSeconds32 interval = 0;
+    if( iAnimIconIndex ==
+                CMPXAddTracksLbxArray::EMPXATLbxIconSongAddedAnim2 )
+        {
+        interval = KAnimationFrame2Timer;
+        }
+    else if(iAnimIconIndex ==
+                CMPXAddTracksLbxArray::EMPXATLbxIconSongAddedAnim3 )
+        {
+        interval = KAnimationFrame3Timer;
+        }
+    else if(iAnimIconIndex ==
+                CMPXAddTracksLbxArray::EMPXATLbxIconSongAddedAnim4 )
+        {
+        interval = KAnimationFrame4Timer;
+        }
+    iPeriodic->Start( interval,
+                    TTimeIntervalMicroSeconds32(KAnimationFrameTimerInterval ),
+                    TCallBack( AnimExpireL, this ) );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::AnimExpireL
+// Animation call back method.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMPXAddTracksDialog::AnimExpireL( TAny* aObject )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::AnimExpireL" );
+    ( ( CMPXAddTracksDialog* )( aObject ) )->DoAnimL();
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::StopAnimL
+// Stop animation.
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::StopAnimL()
+    {
+    if( ( iPeriodic->IsActive() ||
+        iAnimIconIndex ==
+            CMPXAddTracksLbxArray::EMPXATLbxIconSongAddedAnim4 ) )
+        {
+        iAnimIconIndex = 0;
+        iPeriodic->Cancel();
+        iListModel->SetAnimationIconNum( iSelectIndex, 0 );
+        HighlightListItem( iSelectIndex );
+        // restore origional navi pane text
+        iNaviPane->Pop( iNaviLabelPane );
+        iNaviPane->PushDefaultL();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// load resources
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::LoadResourceL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::LoadResourceL" );
+    CCoeEnv* coeEnv = iEikonEnv;
+    TParse parse;
+    parse.Set( KMPXAddTracksDialogRscPath, &KDC_APP_RESOURCE_DIR, NULL );
+    TFileName resourceFile( parse.FullName() );
+    User::LeaveIfError( MPXUser::CompleteWithDllPath( resourceFile ) );
+    BaflUtils::NearestLanguageFile( coeEnv->FsSession(), resourceFile );
+    iResourceOffset = coeEnv->AddResourceFileL( resourceFile );
+    }
+
+// ---------------------------------------------------------------------------
+// start find categories
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::LoadCategoriesL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::LoadCategoriesL" );
+    CMPXMedia* media = CMPXMedia::NewL();
+    CleanupStack::PushL( media );
+    media->SetTObjectValueL<TMPXGeneralType>(
+        KMPXMediaGeneralType, EMPXGroup );
+    media->SetTObjectValueL<TMPXGeneralCategory>(
+        KMPXMediaGeneralCategory, EMPXArtist );
+    RArray<TMPXAttribute> attrs;
+    CleanupClosePushL( attrs );
+    attrs.Append(
+        TMPXAttribute( KMPXMediaIdGeneral,
+            EMPXMediaGeneralTitle | EMPXMediaGeneralId
+            | EMPXMediaGeneralType |  EMPXMediaGeneralCategory |
+            EMPXMediaGeneralFlags ) );
+    iCurrentOp = EMPXOpGetCategory;
+    iCollectionUtility->Collection().FindAllL( *media, attrs.Array(), *this );
+    CleanupStack::PopAndDestroy( &attrs );
+    CleanupStack::PopAndDestroy( media );
+    }
+
+// -----------------------------------------------------------------------------
+// Handle collection message
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::DoHandleCollectionMessageL( const CMPXMessage& aMessage )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::DoHandleCollectionMessageL" );
+    TMPXMessageId id( aMessage.ValueTObjectL<TMPXMessageId>( KMPXMessageGeneralId ) );
+    if ( KMPXMessageGeneral == id )
+        {
+        if( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) ==
+            TMPXCollectionMessage::EBroadcastEvent )
+            {
+            TInt op( aMessage.ValueTObjectL<TInt>( KMPXMessageGeneralType ) );
+            if ( op == EMcMsgUSBMTPEnd || op == EMcMsgRefreshEnd || op == EMcMsgUSBMassStorageEnd )
+                {
+                MPX_DEBUG1( "CMPXAddTracksDialog::DoHandleCollectionMessageL Library updated, reloading" );
+                // library updated, reload
+                LoadCategoriesL();
+                }
+            else if ( op == EMcMsgDiskRemoved )
+                {
+                // since collection view can't close this dialog due to CMPXCollectionViewImp::DoIncrementalOpenL
+                // later, schedule the dialog to be closed by itself
+                iIdle = CIdle::NewL( CActive::EPriorityStandard );
+                iIdle->Start( TCallBack( CMPXAddTracksDialog::DeferredExitCallback, this ) );
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handle collection message
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleCollectionMessage(
+    CMPXMessage* aMessage, TInt aError )
+    {
+    if ( aError == KErrNone && aMessage )
+        {
+        TRAP_IGNORE( DoHandleCollectionMessageL( *aMessage ) );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handles the collection entries being opened. Typically called
+// when client has Open()'d a folder
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleOpenL(
+    const CMPXMedia& /*aEntries*/,
+    TInt /*aIndex*/,
+    TBool /*aComplete*/,
+    TInt /*aError*/ )
+    {
+    // do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handles the collection entries being opened. Typically called
+// when client has Open()'d an item. Client typically responds by
+// 'playing' the item
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleOpenL(
+    const CMPXCollectionPlaylist& /*aPlaylist*/,
+    TInt /*aError*/ )
+    {
+    // do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionObserver
+// Handle collection media
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleCollectionMediaL(
+    const CMPXMedia& aMedia, TInt aError)
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::HandleCollectionMediaL" );
+
+    if ( aError == KErrNone )
+        {
+        iPlaylistId = aMedia.ValueTObjectL<TMPXItemId>( KMPXMediaGeneralId );
+        MPX_DEBUG2( "CMPXAddTracksDialog::HandleCollectionMediaL playlist ID = 0x%x", iPlaylistId.iId1 );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCollectionFindObserver
+// Handle callback for "find" operation
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleFindAllL(
+    const CMPXMedia& aResults, TBool /*aComplete*/, TInt aError )
+    {
+    MPX_DEBUG2( "-->CMPXAddTracksDialog::HandleFindAllL aError = %d", aError );
+
+    if ( aError == KErrNone )
+        {
+        switch ( iCurrentOp )
+            {
+            case EMPXOpGetCategory:
+                {
+                UpdateListboxByCategoryL( aResults );
+                CMPXMedia* media = CMPXMedia::NewL();
+                CleanupStack::PushL( media );
+                media->SetTObjectValueL<TMPXGeneralType>(
+                    KMPXMediaGeneralType, EMPXGroup );
+                media->SetTObjectValueL<TMPXGeneralCategory>(
+                    KMPXMediaGeneralCategory, EMPXSong );
+                RArray<TMPXAttribute> attrs;
+                CleanupClosePushL( attrs );
+                attrs.Append(
+                    TMPXAttribute( KMPXMediaIdGeneral,
+                        EMPXMediaGeneralTitle | EMPXMediaGeneralId
+                        | EMPXMediaGeneralType |  EMPXMediaGeneralCategory
+                        | EMPXMediaGeneralFlags ) );
+                iCurrentOp = EMPXOpGetAllSongs;
+                iCollectionUtility->Collection().FindAllL( *media, attrs.Array(), *this );
+                CleanupStack::PopAndDestroy( &attrs );
+                CleanupStack::PopAndDestroy( media );
+                break;
+                }
+            case EMPXOpGetAllSongs:
+                {
+                delete iAllSongsArray;
+                iAllSongsArray = NULL;
+                CMPXMediaArray* mediaAry(
+                    const_cast<CMPXMediaArray*>( aResults.Value<CMPXMediaArray>(
+                        KMPXMediaArrayContents ) ) );
+                User::LeaveIfNull( mediaAry );
+                iAllSongsArray = CMPXMediaArray::NewL( *mediaAry );
+                iCurrentOp = EMPXOpIdle;
+                if ( iExpandAllSongs )
+                    {
+                    iCommonUiHelper->DismissWaitNoteL();
+                    iDoFind = EFalse;
+                    ExpandCurrentGroupL();
+                    }
+                else if ( iDoFind )
+                    {
+                    iCommonUiHelper->DismissWaitNoteL();
+                    iDoFind = EFalse;
+                    DoFindL();
+                    }
+                break;
+                }
+            case EMPXOpGetSongs:
+                {
+                CMPXMediaArray* media =
+                    const_cast<CMPXMediaArray*>(aResults.Value<CMPXMediaArray>(
+                        KMPXMediaArrayContents ) );
+                User::LeaveIfNull( media );
+                iListModel->InsertTracksUnderGroupL( *media, iCurrentGroupIndex );
+
+                TInt diff = iListModel->OldestExpandedGroupIndex() - iCurrentGroupIndex;
+                TInt newCurrentIdx = iListBox->CurrentItemIndex() - diff;
+                if ( newCurrentIdx < 0 )
+                    {
+                    newCurrentIdx = 0;
+                    }
+                TInt newTopIdx = iListBox->TopItemIndex() - diff;
+                if ( newTopIdx < 0 )
+                    {
+                    newTopIdx = 0;
+                    }
+                iListBox->SetTopItemIndex( newTopIdx );
+                iListBox->SetCurrentItemIndex( newCurrentIdx );
+                HandleItemArrayChangeL();
+                HighlightListItem( iCurrentGroupIndex );
+                UpdateSoftkeyL();
+                iCurrentOp = EMPXOpIdle;
+                iCommonUiHelper->DismissWaitNoteL();
+                break;
+                }
+            default:
+                {
+                iCurrentOp = EMPXOpIdle;
+                break;
+                }
+            }
+        }
+    MPX_DEBUG1( "<--CMPXAddTracksDialog::HandleFindAllL" );
+    }
+
+// ---------------------------------------------------------------------------
+// From MMPXCHelperObserver
+// Handles the completion of adding a playlist event
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleOperationCompleteL( TCHelperOperation /*aOperation*/,
+                                                    TInt aError,
+                                                    void* aArgument )
+    {
+    MPX_DEBUG2("-->CMPXAddTracksDialog::HandleOperationCompleteL error = %d", aError);
+    if ( aError != KErrNone )
+        {
+        StopAnimL();
+        // Fix for err EJKG-7CFD89 & EJKG-7DZGGL 
+        if (aError != KErrNotReady && aError != KErrArgument )
+            {
+            iCommonUiHelper->HandleErrorL( aError );
+            }
+        }
+    else
+        {
+        // Song added text display in navi pane
+        iNaviPane->PushL( *iNaviDecorator );
+        }
+    CMPXMedia* media = (CMPXMedia*) aArgument;
+    delete media;
+    MPX_DEBUG1("<--CMPXAddTracksDialog::HandleOperationCompleteL");
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::PreLayoutDynInitL()
+// Prepare for layout.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::PreLayoutDynInitL()
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::PreLayoutDynInitL" );
+    // Create context icon
+    CreateContextIconL();
+
+    // Backup previous status pane
+    BackupPreviousStatusPaneL();
+
+    // Set new title pane
+    HBufC* title = StringLoader::LoadLC( R_MPX_CUI_ADDSONGS_TITLE );
+    iTitlePane->SetTextL( *title );
+    CleanupStack::PopAndDestroy( title );
+
+    // Set find type
+    CAknSelectionListDialog::PreLayoutDynInitL();
+
+    // Setup listbox content
+    iListBox = static_cast<CEikTextListBox*>( Control( ESelectionListControl ) );
+    CAknFilteredTextListBoxModel*
+    lbxModel = static_cast<CAknFilteredTextListBoxModel*>( iListBox->Model() );
+    iLbxFilterItems = lbxModel->Filter();
+
+    // Initialize last find text
+    iLastFindTxt = HBufC::NewL( 0 );
+
+    // Create tracks list model & listbox array
+    iListModel = CMPXAddTracksListModel::NewL();
+    CMPXAddTracksLbxArray* lbxArray = CMPXAddTracksLbxArray::NewL( iListModel );
+
+    // Set item array to listbox model, transfer ownership
+    CTextListBoxModel* listboxModel = iListBox->Model();
+    listboxModel->SetItemTextArray( lbxArray );
+    listboxModel->SetOwnershipType( ELbmOwnsItemArray );
+
+    // Create and set icon array. Ownership transferred.
+    CArrayPtr<CGulIcon>* icons = lbxArray->CreateIconArrayL();
+    SetIconArrayL( icons );
+
+    // Set scrollbar
+    iListBox->CreateScrollBarFrameL( ETrue );
+    iListBox->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff,
+                                                        CEikScrollBarFrame::EAuto );
+
+    // Enable Marquee
+    static_cast<CEikColumnListBox*>( iListBox )->EnableExtendedDrawingL();
+    static_cast<CEikColumnListBox*>( iListBox )->ItemDrawer()->
+                                                ColumnData()->EnableMarqueeL( ETrue );
+
+    // Enable speed scrolling
+    iLbxExtFeat = CMPXLbxExtendedFeatures::NewL( iListBox, EFalse );
+    iLbxExtFeat->EnableSpeedScrollL( ETrue );
+
+    CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
+    iNaviPane = static_cast<CAknNavigationControlContainer*>
+                ( statusPane->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) );
+    // read the navigation pane text resource
+    HBufC* text = StringLoader::LoadLC( R_MPX_CUI_ADDSONGS_SONG_ADDED );
+    iNaviDecorator = iNaviPane->CreateNavigationLabelL( *text );
+    CleanupStack::PopAndDestroy( text );
+
+    // Animation icon timer
+    iPeriodic = CPeriodic::NewL( CActive::EPriorityIdle );
+
+    // Set empty text
+    iListBox->View()->SetListEmptyTextL( *iNoSongText );
+    iListModel->SetFindSongsFlag( ETrue );
+
+    // get current playlist ID
+    CMPXCollectionPath* cpath = iCollectionUtility->Collection().PathL();
+    CleanupStack::PushL( cpath );
+    cpath->Back();
+    MPX_DEBUG_PATH( *cpath );
+    RArray<TMPXAttribute> attrs;
+    CleanupClosePushL(attrs);
+    attrs.Append( KMPXMediaGeneralId );
+    iCollectionUtility->Collection().MediaL( *cpath, attrs.Array() );
+    CleanupStack::PopAndDestroy( &attrs );
+    CleanupStack::PopAndDestroy( cpath );
+
+    // Update listbox
+    LoadCategoriesL();
+
+    // Update softkey
+    UpdateSoftkeyL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::OkToExitL
+// Check if it's ok to exit.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CMPXAddTracksDialog::OkToExitL( TInt aButtonId )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::OkToExitL" );
+    MPX_DEBUG2( "CMPXAddTracksDialog::OkToExitL aButtonId = 0x%x", aButtonId );
+    TBool retVal = EFalse;
+
+    switch (aButtonId)
+        {
+        case EMPXCmdAddTracksExpand:
+            {
+            ExpandCurrentGroupL();
+            break;
+            }
+        case EMPXCmdAddTracksCollapse:
+            {
+            CollapseCurrentGroupL();
+            break;
+            }
+        case EMPXCmdAddTracksAdd:
+            {
+            // Add track to the playlist
+            AddCurrentTrackToPlaylistL();
+            break;
+            }
+        case EMPXCmdAddTracksDone:
+            {
+            retVal = ETrue;
+            break;
+            }
+        case EMPXCmdAddTracksFindCancel:
+            {
+            CAknSearchField* findBox = FindBox();
+            findBox->MakeVisible( EFalse );
+            findBox->SetFocus( EFalse );
+            TRAP_IGNORE( findBox->ResetL() );
+            iListBox->SetFocus( ETrue );
+            
+            TRect mainPane;
+            AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane );
+            SetSizeAndPosition( mainPane.Size() );
+            break;
+            }
+        default:
+            {
+            retVal = CAknSelectionListDialog::OkToExitL( aButtonId );
+            break;
+            }
+        }
+
+    return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXAddTracksDialog::OfferKeyEventL
+// Handles key-events.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CMPXAddTracksDialog::OfferKeyEventL(
+    const TKeyEvent& aKeyEvent,
+    TEventCode aType )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::OfferKeyEventL" );
+    TKeyResponse res = EKeyWasNotConsumed;
+    TBool updateCBA = EFalse;
+    CAknSearchField* findbox = FindBox();
+
+    if ( aType == EEventKey )
+        {
+        StopAnimL();
+
+        switch ( aKeyEvent.iCode )
+            {
+            case EKeyUpArrow:
+            case EKeyDownArrow:
+                {
+                updateCBA = ETrue;
+                break;
+                }
+            case EKeyLeftArrow:
+                {
+                TInt index = CurrentLbxItemIndex();
+                if ( index != KErrNotFound )
+                    {
+                    if ( iListModel->TrackTypeL( index ) != EMPXGroup )
+                        {
+                        GotoClosestGroupL();
+                        }
+                    else
+                        {
+                        CollapseCurrentGroupL();
+                        }
+                    }
+                res = EKeyWasConsumed;
+                break;
+                }
+            case EKeyRightArrow:
+                {
+                ExpandCurrentGroupL();
+                res = EKeyWasConsumed;
+                break;
+                }
+            case EKeyOK:
+            case EKeyEnter:
+                {
+                // Do the right thing on right item
+                TInt index = CurrentLbxItemIndex();
+                if ( index != KErrNotFound )
+                    {
+                    if ( iListModel->TrackTypeL( index ) == EMPXGroup )
+                        {
+                        if ( iListModel->IsExpandedIndex( index ) )
+                            {
+                            CollapseCurrentGroupL();
+                            }
+                        else
+                            {
+                            ExpandCurrentGroupL();
+                            }
+                        }
+                    else
+                        {
+                        AddCurrentTrackToPlaylistL();
+                        }
+                    }
+                res = EKeyWasConsumed;
+                break;
+                }
+            default:
+                {
+                break;
+                }
+            }
+        }
+    TBool offerEventToBaseClass( EFalse );
+
+    if ( res == EKeyWasNotConsumed )
+        {
+        if ( ( aKeyEvent.iCode == EKeyUpArrow ) ||
+            ( aKeyEvent.iScanCode == EStdKeyUpArrow ) ||
+            ( aKeyEvent.iCode == EKeyDownArrow ) ||
+            ( aKeyEvent.iScanCode == EStdKeyDownArrow ) )
+            {
+            res = iLbxExtFeat->HandleLbxKeyEventL( aKeyEvent, aType );
+            }
+        // handle right soft key
+        else if( findbox->IsVisible() &&
+            ( aKeyEvent.iCode == EKeyDevice1 ||
+              aKeyEvent.iScanCode == EStdKeyDevice1 ) )
+            {
+            StopAnimL();
+            res = EKeyWasConsumed;
+            }
+        else
+            {
+            if ( findbox )
+                {
+                TName text;
+                findbox->GetSearchText( text );
+                updateCBA = ETrue;
+                if ( *iLastFindTxt != text )
+                    {
+                    // Update CBA if find text is changed
+                    delete iLastFindTxt;
+                    iLastFindTxt = NULL;
+                    iLastFindTxt = text.AllocL();
+                    DoFindL();
+                    }
+                if ( iLastFindTxt->Length() == 0 && aKeyEvent.iCode == EKeyBackspace )
+                    {
+                    CAknSearchField* findBox = FindBox();
+                    findBox->MakeVisible( EFalse );
+                    findBox->SetFocus( EFalse );
+                    TRAP_IGNORE( findBox->ResetL() );
+                    iListBox->SetFocus( ETrue );
+                    
+                    TRect mainPane;
+                    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane );
+                    SetSizeAndPosition( mainPane.Size() );
+                    res = EKeyWasConsumed;
+                    }
+                else
+                    {
+                    offerEventToBaseClass = ETrue;
+                    }
+                }
+            else
+                {
+                offerEventToBaseClass = ETrue;
+                }
+            }
+        }
+    if ( updateCBA )
+        {
+        UpdateSoftkeyL();
+        }
+    if ( offerEventToBaseClass )
+        {
+        // this has to be done after cba is updated
+        res = CAknSelectionListDialog::OfferKeyEventL( aKeyEvent, aType );
+        }
+    return res;
+    }
+
+// ---------------------------------------------------------------------------
+// From CCoeControl
+// Handles a change to the control's resources.
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleResourceChange( TInt aType )
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::HandleResourceChange" );
+    CAknSelectionListDialog::HandleResourceChange( aType );
+
+    if ( aType == KEikDynamicLayoutVariantSwitch )
+        {
+        TRect rect;
+        AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, rect );
+        SetRect( rect );
+        }
+
+    if ( aType == KAknsMessageSkinChange )
+        {
+        // Create and set icon array. Ownership transferred.
+        CTextListBoxModel* listboxModel = iListBox->Model();
+        MDesCArray* lbxArray = listboxModel->ItemTextArray();
+        CMPXAddTracksLbxArray* addtracksLbxArray =
+            static_cast<CMPXAddTracksLbxArray*>( lbxArray );
+        TRAP_IGNORE(
+            CArrayPtr<CGulIcon>* icons = addtracksLbxArray->CreateIconArrayL();
+            SetIconArrayL( icons );
+            );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From MEikListBoxObserver
+// Handles listbox events.
+// ---------------------------------------------------------------------------
+//
+void CMPXAddTracksDialog::HandleListBoxEventL(
+    CEikListBox* /*aListBox*/,
+    TListBoxEvent aEventType)
+    {
+    MPX_FUNC( "CMPXAddTracksDialog::HandleListBoxEventL" );
+    StopAnimL();
+    if ( aEventType == EEventEnterKeyPressed || aEventType == EEventItemDoubleClicked
+#ifdef SINGLE_CLICK_INCLUDED
+         || aEventType == EEventItemSingleClicked
+#endif
+        )
+        {
+		// Do the right thing on right item
+		TInt index = CurrentLbxItemIndex();
+		if ( index != KErrNotFound )
+			{
+			if ( iListModel->TrackTypeL( index ) == EMPXGroup )
+				{
+				if ( iListModel->IsExpandedIndex( index ) )
+					{
+					CollapseCurrentGroupL();
+					}
+				else
+					{
+					ExpandCurrentGroupL();
+					}
+				}
+			else
+				{
+				AddCurrentTrackToPlaylistL();
+				}
+			}
+        }
+    else
+	    {
+	    iNaviPane->PushDefaultL();
+        UpdateSoftkeyL();
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// Function called by CIdle to close the dialog itself when collection view
+// can not handle the closing of dialog due to waitnote displayed by
+// CMPXCollectionViewImp::DoIncrementalOpenL
+// ---------------------------------------------------------------------------
+//
+TInt CMPXAddTracksDialog::DeferredExitCallback( TAny* aPtr )
+    { 
+    MPX_DEBUG1( "CMPXAddTracksDialog::DeferredExitCallback" );  
+    CMPXAddTracksDialog* self = 
+        static_cast<CMPXAddTracksDialog*>( aPtr );
+    TRAP_IGNORE( self->TryExitL( EMPXCmdAddTracksDone ) );
+    return KErrNone;
+    }
+
+// ProcessCommandL has been implemented here for the sole
+// of handling RSK command when findbox is shown. For other
+// cases it goes along the same path that is used by hardware
+// keys, e.g. by call to TryToExitL.
+void CMPXAddTracksDialog::ProcessCommandL( TInt aCommandId )
+	{
+	CAknSelectionListDialog::ProcessCommandL( aCommandId );
+	TryExitL( aCommandId );
+	
+	// Check that the dialog is not being closed
+	if( aCommandId != EMPXCmdAddTracksDone )
+		{
+		// Reset view so that all songs are shown
+		TName text;
+		CAknSearchField* findbox = FindBox();
+		if( findbox )
+			{
+			findbox->GetSearchText( text );
+			delete iLastFindTxt;
+			iLastFindTxt = NULL;
+			iLastFindTxt = text.AllocL();
+			DoFindL();
+			HandleItemArrayChangeL();
+			}
+		}
+	}
+//  End of File