diff -r 000000000000 -r ff3acec5bc43 mpxplugins/viewplugins/views/addtracksdialog/src/mpxaddtracksdialog.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpxcommonuihelper.h" +#include "mpxaddtracksdialogcommon.h" +#include "mpxaddtracksdialog.hrh" +#include "mpxaddtracksdialog.h" +#include "mpxaddtrackslistmodel.h" +#include "mpxaddtrackslbxarray.h" +#include + +// 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 + ( sp->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) ); + iOrigNaviPane = iNaviPane->Top(); + + iNaviPane->PushDefaultL(); + + // Backup title pane + iTitlePane = static_cast + ( sp->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) ); + iOrigTitle = iTitlePane->Text()->AllocL(); + + // Backup context pane only if new context icon is created + if ( iNewIcon ) + { + iContextPane = static_cast + ( 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(aMedia.Value( + 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( 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( 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( iListBox->Model() ); + CAknSearchField* tempSearchField = + static_cast( 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( + KMPXMediaGeneralType, EMPXGroup ); + media->SetTObjectValueL( + KMPXMediaGeneralCategory, EMPXSong ); + media->SetTObjectValueL( + KMPXMediaGeneralId, iListModel->TrackIdL( index ) ); + RArray 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( + KMPXMediaGeneralId, iPlaylistId ); + media->SetTObjectValueL( + KMPXMediaGeneralType, EMPXItem ); + media->SetTObjectValueL( + 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 bufSearchText; + TPtr searchText = bufSearchText.Des(); + TBufC 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 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 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( + KMPXMediaGeneralType, EMPXGroup ); + media->SetTObjectValueL( + KMPXMediaGeneralCategory, EMPXArtist ); + RArray 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( KMPXMessageGeneralId ) ); + if ( KMPXMessageGeneral == id ) + { + if( aMessage.ValueTObjectL( KMPXMessageGeneralEvent ) == + TMPXCollectionMessage::EBroadcastEvent ) + { + TInt op( aMessage.ValueTObjectL( 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( 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( + KMPXMediaGeneralType, EMPXGroup ); + media->SetTObjectValueL( + KMPXMediaGeneralCategory, EMPXSong ); + RArray 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( aResults.Value( + 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(aResults.Value( + 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( Control( ESelectionListControl ) ); + CAknFilteredTextListBoxModel* + lbxModel = static_cast( 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* icons = lbxArray->CreateIconArrayL(); + SetIconArrayL( icons ); + + // Set scrollbar + iListBox->CreateScrollBarFrameL( ETrue ); + iListBox->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, + CEikScrollBarFrame::EAuto ); + + // Enable Marquee + static_cast( iListBox )->EnableExtendedDrawingL(); + static_cast( iListBox )->ItemDrawer()-> + ColumnData()->EnableMarqueeL( ETrue ); + + // Enable speed scrolling + iLbxExtFeat = CMPXLbxExtendedFeatures::NewL( iListBox, EFalse ); + iLbxExtFeat->EnableSpeedScrollL( ETrue ); + + CEikStatusPane* statusPane = iAvkonAppUi->StatusPane(); + iNaviPane = static_cast + ( 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 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( lbxArray ); + TRAP_IGNORE( + CArrayPtr* 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( 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