mpviewplugins/mpmediawallviewplugin/src/mpmediawallview.cpp
changeset 29 8192e5b5c935
child 32 c163ef0b758d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpviewplugins/mpmediawallviewplugin/src/mpmediawallview.cpp	Thu May 27 12:49:57 2010 +0300
@@ -0,0 +1,508 @@
+/*
+* 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 Settings view.
+*
+*/
+
+#include <QParallelAnimationGroup>
+#include <QPropertyAnimation>
+
+#include <hbicon.h>
+#include <hbaction.h>
+#include <hbapplication.h>
+#include <hbscrollbar.h>
+#include <hblabel.h>
+#include <hbpushbutton.h>
+#include <hbtoolbutton.h>
+
+#include <hgmediawall.h>
+
+#include "mpmediawallview.h"
+#include "mpmediawalldocumentloader.h"
+#include "mpcommondefs.h"
+#include "mpmpxcollectiondata.h"
+#include "mpcollectiondatamodel.h"
+#include "mpenginefactory.h"
+#include "mpplaybackdata.h"
+#include "mpalbumcoverwidget.h"
+#include "mptracklistwidget.h"
+#include "mpcollectiontbonelistdatamodel.h"
+#include "mptrace.h"
+
+const char*MUSIC_MEDIAWALL_DOCML = ":/mediawallviewdocml/mediawall.docml";
+
+/*!
+    \class MpMediaWallView
+    \brief Music Player Settings view.
+
+    Music player media wall view displays music players albums on an full screen view
+*/
+
+/*!
+    \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 media wall view.
+ */
+MpMediaWallView::MpMediaWallView()
+    : mEngine( 0 ),
+      mCollectionData( 0 ),
+      mModel( 0 ),
+      mMediaWallWidget( 0 ),
+      mNoMusic( 0 ),
+      mDocumentLoader( 0 ),
+      mPlayPauseContainer( 0 ),
+      mPlayIcon( 0 ),
+      mPauseIcon( 0 ),
+      mPlayPauseAction( 0 ),
+      mLibraryUpdating( false ),
+      mPlaybackData( 0 ),
+      mActivated( false ),
+      mIconUpdateNedded( false ),
+      mListShowAnimationGroup( 0 ),
+      mListShowListAnimation( 0 ),
+      mCoverShowListAnimation( 0 ),
+      mShowingSongsList( false ),
+      mAlbumCover( 0 ),
+      mTrackList( 0 )
+{
+    connect( MpEngineFactory::sharedEngine(), SIGNAL( libraryAboutToUpdate() ),
+                    this, SLOT( libraryAboutToUpdate() ) );
+    connect( MpEngineFactory::sharedEngine(), SIGNAL( libraryUpdated() ),
+                    this, SLOT( libraryUpdated() ) );
+    TX_LOG
+}
+    
+/*!
+ Destructs the media wall view.
+ */
+MpMediaWallView::~MpMediaWallView()
+{
+    TX_ENTRY
+    //delete not parented objects
+    delete mDocumentLoader;
+    delete mPlayIcon;
+    delete mPauseIcon;
+    TX_EXIT
+}
+
+/*!
+ Initializes the media wall view.
+ */
+void MpMediaWallView::initializeView()
+{
+    TX_ENTRY
+    setTitleBarVisible( false );
+    setStatusBarVisible( false );
+       
+    mDocumentLoader = new MpMediaWallDocumentLoader();  
+    bool ok = false;
+    mDocumentLoader->load( MUSIC_MEDIAWALL_DOCML, &ok );
+    if ( ok ) {
+        QGraphicsWidget *widget;
+        
+        //Setup fake softkey to hide the app
+        widget = mDocumentLoader->findWidget( QString( "navigationButton" ) );
+        HbAction  *action;
+        action = new HbAction( Hb::BackNaviAction, this );
+        connect( action, SIGNAL( triggered( bool ) ), this, SLOT( sendToBackground() ) );
+        qobject_cast<HbToolButton*>( widget )->setAction( action );
+        
+        //Setup the play/pause command button
+        widget = mDocumentLoader->findWidget( QString( "playPauseButton" ) );
+        mPauseIcon = new HbIcon( "qtg_mono_pause" );
+        mPlayIcon = new HbIcon( "qtg_mono_play" );
+        mPlayPauseAction = new HbAction( HbIcon() , QString(), this );  
+        mPlaybackData = MpEngineFactory::sharedEngine()->playbackData();
+        qobject_cast<HbToolButton*>( widget )->setAction( mPlayPauseAction );
+        //we need this widget to hide the play pause button, for soem reaosn it does not want to hide.
+        mPlayPauseContainer = mDocumentLoader->findWidget( QString( "playPauseButtonContainer" ) );
+        updatePlayPauseAction();
+        connect( mPlaybackData, SIGNAL( playbackStateChanged() ),
+                 this, SLOT( updatePlayPauseAction() ) );
+        connect( mPlayPauseAction, SIGNAL( triggered( bool ) ),
+                 MpEngineFactory::sharedEngine(), SLOT( playPause() ) );
+
+        
+        //Get the main container and set as widget.
+        widget = mDocumentLoader->findWidget( QString( "container" ) );
+        setWidget( widget );
+        
+        mEngine = MpEngineFactory::createIsolatedEngine( MpEngine::MediaBrowsing );
+        mCollectionData = mEngine->collectionData();
+        mModel = new MpCollectionDataModel( mCollectionData, this );
+        
+        connect( mCollectionData, SIGNAL( contextChanged( TCollectionContext ) ), 
+                 this, SLOT( contextOpened( TCollectionContext ) ) );
+        connect( mEngine, SIGNAL( containerContentsChanged() ),
+                this, SLOT( containerContentsChanged() ) );
+        if ( !mLibraryUpdating ) {
+        mEngine->openCollection( ECollectionContextAlbumsMediaWall );
+        }
+    }
+    else {
+        TX_LOG_ARGS( "Error: invalid xml file." );
+        Q_ASSERT_X( ok, "MpCollectionView::initializeView", "invalid xml file" );
+    }
+    
+    mAlbumCover = new MpAlbumCoverWidget( this );
+    mAlbumCover->setDefaultIcon( HbIcon( "qtg_large_music_album" ) );
+    mAlbumCover->hide();
+    
+    mTrackList = new MpTrackListWidget( this );
+    mTrackList->list()->setModel( new MpCollectionTBoneListDataModel(mCollectionData, mTrackList ) );
+    mTrackList->hide();
+    
+    connect(mAlbumCover,SIGNAL(clicked()),this, SLOT(hideTracksList()));
+    connect(mTrackList->list(), SIGNAL(activated(QModelIndex)), this, SLOT(listItemActivated(QModelIndex)));
+    connect(mTrackList,SIGNAL(close()),this, SLOT(hideTracksList()));
+
+
+    
+    TX_EXIT
+}
+
+/*!
+ Activates the media wall view.
+ */
+void MpMediaWallView::activateView()
+{
+    TX_ENTRY
+    mActivated = true;
+    if ( mIconUpdateNedded ) {
+        updatePlayPauseAction();
+        mIconUpdateNedded = false;
+    }
+    scrollToNowPlaying();   
+    TX_EXIT
+}
+
+/*!
+ Deactivates the media wall view.
+ */
+void MpMediaWallView::deactivateView()
+{
+    TX_ENTRY
+    mActivated = false;
+    dismissListClosingAnimation();
+    TX_EXIT
+}
+
+/*!
+ Slot to be called when the context is opened.
+ */
+void MpMediaWallView::contextOpened( TCollectionContext context )
+{
+    if ( context != ECollectionContextAlbumsMediaWall ) {
+        //Force the context to Albums Media Wall, this to get the model and 
+        //data to provide the right funtionality to media wall.
+        mCollectionData->setContext( ECollectionContextAlbumsMediaWall );
+        return;
+    }
+    if ( mCollectionData->count() ) {
+        if (mNoMusic) {
+            delete mNoMusic;
+            mNoMusic = 0;
+        }
+        if ( mMediaWallWidget ) {
+            mModel->refreshModel();
+        } else {
+            bool ok = false;
+            mDocumentLoader->load( MUSIC_MEDIAWALL_DOCML, "mediaWall", &ok);
+            if ( ok ) {
+                QGraphicsWidget *widget;
+                widget = mDocumentLoader->findWidget(QString("mediaWallWidget"));
+                mMediaWallWidget = qobject_cast<HgMediawall*>(widget);
+                mModel->refreshModel();
+                setUpMediaWallWidget();
+            }
+            else {
+                TX_LOG_ARGS("Error: invalid xml file.");
+                Q_ASSERT_X(ok, "MpMediaWallView::contextOpened", "invalid xml file");
+
+            }          
+        }
+    }
+    else {
+        if ( mMediaWallWidget ) {
+            delete mMediaWallWidget;
+            mMediaWallWidget = 0;
+            
+        }
+        if ( !mNoMusic ) {
+            bool ok = false;
+            mDocumentLoader->load( MUSIC_MEDIAWALL_DOCML, "empty", &ok);
+            if ( ok ) {
+                QGraphicsWidget *widget;
+                widget = mDocumentLoader->findWidget(QString("noMusic"));
+                mNoMusic = qobject_cast<HbLabel*>(widget);
+            }
+            else {
+                TX_LOG_ARGS("Error: invalid xml file.");
+                Q_ASSERT_X(ok, "MpMediaWallView::contextOpened", "invalid xml file");
+
+            }
+        }
+    }
+}
+
+/*!
+ Slot to be called when the container contents changed.
+ */
+void MpMediaWallView::containerContentsChanged() 
+{
+    if ( !mLibraryUpdating && mEngine ) {
+        mEngine->openCollection( ECollectionContextAlbumsMediaWall );
+    }
+}
+
+/*!
+ Slot to be called when the container contents changed.
+ */
+void MpMediaWallView::libraryAboutToUpdate()
+{
+    mLibraryUpdating = true;
+}
+
+/*!
+ Slot to be called when the container contents changed.
+ */
+void MpMediaWallView::libraryUpdated()
+{
+    mLibraryUpdating = false;
+    if ( mEngine ) {
+        mEngine->openCollection( ECollectionContextAlbumsMediaWall );
+    }
+}
+
+/*!
+ Slot to be called to send to background.
+ */
+void MpMediaWallView::sendToBackground()
+{
+    TX_ENTRY
+    emit command( MpCommon::SendToBackground );
+    TX_EXIT
+}
+
+/*!
+ Slot to update teh play pause action icon.
+ */
+void MpMediaWallView::updatePlayPauseAction()
+{
+    if ( !mActivated ) {
+        mIconUpdateNedded = true;
+        return;
+    }
+    TX_ENTRY
+    switch ( mPlaybackData->playbackState() ) {
+        case MpPlaybackData::Playing:
+            TX_LOG_ARGS( "MpPlaybackData::Playing" )
+            mPlayPauseAction->setIcon( *mPauseIcon );
+            mPlayPauseContainer->show();
+            break;
+        case MpPlaybackData::Paused:
+        case MpPlaybackData::Stopped:
+            TX_LOG_ARGS( "MpPlaybackData::Paused" )
+            mPlayPauseAction->setIcon( *mPlayIcon );
+            mPlayPauseContainer->show();
+            break;
+        case MpPlaybackData::NotPlaying:
+            mPlayPauseContainer->hide();       
+            break;
+        default:
+            break;
+    }
+    TX_EXIT
+}
+
+/*!
+ Slot called to start the album and list opening animation.
+ */
+void MpMediaWallView::showTrackList()
+{
+    if( mShowingSongsList ) {
+        return;
+    }
+    mShowingSongsList = true;
+    setUpListAnimation();
+    mListShowAnimationGroup->setDirection(QAbstractAnimation::Forward);
+    mListShowAnimationGroup->start();
+}
+
+/*!
+ Slot to be called to starts the album and list closing animation.
+ */
+void MpMediaWallView::hideTracksList()
+{
+    mListShowAnimationGroup->setDirection(QAbstractAnimation::Backward);
+    connect(mListShowAnimationGroup, SIGNAL(finished()), this, SLOT(dismissListClosingAnimation()));
+    mListShowAnimationGroup->start();
+}
+
+/*!
+ Slot to be called when list closing animation is done or when we want to cancel the animation.
+ */
+void MpMediaWallView::dismissListClosingAnimation()
+{
+    if ( !mShowingSongsList ) {
+        return;
+    }
+    mShowingSongsList = false;
+    mAlbumCover->hide();
+    mTrackList->hide();
+    mListShowAnimationGroup->stop();
+    disconnect(mListShowAnimationGroup, SIGNAL(finished()), this, SLOT(dismissListClosingAnimation()));
+}
+
+/*!
+ Slot to be called when a list item is selected by the user.
+ */
+void MpMediaWallView::listItemActivated( const QModelIndex &index )
+{
+    int albumIndex = mMediaWallWidget->currentIndex().row();
+    //We are playing on the shared engine, but we pass the collection data that
+    //points to albums on media wall, this is used to construct the playlist.
+    MpEngineFactory::sharedEngine()->playAlbumSongs( albumIndex, index.row(), mCollectionData );
+}
+
+/*!
+ Loads the media wall widget.
+ */
+void MpMediaWallView::setUpMediaWallWidget()
+{
+    HbIcon defaultIcon( "qtg_large_music_album" );
+    defaultIcon.setSize(mMediaWallWidget->itemSize());
+    mMediaWallWidget->setDefaultImage( defaultIcon.pixmap().toImage() );
+    mMediaWallWidget->enableReflections( false );
+    mMediaWallWidget->setModel( mModel );
+    if ( mPlaybackData->playbackState() != MpPlaybackData::NotPlaying ) {
+        scrollToNowPlaying();
+    }
+    //The rest of the cases are attepting to balance the items on screen.
+    else if ( mModel->rowCount() >= 5 ) {
+        /* 5 and more
+        [0] [1] [X] [3] [4]...
+        */
+        QModelIndex index;
+        index = mModel->index( 2 );
+        mMediaWallWidget->scrollTo( index );
+    }
+    else if ( mModel->rowCount() >=3  ) {
+        /* 4 and 3
+        __ [0] [X] [2] [3]
+        __ [0] [X] [2] __
+        */
+        QModelIndex index;
+        index = mModel->index( 1 );
+        mMediaWallWidget->scrollTo( index );
+    }
+    else {
+        /* 2 and 1
+        __ __ [X] [1] __
+        __ __ [X] __ __
+        */
+        QModelIndex index;
+        index = mModel->index( 0 );
+        mMediaWallWidget->scrollTo( index );
+    }
+    mMediaWallWidget->setTitleFontSpec( HbFontSpec( HbFontSpec::Primary ) );
+    mMediaWallWidget->setDescriptionFontSpec( HbFontSpec( HbFontSpec::Secondary ) );
+    mMediaWallWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOn ); //HgWidget::ScrollBarAutoHide
+    mMediaWallWidget->scrollBar()->setInteractive( true );
+    mMediaWallWidget->setIndexFeedbackPolicy( HgWidget::IndexFeedbackSingleCharacter );
+    connect(mMediaWallWidget, SIGNAL(activated(QModelIndex)), SLOT(showTrackList()));
+    connect(mMediaWallWidget, SIGNAL(scrollingStarted()), SLOT(dismissListClosingAnimation()));
+}
+
+/*!
+ Scrolls the media wall to now playing position.
+ */
+void MpMediaWallView::scrollToNowPlaying()
+{
+    if ( mMediaWallWidget  && mPlaybackData->playbackState() != MpPlaybackData::NotPlaying ) {
+        int albumId = mPlaybackData->albumId();
+        QModelIndex index;
+        index = mModel->index( mCollectionData->itemIndex( albumId ) );
+        mMediaWallWidget->scrollTo( index );
+    }
+}
+
+/*!
+ Sets up the album and list animation.
+ */
+void MpMediaWallView::setUpListAnimation()
+{
+    if ( !mListShowAnimationGroup ) {
+        mListShowAnimationGroup = new QParallelAnimationGroup( this );
+        mCoverShowListAnimation = new QPropertyAnimation(mAlbumCover, "geometry", this );
+        mCoverShowListAnimation->setDuration( 400 );        
+        mCoverShowListAnimation->setEasingCurve(QEasingCurve::InOutCubic);
+        mListShowAnimationGroup->addAnimation(mCoverShowListAnimation);
+        mListShowListAnimation = new QPropertyAnimation( mTrackList, "geometry", this );
+        mListShowListAnimation->setDuration( 400 );
+        mListShowListAnimation->setEasingCurve(QEasingCurve::InOutCubic);
+        mListShowAnimationGroup->addAnimation(mListShowListAnimation);
+        //track list goes on top of media wall.
+        mTrackList->setZValue(mMediaWallWidget->zValue()+1);
+        //album cover goes on top of track list.
+        mAlbumCover->setZValue(mMediaWallWidget->zValue()+2);
+    }
+    
+    //Get the current album cover geometry.
+    QPolygonF poly;
+    QModelIndex index = mMediaWallWidget->currentIndex();
+    if ( !mMediaWallWidget->getItemOutline( index, poly ) ) {
+        return;
+    }
+    QRectF itemRect = poly.boundingRect();
+
+    //Request the albums tracks, they are set to the track list model.
+    if ( !mCollectionData->setCurrentAlbum( index.row() ) ) {
+        mEngine->findAlbumSongs( index.row() );
+    }
+    
+    //Get the album cover icon.
+    QVariant image = mModel->data(index, Qt::DecorationRole);
+    if ( image.canConvert<HbIcon>() ) {
+       mAlbumCover->setIcon(image.value<HbIcon>());
+    }
+    else {
+        mAlbumCover->setIcon(HbIcon());
+    }
+    
+    //Mapping form local media wall coords to window coors.
+    itemRect.moveTo( mMediaWallWidget->geometry().topLeft() + itemRect.topLeft());   
+    //Calculate start and end position of items for the animation.
+    QRectF endRect = itemRect;
+    endRect.moveTo( endRect.topLeft().x() - endRect.size().width() / 2.0, endRect.topLeft().y() );
+    mCoverShowListAnimation->setStartValue(itemRect);
+    mCoverShowListAnimation->setEndValue(endRect);
+    endRect.moveTo(endRect.topRight() - QPointF(1,0)); //adjust by one pixel to prevent a gap.
+    mListShowListAnimation->setStartValue(itemRect);
+    mListShowListAnimation->setEndValue(endRect);
+    
+    //set initial condition and show to prevent flicker.
+    mAlbumCover->setPos(itemRect.topLeft());
+    mTrackList->setPos(itemRect.topLeft());
+    mTrackList->setGeometry(itemRect);
+    mAlbumCover->show();
+    mTrackList->show();
+}
+