diff -r 3ec52facab4d -r 8192e5b5c935 mpviewplugins/mpmediawallviewplugin/src/mpmediawallview.cpp --- /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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#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( 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( 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(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(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() ) { + mAlbumCover->setIcon(image.value()); + } + 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(); +} +