--- /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