mpviewplugins/mpcollectionviewplugin/src/mpcollectionview.cpp
branchRCL_3
changeset 52 14979e23cb5e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpviewplugins/mpcollectionviewplugin/src/mpcollectionview.cpp	Tue Aug 31 15:12:29 2010 +0300
@@ -0,0 +1,1342 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Music Player collection view.
+*
+*/
+
+// INCLUDE FILES
+#include <time.h>
+#include <cstdlib>
+#include <QtCore>
+
+#include <hbinstance.h>
+#include <hbapplication.h>
+#include <hbaction.h>
+#include <hbtoolbar.h>
+#include <hbmenu.h>
+#include <hbmessagebox.h>
+#include <hblabel.h>
+#include <hblistview.h>
+#include <hbscrollbar.h>
+#include <hbstyleloader.h>
+
+#include "mpcollectionview.h"
+#include "mpcollectiondocumentloader.h"
+#include "mpcollectioncontainerfactory.h"
+#include "mpcollectioncontainer.h"
+#include "mpcollectiondatamodel.h"
+#include "mpenginefactory.h"
+#include "mpmpxcollectiondata.h"
+#include "mpnowplayingwidget.h"
+#include "mpcommondefs.h"
+#include "mptrace.h"
+#include "mpsnapshotwidget.h"
+#include "mpsettingsmanager.h"
+#include "mpcollectionlistcontainer.h"
+#include "mpcollectionpopuphandler.h"
+
+
+const char*MUSIC_COLLECTION_DOCML = ":/docml/musiccollection.docml";
+
+const char*CONTAINER_EFFECT_GROUP = "mpcontainer";
+
+const char*SHOW_EFFECT = "show";
+const char*HIDE_EFFECT = "hide";
+const char*SHOW_BACK_EFFECT = "show_back";
+const char*HIDE_BACK_EFFECT = "hide_back";
+
+const char*SHOW_EFFECT_RESOURCE_NAME = "view_show_normal";
+const char*HIDE_EFFECT_RESOURCE_NAME = "view_hide_normal";
+const char*SHOW_BACK_EFFECT_RESOURCE_NAME = "view_show_back";
+const char*HIDE_BACK_EFFECT_RESOURCE_NAME = "view_hide_back";
+
+const char*EFFECT_TARGET_SNAPSHOT = "snapshot";
+const char*EFFECT_TARGET_CONTAINER = "container";
+
+const int KMainToolBarAll = 0;
+const int KMainToolBarArtists = 1;
+const int KMainToolBarAlbums = 2;
+const int KMainToolBarPlaylists = 3;
+
+const int KPlaylistToolBarAdd = 0;
+const int KPlaylistToolBarRemove = 1;
+const int KplaylistToolBarReorder = 2;
+
+/*!
+    \class MpCollectionView
+    \brief Music Player collection view.
+
+    Collection view provides access to music collection in the device.
+    This class owns the menu and the toolbar. In addition, it is
+    responsible for creating UI containers and the underlying engine
+    components and connecting them to work together.
+*/
+
+/*!
+    \fn void command( int command )
+
+    This signal is emitted when the view issues a \a command to the
+    application such as request to switch to a different view.
+ */
+
+/*!
+ Constructs the collection view.
+ */
+MpCollectionView::MpCollectionView()
+    : mCollectionContext( ECollectionContextUnknown ),
+      mMpEngine( 0 ),
+      mContainerFactory( 0 ),
+      mCollectionContainer( 0 ),
+      mCollectionDataModel( 0 ),
+      mActivated( false ),
+      mNowPlayingBanner( 0 ),
+      mBannerAttached( false ),
+      mSoftKeyQuit( 0 ),
+      mSoftKeyBack( 0 ),
+      mShuffleAction( 0 ),
+      mShuffleEnabled( false ),
+      mDocumentLoader( 0 ),
+      mMainContainer( 0 ),
+      mMainToolBar( 0 ),
+      mPlaylistToolBar( 0 ),
+      mSnapshot( 0 ),
+      mActivationWaiting( false ),
+      mMpPopupHandler( 0 ),
+      mUsbBlocked( false )
+{
+    TX_LOG
+}
+
+/*!
+ Destructs the collection view.
+ */
+MpCollectionView::~MpCollectionView()
+{
+    TX_ENTRY
+    delete mSnapshot;
+    delete mSoftKeyQuit;
+    delete mSoftKeyBack;
+
+    HbToolBar *toolBar = takeToolBar();
+    if ( mMainToolBar != toolBar && mPlaylistToolBar != toolBar ) {
+        delete toolBar;
+    }
+    if ( mMainToolBar ) {
+        mMainToolBar->deleteLater();
+    }
+    if ( mPlaylistToolBar ) {
+        mPlaylistToolBar->deleteLater();
+    }
+
+    delete mCollectionContainer;
+    delete mContainerFactory;
+    delete mCollectionDataModel;
+    delete mDocumentLoader;
+    TX_EXIT
+}
+
+/*!
+ Initializes the collection view. Allocates all resources needed by the view.
+ */
+void MpCollectionView::initializeView()
+{
+    TX_ENTRY
+
+    mWindow = mainWindow();
+
+    // Create softkey actions
+    mSoftKeyQuit = new HbAction( Hb::QuitNaviAction, this );
+    connect( mSoftKeyQuit, SIGNAL( triggered() ), 
+	         this, SLOT( back() ) );
+
+    mSoftKeyBack = new HbAction( Hb::BackNaviAction, this );
+    connect( mSoftKeyBack, SIGNAL( triggered() ), 
+	         this, SLOT( back() ) );
+
+    mMpEngine = MpEngineFactory::sharedEngine();
+
+    connect( mMpEngine, SIGNAL( collectionPlaylistOpened() ),
+            this, SLOT( startPlaybackView() ) );
+    connect( mMpEngine, SIGNAL( playlistSaved( bool ) ),
+            this, SLOT( playlistSaved( bool ) ) );
+    connect( mMpEngine, SIGNAL( songsDeleted( bool ) ),
+            this, SLOT( songsDeleted( bool ) ) );
+    connect( mMpEngine, SIGNAL( playlistsRenamed( bool ) ),
+            this, SLOT( playlistsRenamed( bool ) ) );
+    connect( mMpEngine, SIGNAL( isolatedCollectionOpened( MpMpxCollectionData* ) ),
+            this, SLOT( handleIsolatedCollectionOpened( MpMpxCollectionData* ) ) );
+
+    mCollectionData = mMpEngine->collectionData();
+    qRegisterMetaType<TCollectionContext>("TCollectionContext");
+    connect( mCollectionData, SIGNAL( contextChanged( TCollectionContext ) ), 
+             this, SLOT( setContext( TCollectionContext ) ), 
+			 Qt::QueuedConnection );
+    mCollectionDataModel = new MpCollectionDataModel( mCollectionData , mMpEngine->playbackData());
+    
+    connect( mCollectionDataModel, SIGNAL( dataReloaded() ),
+             this, SLOT( containerDataChanged() ) );
+
+    mDocumentLoader = new MpCollectionDocumentLoader();
+    bool ok = false;
+    mDocumentLoader->load( MUSIC_COLLECTION_DOCML, &ok );
+    if ( ok ) {
+        QGraphicsWidget *widget;
+
+        widget = mDocumentLoader->findWidget( QString( "nowPlaying" ) );
+        mNowPlayingBanner = qobject_cast<MpNowPlayingWidget*>( widget );
+
+        if ( mViewMode == MpCommon::FetchView ) {
+            // Banner is not needed since playback is stopped when returning
+            // from playback preview. Disable the banner from updating.
+            mNowPlayingBanner->setEnabled( false );
+            attachNowPlayingBanner( false );
+        }
+        else {
+            connect( mNowPlayingBanner, SIGNAL( clicked() ), 
+				     this, SLOT( startPlaybackView() ) );
+            connect( mNowPlayingBanner, SIGNAL( playbackAttachmentChanged( bool ) ),
+                     this, SLOT( attachNowPlayingBanner( bool ) ) );
+            attachNowPlayingBanner( mNowPlayingBanner->isBannerAttached() );
+        }
+
+        widget = mDocumentLoader->findWidget( QString( "mainContainer" ) );
+        mMainContainer = qobject_cast<HbWidget*>( widget );
+
+        setWidget( mMainContainer );
+
+        HbEffect::add(
+            QStringList() << CONTAINER_EFFECT_GROUP << CONTAINER_EFFECT_GROUP << CONTAINER_EFFECT_GROUP << CONTAINER_EFFECT_GROUP,
+            QStringList() << SHOW_EFFECT_RESOURCE_NAME <<  HIDE_EFFECT_RESOURCE_NAME << SHOW_BACK_EFFECT_RESOURCE_NAME << HIDE_BACK_EFFECT_RESOURCE_NAME,
+            QStringList() << SHOW_EFFECT << HIDE_EFFECT << SHOW_BACK_EFFECT << HIDE_BACK_EFFECT);
+
+
+    }
+    else {
+        TX_LOG_ARGS( "Error: invalid xml file." );
+        Q_ASSERT_X( ok, "MpCollectionView::initializeView", "invalid xml file" );
+    }
+
+    // Load custom tbone css here so we do it only once.
+    HbStyleLoader::registerFilePath(":/css/tbonemediawall.css");
+    HbStyleLoader::registerFilePath(":/css/tbonemediawall_color.css");
+    HbStyleLoader::registerFilePath(":/css/tbonemediawall.hgmediawall.widgetml");
+        
+    mContainerFactory = new MpCollectionContainerFactory( this, mDocumentLoader );
+    
+    mMpPopupHandler = new MpCollectionPopupHandler( this );
+
+    connect( mMpEngine, SIGNAL( usbBlocked(bool) ),
+             this, SLOT( handleUsbBlocked(bool) ) );
+    connect( mMpEngine, SIGNAL( libraryAboutToUpdate() ),
+             this, SLOT( handleLibraryAboutToUpdate() ) );
+    connect( mMpEngine, SIGNAL( libraryUpdated() ),
+             this, SLOT( handleLibraryUpdated() ) );
+    mUsbBlocked = mMpEngine->verifyUsbBlocking();
+
+    if ( MpSettingsManager::firstStartup() ) {
+        mActivationWaiting = true;
+        mMpEngine->refreshLibrary( true );
+    }
+
+    TX_EXIT
+}
+
+/*!
+ Activates the collection view.
+ */
+void MpCollectionView::activateView()
+{
+    if ( mActivationWaiting ) {
+        return;
+    }
+    mActivated = true;
+    TX_ENTRY_ARGS( "mCollectionContext=" << mCollectionContext );
+    if ( mCollectionContext == ECollectionContextUnknown ) {
+        // Open 'All Songs' by default
+        if ( mCollectionData->context() == ECollectionContextAllSongs ){
+            setContext( ECollectionContextAllSongs );
+        }
+        else {
+            mMpEngine->openCollection( ECollectionContextAllSongs );
+        }
+    }
+    else {
+        // This true when returning from other views, e.g. playback view
+        setSoftkey();
+    }
+    TX_EXIT
+}
+
+/*!
+ Deactivates the collection view.
+ */
+void MpCollectionView::deactivateView()
+{
+    TX_ENTRY
+    mActivated = false;
+
+    closeActiveDialog( true );
+
+    setNavigationAction( 0 );
+    TX_EXIT
+}
+
+/*!
+ Returns view activation status.
+ */
+bool MpCollectionView::isActivated()
+{
+    TX_LOG_ARGS( "View activated = " << mActivated );
+    return mActivated;
+}
+
+/*!
+ Opens or plays an item through collection container in order to keep track of the Artist / Album data used by infobar.
+ */
+void MpCollectionView::openItem( int index )
+{
+    TX_ENTRY_ARGS( "index = " << index );
+    QModelIndex modelIndex;
+    modelIndex = mCollectionDataModel->index( index );
+    qobject_cast<MpCollectionListContainer*>(mCollectionContainer)->itemActivated( modelIndex );
+    TX_EXIT
+}
+
+/*!
+ Shows the detailed metadata information for the song with \a index.
+ It activates details view.
+ */
+void MpCollectionView::showItemDetails( int index )
+{
+    TX_ENTRY_ARGS( "index = " << index );
+    mMpEngine->retrieveSongDetails( index );
+    emit command( MpCommon::ActivateDetailsView );
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when collection context is changed as a result of Open
+ operation.
+ */
+void MpCollectionView::setContext( TCollectionContext context )
+{
+    TX_ENTRY_ARGS( "context=" << context );
+    if ( mActivated ) {
+        startContainerTransition( mCollectionContext, context );
+    }
+
+    mCollectionContext = context;
+    // Reset softkey and the menu
+    if ( mActivated ) {
+        setSoftkey();
+    }
+
+    // Close any possible popup already launched with previous context
+    closeActiveDialog();
+
+    updateToolBar();
+    updateMenu();
+
+    mCollectionContainer = mContainerFactory->createContainer( context );
+    mCollectionContainer->setViewMode( mViewMode );
+    mCollectionDataModel->refreshModel();
+    mCollectionContainer->setDataModel( mCollectionDataModel );
+
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when 'All Songs' action is triggered from the toolbar.
+ */
+void MpCollectionView::openSongs()
+{
+    TX_ENTRY
+    if ( mCollectionContext != ECollectionContextAllSongs ) {
+        mMpEngine->openCollection( ECollectionContextAllSongs );
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when 'Artists' action is triggered from the toolbar.
+ */
+void MpCollectionView::openArtists()
+{
+    TX_ENTRY
+    if ( mCollectionContext != ECollectionContextArtists ) {
+        mMpEngine->openCollection( ECollectionContextArtists );
+    }
+    TX_EXIT
+}
+
+
+/*!
+ Slot to be called when 'Albums' action is triggered from the toolbar.
+ */
+void MpCollectionView::openAlbums()
+{
+    TX_ENTRY
+    if ( mCollectionContext != ECollectionContextAlbums ) {
+        mMpEngine->openCollection( ECollectionContextAlbums );
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when 'Playlists' action is triggered from the toolbar.
+ */
+void MpCollectionView::openPlaylists()
+{
+    TX_ENTRY
+    if ( mCollectionContext != ECollectionContextPlaylists) {
+        mMpEngine->openCollection( ECollectionContextPlaylists );
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when 'Find' action is triggered from the toolbar.
+ */
+void MpCollectionView::find()
+{
+    // Todo
+    HbMessageBox *messageBox = new HbMessageBox( "Not ready!", HbMessageBox::MessageTypeInformation );
+    messageBox->setAttribute( Qt::WA_DeleteOnClose );
+    messageBox->show();
+    updateToolBar();
+}
+
+/*!
+ Slot to be called when 'Music Store' action is triggered from the toolbar.
+ */
+void MpCollectionView::openMusicStore()
+{
+    // Todo
+    HbMessageBox *messageBox = new HbMessageBox( "Not ready!", HbMessageBox::MessageTypeInformation );
+    messageBox->setAttribute( Qt::WA_DeleteOnClose );
+    messageBox->show();
+    updateToolBar();
+}
+
+/*!
+ Slot to be called when an item is selected by the user.
+ */
+void MpCollectionView::openIndex( int index )
+{
+    TX_ENTRY_ARGS( "index=" << index );
+    bool doOpen = true;
+    if ( mViewMode == MpCommon::FetchView ) {
+        QString songUri;
+        switch ( mCollectionContext ) {
+            case ECollectionContextAllSongs:
+            case ECollectionContextArtistAllSongs:
+            case ECollectionContextPlaylistSongs:
+                doOpen = false;
+                if (!mCollectionData->hasItemProperty(index, MpMpxCollectionData::Corrupted)) {
+                    songUri = mCollectionData->itemData( index, MpMpxCollectionData::Uri );
+                    emit songSelected( songUri );
+                    }
+                else {
+                    showCorruptedNote();
+                }
+                break;
+            case ECollectionContextArtistAlbumsTBone:
+            case ECollectionContextAlbumsTBone:
+                doOpen = false;
+                if (!mCollectionData->hasAlbumSongProperty(index, MpMpxCollectionData::Corrupted)) {
+                    songUri = mCollectionData->albumSongData( index, MpMpxCollectionData::Uri );
+                    emit songSelected( songUri );
+                    }
+                else {
+                    showCorruptedNote();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    if ( doOpen ) {
+        if ( mCollectionContext == ECollectionContextArtistAlbums ) {
+            if ( (mCollectionData->count() > 1) && (index == 0) ) {
+                mMpEngine->openCollectionItem( index );
+            }
+            else {
+                // Artist-Album view going into T-bone. We don't actually open the
+                // collection. Just fake an open.
+                mCollectionData->setContext( ECollectionContextArtistAlbumsTBone );
+            }
+        }
+        else if ( mCollectionContext == ECollectionContextAlbums ) {
+            // Album view going into T-bone. We don't actually open the
+            // collection. Just fake an open.
+            mCollectionData->setContext( ECollectionContextAlbumsTBone );
+        }
+        else {
+            switch ( mCollectionContext ) {
+                case ECollectionContextAllSongs:
+                case ECollectionContextArtistAllSongs:
+                case ECollectionContextPlaylistSongs:
+                    if (!mCollectionData->hasItemProperty(index, MpMpxCollectionData::Corrupted)) {
+                        mMpEngine->openCollectionItem( index );
+                        }
+                    else {
+                        showCorruptedNote();
+                    }
+                    break;
+                case ECollectionContextArtists:
+                case ECollectionContextPlaylists:
+                    mMpEngine->openCollectionItem( index );
+                default:
+                    break;
+            }
+        }
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when an album is centered in T-Bone view and we need to
+ find the songs beloging to album with \a index.
+ */
+void MpCollectionView::findAlbumSongs( int index )
+{
+    TX_ENTRY_ARGS( "index=" << index );
+    mMpEngine->findAlbumSongs(index);
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when a song is selected in T-Bone view and we need to
+ play album with \a albumIndex starting with the songs with \a songIndex.
+ */
+void MpCollectionView::playAlbumSongs( int albumIndex, int songIndex )
+{
+    TX_ENTRY_ARGS( "albumIndex=" << albumIndex << "songIndex=" << songIndex );
+    if (!mCollectionData->hasAlbumSongProperty(songIndex, MpMpxCollectionData::Corrupted)) {
+        mMpEngine->playAlbumSongs(albumIndex, songIndex);
+    }
+    else {
+        showCorruptedNote();
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when back/quit softkey is pressed.
+ */
+void MpCollectionView::back()
+{
+    TX_ENTRY_ARGS( "mCollectionContext=" << mCollectionContext );
+    bool doExit( false );
+    switch ( mCollectionContext ) {
+        case ECollectionContextAllSongs:
+        case ECollectionContextArtists: 
+        case ECollectionContextAlbums:
+        case ECollectionContextPlaylists:
+            // Exit from these levels.
+            doExit = true;
+            break;
+        case ECollectionContextArtistAlbums:
+        case ECollectionContextArtistAllSongs:
+        case ECollectionContextPlaylistSongs:
+            mMpEngine->back();
+            break;
+        case ECollectionContextArtistAlbumsTBone:
+            if ( mCollectionData->count() > 1 ) {
+                // Going from T-Bone to Artist-Album view; Need to fake back.
+                mCollectionData->setContext(ECollectionContextArtistAlbums);
+            }
+            else {
+                // There only 1 album under this artist. Return to artist view.
+                mMpEngine->back();
+            }
+            break;
+        case ECollectionContextAlbumsTBone:
+            // Going from T-Bone to Album view; Need to fake back.
+            mCollectionData->setContext(ECollectionContextAlbums);
+            break;
+        default:
+            doExit = true;
+            break;
+    }
+
+    if ( doExit ) {
+        if ( mViewMode == MpCommon::FetchView ) {
+            // Send an empty string to indicate that user has cancelled
+            // the fetch operation
+            emit songSelected( "" );
+        }
+        else {
+            emit command( MpCommon::SendToBackground );
+        }
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called to exit.
+ */
+void MpCollectionView::exit()
+{
+    TX_ENTRY
+    emit command( MpCommon::Exit );
+    TX_EXIT
+}
+
+
+/*!
+ Slot to be called to activate playback view.
+ */
+void MpCollectionView::startPlaybackView()
+{
+    TX_LOG
+    emit command( MpCommon::ActivatePlaybackView );
+}
+
+/*!
+ Slot to be called when 'Now Playing Banner' state changes. If active, 'Now
+ Playing Banner' is attached/shown in the collection view.
+ */
+void MpCollectionView::attachNowPlayingBanner( bool active )
+{
+    TX_ENTRY
+    setBannerVisibility( active );
+    mBannerAttached = active;
+    updateMenu();
+    TX_EXIT
+}
+
+/*!
+ Slot for container transition end.
+ */
+void MpCollectionView::containerTransitionComplete( const HbEffect::EffectStatus &status )
+{    
+    if ( status.userData == EFFECT_TARGET_SNAPSHOT ) {
+        qobject_cast<QGraphicsView *>( mWindow )->scene()->removeItem( mSnapshot );
+        mSnapshot->deleteLater();
+        mSnapshot = 0;
+    }
+}
+
+/*!
+ Slot to be called when 'Shuffle play all' is clicked by the user from the menu.
+ */
+void MpCollectionView::shufflePlayAll()
+{
+    TX_ENTRY
+    mMpEngine->setShuffle( true );
+    MpSettingsManager::setShuffle( true );
+    int index = generateShuffleIndex();
+    switch ( mCollectionContext ) {
+        case ECollectionContextArtistAlbumsTBone:
+        case ECollectionContextAlbumsTBone:
+            playAlbumSongs( mCollectionData->currentAlbumIndex(), index );
+            break;
+        default:
+            openIndex( index );
+            break;
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when 'Add to playlist' is clicked by the user from the menu.
+ */
+void MpCollectionView::addToPlaylist()
+{
+    switch ( mCollectionContext ) {
+        case ECollectionContextArtistAlbumsTBone:
+        case ECollectionContextAlbumsTBone:
+            mMpPopupHandler->openAddSongsToPlaylistFromTBone();    
+            break;
+        default:
+            mMpPopupHandler->openAddSongsToPlaylist( mCollectionDataModel );
+            break;
+    }
+}
+
+/*!
+ Slot to be called when 'Delete' is clicked by the user from the menu.
+ */
+void MpCollectionView::deleteSongs()
+{
+    mMpPopupHandler->openDeleteSongs( mCollectionDataModel );
+}
+
+/*!
+ Slot to be called when 'Rename Playlist' is clicked by the user from the menu.
+ */
+void MpCollectionView::renameCurrentPlaylistContainer()
+{
+    QString currentName;
+    currentName = mCollectionData->collectionTitle();    
+    mMpPopupHandler->openRenamePlaylistContainerDialog( currentName );
+}
+
+
+/*!
+ Slot to be called when 'Add to playlist' operation has completed.
+ */
+void MpCollectionView::playlistSaved( bool success )
+{
+    if ( success
+         && ( ECollectionContextPlaylists == mCollectionContext
+              || ECollectionContextPlaylistSongs == mCollectionContext ) ) {
+        mMpEngine->reopenCollection();
+    }
+}
+
+/*!
+ Slot to be called when 'Delete' operation has completed.
+ */
+void MpCollectionView::songsDeleted( bool success )
+{
+    // Update list if delete succeded or if delete interrupted by an USB MTP Event
+    if ( success || mMpEngine->verifyUsbBlocking( true ) ) {
+        mMpEngine->reopenCollection();
+    }
+}
+/*!
+ Slot to be called when 'Rename' operation has completed.
+ */
+void MpCollectionView::playlistsRenamed( bool success )
+{
+    if ( success ) {
+        mMpEngine->reopenCollection();
+    }
+}
+
+/*!
+ Slot to be called to get ready for add to playlist using an isolated collection.
+ */
+void MpCollectionView::prepareToAddToPlaylist()
+{
+    TX_ENTRY
+    mMpEngine->openIsolatedCollection( ECollectionContextAllSongs );
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when isolated collection is oppened.
+ */
+void MpCollectionView::handleIsolatedCollectionOpened( MpMpxCollectionData* collectionData )
+{
+    TX_ENTRY
+    if ( mActivated ) {
+
+        if (ECollectionContextPlaylistSongs == mCollectionContext) {
+            mMpPopupHandler->openAddToCurrentPlaylist( collectionData );
+        }
+        else if (ECollectionContextPlaylists == mCollectionContext) {
+            mMpPopupHandler->openCreateNewPlaylist( collectionData );
+        }
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called to arrange songs in a playlist.
+ */
+void MpCollectionView::arrangeSongs( )
+{
+    mMpPopupHandler->openArrangeSongs();
+}
+
+/*!
+ Slot to be called when an item is long pressed by the user.
+ */
+void MpCollectionView::openContextMenu( int index, const QPointF &coords )
+{
+    TX_ENTRY_ARGS( "index=" << index );
+    switch ( mViewMode ) {
+        case MpCommon::DefaultView:
+            mMpPopupHandler->openDefaultViewContextMenu( index, coords );
+            break;
+        case MpCommon::FetchView:
+            mMpPopupHandler->openFetchViewContextMenu( index, coords );
+            break;
+        default:
+            break;
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when USB blocking status changes.
+ */
+void MpCollectionView::handleUsbBlocked( bool blocked )
+{
+    TX_ENTRY_ARGS( "blocked=" << blocked );
+    mUsbBlocked = blocked;
+        
+    closeActiveDialog();
+    
+    updateMenu();
+    if ( mCollectionContext == ECollectionContextPlaylistSongs ) {
+         updateToolBar();
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when library is going to be updated.
+ */
+void MpCollectionView::handleLibraryAboutToUpdate()
+{
+    TX_ENTRY
+    closeActiveDialog();
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when refreshing completes or library has been updated.
+ */
+void MpCollectionView::handleLibraryUpdated()
+{
+    TX_ENTRY
+    if ( mActivationWaiting ) {
+        mActivationWaiting = false;
+        activateView();
+    }
+    else {
+        closeActiveDialog();
+
+        // Update cache, even if collection is in background.
+        // Library refreshing could be triggered at any point due USB/MMC events.
+        if ( mCollectionContext == ECollectionContextAllSongs ) {
+            mMpEngine->reopenCollection();
+        }
+		// We force to go to the all songs collection when the refresh is finished.
+        else{
+            openSongs();
+        }
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when shuffle action status changes. This is called by the
+ containers. Shuffle is only enabled when there is more than 1 song and the
+ it can change when songs are deleted or when new songs are found during refresh.
+ */
+void MpCollectionView::setShuffleAction( bool enabled )
+{
+    TX_ENTRY
+    mShuffleEnabled = enabled;
+    if ( mShuffleAction ) {
+        mShuffleAction->setEnabled(enabled);
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when a container data is changed/updated.
+ */
+void MpCollectionView::containerDataChanged()
+{
+    TX_ENTRY
+    if ( mCollectionContext == ECollectionContextPlaylistSongs ) {
+         updateToolBar();
+    }
+    TX_EXIT
+}
+
+/*!
+ \internal
+ Sets the main ( default ) toolbar for the view.
+ */
+void MpCollectionView::setMainToolBar()
+{
+    TX_ENTRY
+    if ( !mMainToolBar ) {
+        //Create the toolbar.
+        mMainToolBar = new HbToolBar();
+        mMainToolBar->setObjectName( "MainToolBar" );
+        mMainToolBar->setOrientation( Qt::Horizontal );
+        QActionGroup *actionsGroup = new QActionGroup( mMainToolBar );
+        HbAction *action;
+
+        // All Songs
+        action = createToolBarAction( actionsGroup, "qtg_mono_songs_all", "AllSongsAction" );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( openSongs() ) );
+        mMainToolBar->addAction( action );
+        
+        // Artists
+        action = createToolBarAction( actionsGroup, "qtg_mono_artists", "ArtistsAction" );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( openArtists() ) );
+        mMainToolBar->addAction( action );
+
+        // Albums
+        action = createToolBarAction( actionsGroup, "qtg_mono_music_albums", "AlbumsAction" );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( openAlbums() ) );
+        mMainToolBar->addAction( action );
+
+        // Playlists
+        action = createToolBarAction( actionsGroup, "qtg_mono_playlist", "PlaylistsAction" );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( openPlaylists() ) );
+        mMainToolBar->addAction( action );
+        
+        if ( mViewMode != MpCommon::FetchView ) {
+            // Music Store
+            action = createToolBarAction(actionsGroup, "qtg_mono_ovistore", "MusicStoreAction" );
+            connect( action, SIGNAL( triggered( bool ) ), this, SLOT( openMusicStore() ) );
+            mMainToolBar->addAction( action );
+        }
+    }
+    HbAction* action = 0;
+    switch ( mCollectionContext ) {
+        case ECollectionContextAllSongs:
+            action = qobject_cast<HbAction*>( mMainToolBar->actions()[KMainToolBarAll] );
+            break;
+        case ECollectionContextArtists:
+            action = qobject_cast<HbAction*>( mMainToolBar->actions()[KMainToolBarArtists] );
+            break;
+        case ECollectionContextAlbums:
+            action = qobject_cast<HbAction*>( mMainToolBar->actions()[KMainToolBarAlbums] );
+            break;
+        case ECollectionContextPlaylists:
+            action = qobject_cast<HbAction*>( mMainToolBar->actions()[KMainToolBarPlaylists] );
+            break;
+    }
+    if ( action ) {
+        action->setChecked( true );
+    }
+    if ( toolBar() != mMainToolBar ) {
+        HbToolBar *tmpToolBar = takeToolBar();
+        if ( tmpToolBar && tmpToolBar->actions().empty() ) {
+            tmpToolBar->deleteLater();
+        }
+        setToolBar( mMainToolBar );
+    }
+    TX_EXIT
+}
+
+/*!
+ \internal
+ Sets the playlist toolbar for the view.
+ Used only on the playlist container.
+ */
+void MpCollectionView::setPlaylistToolBar()
+{
+    TX_ENTRY
+    if ( !mPlaylistToolBar ) {
+        mPlaylistToolBar = new HbToolBar();
+        mPlaylistToolBar->setObjectName( "PlaylistToolBar" );
+        mPlaylistToolBar->setOrientation( Qt::Horizontal );
+        HbAction *action;
+
+        action = new HbAction( this );
+        action->setIcon( HbIcon( "qtg_mono_plus" ) );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( prepareToAddToPlaylist() ) );
+        action->setObjectName( "AddToPlaylistAction" );
+        mPlaylistToolBar->addAction( action );
+
+        action = new HbAction( this );
+        action->setIcon( HbIcon( "qtg_mono_minus" ) );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( deleteSongs() ) );
+        action->setObjectName( "RemoveFromPlaylistAction" );
+        mPlaylistToolBar->addAction( action );
+
+        action = new HbAction( this );
+        action->setIcon( HbIcon( "qtg_mono_organize" ) );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( arrangeSongs() ) );
+        action->setObjectName( "OrganizePlaylistAction" );
+        mPlaylistToolBar->addAction( action );
+    }
+
+    int items = mCollectionData->count();
+
+    //no use for add if usb blocked.
+    mPlaylistToolBar->actions()[KPlaylistToolBarAdd]->setEnabled( !mUsbBlocked );
+
+    //no use for remove if there are no items or usb blocked.
+    mPlaylistToolBar->actions()[KPlaylistToolBarRemove]->setEnabled( items > 0 && !mUsbBlocked );
+
+    //no use for reorder if there is no more than 1 item or usb blocked.
+    mPlaylistToolBar->actions()[KplaylistToolBarReorder]->setEnabled( items > 1 && !mUsbBlocked );
+
+    if ( toolBar() != mPlaylistToolBar ) {
+        HbToolBar *tmpToolBar = takeToolBar();
+        if ( tmpToolBar && tmpToolBar->actions().empty () ) {
+            tmpToolBar->deleteLater();
+        }
+        setToolBar( mPlaylistToolBar );
+    }
+    TX_EXIT
+}
+
+/*!
+ \internal
+ Creates action associated with the action group for the toolbar.
+ */
+HbAction *MpCollectionView::createToolBarAction(
+    QActionGroup *actionsGroup,
+    const QString& icon,
+    const QString& objectName )
+{
+    HbIcon actionIcon( icon );
+
+    HbAction *action = new HbAction( actionsGroup );
+    action->setIcon( actionIcon );
+    action->setCheckable( true );
+    action->setObjectName( objectName );
+    return action;
+}
+
+/*!
+ \internal
+ Updates the options menu according to current context.
+ */
+void MpCollectionView::updateMenu()
+{
+    TX_ENTRY
+    HbMenu *myMenu = new HbMenu();
+    HbAction *menuAction;
+    if ( mViewMode == MpCommon::DefaultView ) {
+        int count = mCollectionData->count();
+        switch ( mCollectionContext ) {
+            case ECollectionContextAllSongs:
+                mShuffleAction = myMenu->addAction( hbTrId( "txt_mus_opt_shuffle" ) );
+                connect( mShuffleAction, SIGNAL( triggered() ), this, SLOT( shufflePlayAll() ) );
+                if ( count <= 1 ) {
+                    mShuffleAction->setDisabled( true );
+                }
+                menuAction = myMenu->addAction( hbTrId( "txt_mus_opt_add_to_playlist" ) );
+                if ( count && !mUsbBlocked ) {
+                    connect( menuAction, SIGNAL( triggered() ), this, SLOT( addToPlaylist() ) );
+                }
+                else {
+                    menuAction->setDisabled( true );
+                }
+                addDefaultMenuOptions( myMenu, true, true );
+                break;
+            case ECollectionContextArtists:
+            case ECollectionContextArtistAlbums:
+            case ECollectionContextAlbums:
+                addDefaultMenuOptions( myMenu, true, true );
+                break;
+            case ECollectionContextArtistAlbumsTBone:
+            case ECollectionContextAlbumsTBone:
+                mShuffleAction = myMenu->addAction( hbTrId( "txt_mus_opt_shuffle" ) );
+                connect( mShuffleAction, SIGNAL( triggered() ), this, SLOT( shufflePlayAll() ) );
+                if ( !mShuffleEnabled ) {
+                    mShuffleAction->setDisabled( true );
+                }
+                menuAction = myMenu->addAction( hbTrId( "txt_mus_opt_add_to_playlist" ) );
+                if ( !mUsbBlocked ) {
+                    connect( menuAction, SIGNAL( triggered() ), this, SLOT( addToPlaylist() ) );
+                }
+                else {
+                    menuAction->setDisabled( true );
+                }
+                addDefaultMenuOptions( myMenu, true, true );
+                break;
+            case ECollectionContextArtistAllSongs:
+                mShuffleAction = myMenu->addAction( hbTrId( "txt_mus_opt_shuffle" ) );
+                connect( mShuffleAction, SIGNAL( triggered() ), this, SLOT( shufflePlayAll() ) );
+                if ( count <= 1 ) {
+                    mShuffleAction->setDisabled( true );
+                }
+                menuAction = myMenu->addAction( hbTrId( "txt_mus_opt_add_to_playlist" ) );
+                if ( !mUsbBlocked ) {
+                    connect( menuAction, SIGNAL( triggered() ), this, SLOT( addToPlaylist() ) );
+                }
+                else {
+                    menuAction->setDisabled( true );
+                }
+                addDefaultMenuOptions( myMenu, true, true );
+                break;
+            case ECollectionContextPlaylists:
+                menuAction = myMenu->addAction( hbTrId( "txt_mus_opt_new_playlist" ) );
+                if ( !mUsbBlocked ) {
+                    connect( menuAction, SIGNAL( triggered() ), this, SLOT( prepareToAddToPlaylist() ) );
+                }
+                else {
+                    menuAction->setDisabled( true );
+                }
+                addDefaultMenuOptions( myMenu, true, true );
+                break;
+            case ECollectionContextPlaylistSongs:
+                mShuffleAction = myMenu->addAction( hbTrId( "txt_mus_opt_shuffle" ) );
+                connect( mShuffleAction, SIGNAL( triggered() ), this, SLOT( shufflePlayAll() ) );
+                if ( count <= 1 ) {
+                    mShuffleAction->setDisabled( true );
+                }
+                if ( !mCollectionData->isAutoPlaylist() ) {
+                menuAction = myMenu->addAction( hbTrId( "txt_common_menu_rename_item" ) );
+                    if ( !mUsbBlocked ) {
+                        connect( menuAction, SIGNAL( triggered() ), this, SLOT( renameCurrentPlaylistContainer() ) );
+                    }
+                    else {
+                        menuAction->setDisabled( true );
+                    }
+                }
+                addDefaultMenuOptions( myMenu, true, true );
+                break;
+            default:
+                break;
+        }
+    }
+    else if ( mViewMode == MpCommon::FetchView ) {
+        switch ( mCollectionContext ) {
+            case ECollectionContextAllSongs:
+            case ECollectionContextArtists:
+            case ECollectionContextAlbums:
+                addDefaultMenuOptions( myMenu, true, false );
+                break;
+            default:
+                break;
+        }
+    }
+
+    setMenu( myMenu );
+    TX_EXIT
+}
+
+/*!
+ \internal
+ Add default options to a specific menu.
+ */
+void MpCollectionView::addDefaultMenuOptions( HbMenu *menu, bool optRefresh, bool optExit )
+{
+    TX_ENTRY
+    if ( menu ) {
+        HbAction *menuAction;
+        if( optRefresh ) {
+            menuAction = menu->addAction( hbTrId( "txt_mus_opt_refresh_library" ) );
+            if ( !mUsbBlocked ) {
+                connect( menuAction, SIGNAL( triggered() ), mMpEngine, SLOT( refreshLibrary() ) );
+            }
+            else {
+                menuAction->setDisabled( true );
+                }
+        }
+        if ( optExit ) {
+            connect( menu->addAction(hbTrId("txt_common_opt_exit")), SIGNAL( triggered() ), this, SLOT( exit() ) );
+        }
+    }
+    TX_EXIT
+}
+
+/*!
+ \internal
+ Updates the Toolbar according to current context.
+ */
+void MpCollectionView::updateToolBar()
+{
+    TX_ENTRY
+
+    switch ( mCollectionContext ) {
+        case ECollectionContextPlaylistSongs:
+            if ( !mCollectionData->isAutoPlaylist() ) {
+                setPlaylistToolBar();
+            }
+            else if ( !toolBar()->actions().empty() ) {
+                takeToolBar();
+                setToolBar( new HbToolBar );
+            }
+            break;
+        case ECollectionContextArtistAlbums:
+        case ECollectionContextArtistAlbumsTBone:
+        case ECollectionContextArtistAllSongs:
+        case ECollectionContextAlbumsTBone:
+            if ( !toolBar()->actions().empty() ) {
+                takeToolBar();
+                setToolBar( new HbToolBar );
+            }
+            break;
+        default:
+            setMainToolBar();
+            break;
+    }
+    TX_EXIT
+}
+
+/*!
+ \internal
+ Updates the softkey according to current context.
+ */
+void MpCollectionView::setSoftkey()
+{
+    if ( mViewMode == MpCommon::FetchView ) {
+        // 'Back' is used in all views in fetch mode because we must
+        // appear as an embedded application.
+        setNavigationAction( mSoftKeyBack );
+    }
+    else {
+        switch ( mCollectionContext ) {
+            case ECollectionContextAllSongs:
+            case ECollectionContextArtists:
+            case ECollectionContextAlbums:
+            case ECollectionContextPlaylists:
+                setNavigationAction( mSoftKeyQuit );
+                break;
+            default:
+                setNavigationAction( mSoftKeyBack );
+                break;
+        }
+    }
+}
+
+/*!
+ \internal
+ Sets the Now Playing Banner visibility based on \a visible.
+ */
+void MpCollectionView::setBannerVisibility( bool visible )
+{
+    bool ok = false;
+    if ( visible ) {
+        mDocumentLoader->load( MUSIC_COLLECTION_DOCML, "showBanner", &ok );
+    }
+    else {
+        mDocumentLoader->load( MUSIC_COLLECTION_DOCML, "hideBanner", &ok );
+    }
+
+    if ( !ok ) {
+        TX_LOG_ARGS( "Error: invalid xml file." );
+        Q_ASSERT_X( ok, "MpCollectionView::setBannerVisibility", "invalid xml file" );
+    }
+}
+
+/*!
+ \internal
+ Generates a random index for shuffle all. In case of All Songs, due to incremental open
+ delay, the chosen index may not be available yet. In such case, narrow down the upper limit
+ and regenerate until a valid index is found.
+ */
+int MpCollectionView::generateShuffleIndex()
+{
+    int low = 0;
+    int high = 0;
+    bool tbone;
+    switch ( mCollectionContext ) {
+        case ECollectionContextArtistAlbumsTBone:
+        case ECollectionContextAlbumsTBone:
+            tbone = true;
+            high = mCollectionData->albumSongsCount();
+            break;
+        default:
+            tbone = false;
+            high = mCollectionData->count();
+            break;
+    }
+
+    bool validIndex = false;
+    int index = 0;
+    int songId;
+    time_t seconds;
+    while ( !validIndex ) {
+        time( &seconds );
+        srand( ( unsigned int ) seconds );
+        index = rand() % ( high - low + 1 ) + low;
+
+        if ( tbone ) {
+            songId = mCollectionData->albumSongId(index);
+        }
+        else {
+            songId = mCollectionData->itemId(index);
+        }
+
+        if ( songId != -1 ) {
+            // Got a valid index; exit the loop.
+            validIndex = true;
+        }
+        else {
+            // Invalid index; re-select an index, but narrow down the
+            // upper range to increase the change of hitting a valid index.
+            high = index;
+        }
+        TX_LOG_ARGS( "index=" << index << "valid=" << validIndex );
+    }
+    return index;
+}
+
+/*!
+ \internal
+ starts a transition of the main container with a decoy snapshot.
+ */
+void MpCollectionView::startContainerTransition( TCollectionContext contextFrom, TCollectionContext contextTo )
+{
+    if (contextFrom == contextTo) {
+        return;
+    }
+
+    if ( !mSnapshot ) {
+        mSnapshot = new MpSnapshotWidget();
+    }
+    mSnapshot->capture( mWindow, mMainContainer );
+    mWindow->scene()->addItem( mSnapshot );
+
+
+    if( ( contextFrom == ECollectionContextAlbumsTBone && contextTo == ECollectionContextAlbums ) ||
+             ( contextFrom == ECollectionContextArtistAlbums && contextTo == ECollectionContextArtists ) ||
+             ( contextFrom == ECollectionContextArtistAlbumsTBone && contextTo == ECollectionContextArtistAlbums ) ||
+             ( contextFrom == ECollectionContextArtistAlbumsTBone && contextTo == ECollectionContextArtists ) ||
+             ( contextFrom == ECollectionContextArtistAllSongs && contextTo == ECollectionContextArtistAlbums ) ||
+             ( contextFrom == ECollectionContextPlaylistSongs && contextTo == ECollectionContextPlaylists ) ) {
+        HbEffect::start( mSnapshot,
+                QString( CONTAINER_EFFECT_GROUP ),
+                QString( HIDE_BACK_EFFECT ),
+                this,
+                "containerTransitionComplete",
+                QString( EFFECT_TARGET_SNAPSHOT) );
+
+        HbEffect::start( mMainContainer,
+                QString( CONTAINER_EFFECT_GROUP ),
+                QString( SHOW_BACK_EFFECT ),
+                this,
+                "containerTransitionComplete",
+                QString( EFFECT_TARGET_CONTAINER) );
+    }
+    else {
+        HbEffect::start( mSnapshot,
+                QString( CONTAINER_EFFECT_GROUP ),
+                QString( HIDE_EFFECT ),
+                this,
+                "containerTransitionComplete",
+                QString( EFFECT_TARGET_SNAPSHOT) );
+
+        HbEffect::start( mMainContainer,
+                QString( CONTAINER_EFFECT_GROUP ),
+                QString( SHOW_EFFECT ),
+                this,
+                "containerTransitionComplete",
+                QString( EFFECT_TARGET_CONTAINER ) );
+    }
+}
+
+/*!
+ \internal
+ Closes any active dialog or menu.
+ */
+void MpCollectionView::closeActiveDialog( bool onlyContextMenu )
+{
+    mMpPopupHandler->cancelOngoingPopup( onlyContextMenu );
+    menu()->close();
+}
+
+/*!
+ \internal
+ Shows Corrupted Note in collection view
+ */
+void MpCollectionView::showCorruptedNote()
+{
+    TX_ENTRY
+    HbMessageBox *messageBox = new HbMessageBox( hbTrId( "txt_mus_info_file_is_corrupt" ), HbMessageBox::MessageTypeInformation );
+    messageBox->setAttribute( Qt::WA_DeleteOnClose );
+    messageBox->setIcon( HbIcon( QString("qtg_small_fail") ) ); 
+    messageBox->show();
+    TX_EXIT
+}