|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Music Player Settings view. |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <QParallelAnimationGroup> |
|
19 #include <QPropertyAnimation> |
|
20 |
|
21 #include <hbicon.h> |
|
22 #include <hbaction.h> |
|
23 #include <hbapplication.h> |
|
24 #include <hbscrollbar.h> |
|
25 #include <hblabel.h> |
|
26 #include <hbtoolbutton.h> |
|
27 #include <hblistview.h> |
|
28 #include <hbstyleloader.h> |
|
29 |
|
30 #include <hgmediawall.h> |
|
31 |
|
32 #include "mpmediawallview.h" |
|
33 #include "mpmediawalldocumentloader.h" |
|
34 #include "mpcommondefs.h" |
|
35 #include "mpmpxcollectiondata.h" |
|
36 #include "mpcollectiondatamodel.h" |
|
37 #include "mpenginefactory.h" |
|
38 #include "mpplaybackdata.h" |
|
39 #include "mpalbumcoverwidget.h" |
|
40 #include "mptracklistwidget.h" |
|
41 #include "mpcollectiontbonelistdatamodel.h" |
|
42 #include "mptrace.h" |
|
43 |
|
44 const char*MUSIC_MEDIAWALL_DOCML = ":/mediawallviewdocml/mediawall.docml"; |
|
45 |
|
46 /*! |
|
47 \class MpMediaWallView |
|
48 \brief Music Player Settings view. |
|
49 |
|
50 Music player media wall view displays music players albums on an full screen view |
|
51 */ |
|
52 |
|
53 /*! |
|
54 \fn void command( int command ) |
|
55 |
|
56 This signal is emitted when the view issues a \a command to the |
|
57 application such as request to switch to a different view. |
|
58 */ |
|
59 |
|
60 |
|
61 /*! |
|
62 Constructs the media wall view. |
|
63 */ |
|
64 MpMediaWallView::MpMediaWallView() |
|
65 : mEngine( 0 ), |
|
66 mCollectionData( 0 ), |
|
67 mModel( 0 ), |
|
68 mMediaWallWidget( 0 ), |
|
69 mNoMusic( 0 ), |
|
70 mDocumentLoader( 0 ), |
|
71 mPlayPauseContainer( 0 ), |
|
72 mPlayIcon( 0 ), |
|
73 mPauseIcon( 0 ), |
|
74 mPlayPauseAction( 0 ), |
|
75 mLibraryUpdating( false ), |
|
76 mPlaybackData( 0 ), |
|
77 mActivated( false ), |
|
78 mIconUpdateNedded( false ), |
|
79 mListShowAnimationGroup( 0 ), |
|
80 mListShowListAnimation( 0 ), |
|
81 mCoverShowListAnimation( 0 ), |
|
82 mShowingSongsList( false ), |
|
83 mAlbumCover( 0 ), |
|
84 mTrackList( 0 ) |
|
85 { |
|
86 connect( MpEngineFactory::sharedEngine(), SIGNAL( libraryAboutToUpdate() ), |
|
87 this, SLOT( libraryAboutToUpdate() ) ); |
|
88 connect( MpEngineFactory::sharedEngine(), SIGNAL( libraryUpdated() ), |
|
89 this, SLOT( libraryUpdated() ) ); |
|
90 TX_LOG |
|
91 } |
|
92 |
|
93 /*! |
|
94 Destructs the media wall view. |
|
95 */ |
|
96 MpMediaWallView::~MpMediaWallView() |
|
97 { |
|
98 TX_ENTRY |
|
99 //delete not parented objects |
|
100 delete mDocumentLoader; |
|
101 delete mPlayIcon; |
|
102 delete mPauseIcon; |
|
103 TX_EXIT |
|
104 } |
|
105 |
|
106 /*! |
|
107 Initializes the media wall view. |
|
108 */ |
|
109 void MpMediaWallView::initializeView() |
|
110 { |
|
111 TX_ENTRY |
|
112 setTitleBarVisible( false ); |
|
113 setStatusBarVisible( false ); |
|
114 |
|
115 mDocumentLoader = new MpMediaWallDocumentLoader(); |
|
116 bool ok = false; |
|
117 mDocumentLoader->load( MUSIC_MEDIAWALL_DOCML, &ok ); |
|
118 if ( ok ) { |
|
119 QGraphicsWidget *widget; |
|
120 |
|
121 //Setup fake softkey to hide the app |
|
122 widget = mDocumentLoader->findWidget( QString( "navigationButton" ) ); |
|
123 HbAction *action; |
|
124 action = new HbAction( Hb::BackNaviAction, this ); |
|
125 connect( action, SIGNAL( triggered( bool ) ), this, SLOT( sendToBackground() ) ); |
|
126 qobject_cast<HbToolButton*>( widget )->setAction( action ); |
|
127 |
|
128 //Setup the play/pause command button |
|
129 widget = mDocumentLoader->findWidget( QString( "playPauseButton" ) ); |
|
130 mPauseIcon = new HbIcon( "qtg_mono_pause" ); |
|
131 mPlayIcon = new HbIcon( "qtg_mono_play" ); |
|
132 mPlayPauseAction = new HbAction( HbIcon() , QString(), this ); |
|
133 mPlaybackData = MpEngineFactory::sharedEngine()->playbackData(); |
|
134 qobject_cast<HbToolButton*>( widget )->setAction( mPlayPauseAction ); |
|
135 //we need this widget to hide the play pause button, for some reason it does not want to hide. |
|
136 mPlayPauseContainer = mDocumentLoader->findWidget( QString( "playPauseButtonContainer" ) ); |
|
137 updatePlayPauseAction(); |
|
138 connect( mPlaybackData, SIGNAL( playbackStateChanged() ), |
|
139 this, SLOT( updatePlayPauseAction() ) ); |
|
140 connect( mPlayPauseAction, SIGNAL( triggered( bool ) ), |
|
141 MpEngineFactory::sharedEngine(), SLOT( playPause() ) ); |
|
142 |
|
143 |
|
144 //Get the main container and set as widget. |
|
145 widget = mDocumentLoader->findWidget( QString( "container" ) ); |
|
146 setWidget( widget ); |
|
147 |
|
148 mEngine = MpEngineFactory::createIsolatedEngine( MpEngine::MediaBrowsing ); |
|
149 mCollectionData = mEngine->collectionData(); |
|
150 mModel = new MpCollectionDataModel( mCollectionData, this ); |
|
151 |
|
152 connect( mCollectionData, SIGNAL( contextChanged( TCollectionContext ) ), |
|
153 this, SLOT( contextOpened( TCollectionContext ) ) ); |
|
154 connect( mEngine, SIGNAL( containerContentsChanged() ), |
|
155 this, SLOT( containerContentsChanged() ) ); |
|
156 if ( !mLibraryUpdating ) { |
|
157 mEngine->openCollection( ECollectionContextAlbumsMediaWall ); |
|
158 } |
|
159 } |
|
160 else { |
|
161 TX_LOG_ARGS( "Error: invalid xml file." ); |
|
162 Q_ASSERT_X( ok, "MpCollectionView::initializeView", "invalid xml file" ); |
|
163 } |
|
164 |
|
165 mAlbumCover = new MpAlbumCoverWidget( this ); |
|
166 mAlbumCover->setDefaultIcon( HbIcon( "qtg_large_album_art" ) ); |
|
167 mAlbumCover->hide(); |
|
168 |
|
169 mTrackList = new MpTrackListWidget( this ); |
|
170 mTrackList->list()->setModel( new MpCollectionTBoneListDataModel(mCollectionData, mPlaybackData, mTrackList ) ); |
|
171 mTrackList->hide(); |
|
172 |
|
173 connect(mAlbumCover,SIGNAL(clicked()),this, SLOT(hideTracksList())); |
|
174 connect(mTrackList->list(), SIGNAL(activated(QModelIndex)), this, SLOT(listItemActivated(QModelIndex))); |
|
175 connect(mTrackList,SIGNAL(closed()),this, SLOT(hideTracksList())); |
|
176 |
|
177 HbStyleLoader::registerFilePath(":/css/mpcustommediawall.css"); |
|
178 HbStyleLoader::registerFilePath(":/css/mpcustommediawall.hgmediawall.widgetml"); |
|
179 |
|
180 TX_EXIT |
|
181 } |
|
182 |
|
183 /*! |
|
184 Activates the media wall view. |
|
185 */ |
|
186 void MpMediaWallView::activateView() |
|
187 { |
|
188 TX_ENTRY |
|
189 mActivated = true; |
|
190 if ( mIconUpdateNedded ) { |
|
191 updatePlayPauseAction(); |
|
192 mIconUpdateNedded = false; |
|
193 } |
|
194 scrollToNowPlaying(); |
|
195 TX_EXIT |
|
196 } |
|
197 |
|
198 /*! |
|
199 Deactivates the media wall view. |
|
200 */ |
|
201 void MpMediaWallView::deactivateView() |
|
202 { |
|
203 TX_ENTRY |
|
204 mActivated = false; |
|
205 dismissListClosingAnimation(); |
|
206 TX_EXIT |
|
207 } |
|
208 |
|
209 /*! |
|
210 Slot to be called when the context is opened. |
|
211 */ |
|
212 void MpMediaWallView::contextOpened( TCollectionContext context ) |
|
213 { |
|
214 if ( context != ECollectionContextAlbumsMediaWall ) { |
|
215 //Force the context to Albums Media Wall, this to get the model and |
|
216 //data to provide the right funtionality to media wall. |
|
217 mCollectionData->setContext( ECollectionContextAlbumsMediaWall ); |
|
218 return; |
|
219 } |
|
220 if ( mCollectionData->count() ) { |
|
221 if (mNoMusic) { |
|
222 delete mNoMusic; |
|
223 mNoMusic = 0; |
|
224 } |
|
225 if ( mMediaWallWidget ) { |
|
226 mModel->refreshModel(); |
|
227 } else { |
|
228 bool ok = false; |
|
229 mDocumentLoader->load( MUSIC_MEDIAWALL_DOCML, "mediaWall", &ok); |
|
230 if ( ok ) { |
|
231 QGraphicsWidget *widget; |
|
232 widget = mDocumentLoader->findWidget(QString("MPmediaWallWidget")); |
|
233 mMediaWallWidget = qobject_cast<HgMediawall*>(widget); |
|
234 //set these items as children of the media wall so they show behind the scrollbar. |
|
235 mTrackList->setParentItem(mMediaWallWidget); |
|
236 mAlbumCover->setParentItem(mMediaWallWidget); |
|
237 mModel->refreshModel(); |
|
238 setUpMediaWallWidget(); |
|
239 } |
|
240 else { |
|
241 TX_LOG_ARGS("Error: invalid xml file."); |
|
242 Q_ASSERT_X(ok, "MpMediaWallView::contextOpened", "invalid xml file"); |
|
243 |
|
244 } |
|
245 } |
|
246 } |
|
247 else { |
|
248 if ( mMediaWallWidget ) { |
|
249 //Take ownership of these items to prevent delete from media wall widget. |
|
250 mTrackList->setParentItem( this ); |
|
251 mAlbumCover->setParentItem( this ); |
|
252 delete mMediaWallWidget; |
|
253 mMediaWallWidget = 0; |
|
254 |
|
255 } |
|
256 if ( !mNoMusic ) { |
|
257 bool ok = false; |
|
258 mDocumentLoader->load( MUSIC_MEDIAWALL_DOCML, "empty", &ok); |
|
259 if ( ok ) { |
|
260 QGraphicsWidget *widget; |
|
261 widget = mDocumentLoader->findWidget(QString("noMusic")); |
|
262 mNoMusic = qobject_cast<HbLabel*>(widget); |
|
263 } |
|
264 else { |
|
265 TX_LOG_ARGS("Error: invalid xml file."); |
|
266 Q_ASSERT_X(ok, "MpMediaWallView::contextOpened", "invalid xml file"); |
|
267 |
|
268 } |
|
269 } |
|
270 } |
|
271 } |
|
272 |
|
273 /*! |
|
274 Slot to be called when the container contents changed. |
|
275 */ |
|
276 void MpMediaWallView::containerContentsChanged() |
|
277 { |
|
278 if ( !mLibraryUpdating && mEngine ) { |
|
279 mEngine->openCollection( ECollectionContextAlbumsMediaWall ); |
|
280 } |
|
281 } |
|
282 |
|
283 /*! |
|
284 Slot to be called when the container contents changed. |
|
285 */ |
|
286 void MpMediaWallView::libraryAboutToUpdate() |
|
287 { |
|
288 mLibraryUpdating = true; |
|
289 } |
|
290 |
|
291 /*! |
|
292 Slot to be called when the container contents changed. |
|
293 */ |
|
294 void MpMediaWallView::libraryUpdated() |
|
295 { |
|
296 mLibraryUpdating = false; |
|
297 if ( mEngine ) { |
|
298 mEngine->openCollection( ECollectionContextAlbumsMediaWall ); |
|
299 } |
|
300 } |
|
301 |
|
302 /*! |
|
303 Slot to be called to send to background. |
|
304 */ |
|
305 void MpMediaWallView::sendToBackground() |
|
306 { |
|
307 TX_ENTRY |
|
308 emit command( MpCommon::SendToBackground ); |
|
309 TX_EXIT |
|
310 } |
|
311 |
|
312 /*! |
|
313 Slot to update teh play pause action icon. |
|
314 */ |
|
315 void MpMediaWallView::updatePlayPauseAction() |
|
316 { |
|
317 if ( !mActivated ) { |
|
318 mIconUpdateNedded = true; |
|
319 return; |
|
320 } |
|
321 TX_ENTRY |
|
322 switch ( mPlaybackData->playbackState() ) { |
|
323 case MpPlaybackData::Playing: |
|
324 TX_LOG_ARGS( "MpPlaybackData::Playing" ) |
|
325 mPlayPauseAction->setIcon( *mPauseIcon ); |
|
326 mPlayPauseContainer->show(); |
|
327 break; |
|
328 case MpPlaybackData::Paused: |
|
329 case MpPlaybackData::Stopped: |
|
330 TX_LOG_ARGS( "MpPlaybackData::Paused" ) |
|
331 mPlayPauseAction->setIcon( *mPlayIcon ); |
|
332 mPlayPauseContainer->show(); |
|
333 break; |
|
334 case MpPlaybackData::NotPlaying: |
|
335 mPlayPauseContainer->hide(); |
|
336 break; |
|
337 default: |
|
338 break; |
|
339 } |
|
340 TX_EXIT |
|
341 } |
|
342 |
|
343 /*! |
|
344 Slot called to start the album and list opening animation. |
|
345 */ |
|
346 void MpMediaWallView::showTrackList() |
|
347 { |
|
348 if( mShowingSongsList ) { |
|
349 return; |
|
350 } |
|
351 mShowingSongsList = true; |
|
352 setUpListAnimation(); |
|
353 mListShowAnimationGroup->setDirection(QAbstractAnimation::Forward); |
|
354 mListShowAnimationGroup->start(); |
|
355 mModel->setItemVisibility( mMediaWallWidget->currentIndex(), false ); |
|
356 } |
|
357 |
|
358 /*! |
|
359 Slot to be called to starts the album and list closing animation. |
|
360 */ |
|
361 void MpMediaWallView::hideTracksList() |
|
362 { |
|
363 mListShowAnimationGroup->setDirection(QAbstractAnimation::Backward); |
|
364 connect(mListShowAnimationGroup, SIGNAL(finished()), this, SLOT(dismissListClosingAnimation())); |
|
365 mListShowAnimationGroup->start(); |
|
366 } |
|
367 |
|
368 /*! |
|
369 Slot to be called when list closing animation is done or when we want to cancel the animation. |
|
370 */ |
|
371 void MpMediaWallView::dismissListClosingAnimation() |
|
372 { |
|
373 if ( !mShowingSongsList ) { |
|
374 return; |
|
375 } |
|
376 mShowingSongsList = false; |
|
377 mAlbumCover->hide(); |
|
378 mTrackList->hide(); |
|
379 mModel->setItemVisibility( mMediaWallWidget->currentIndex(), true ); |
|
380 mListShowAnimationGroup->stop(); |
|
381 disconnect(mListShowAnimationGroup, SIGNAL(finished()), this, SLOT(dismissListClosingAnimation())); |
|
382 } |
|
383 |
|
384 /*! |
|
385 Slot to be called when a list item is selected by the user. |
|
386 */ |
|
387 void MpMediaWallView::listItemActivated( const QModelIndex &index ) |
|
388 { |
|
389 int albumIndex = mMediaWallWidget->currentIndex().row(); |
|
390 //We are playing on the shared engine, but we pass the collection data that |
|
391 //points to albums on media wall, this is used to construct the playlist. |
|
392 MpEngineFactory::sharedEngine()->playAlbumSongs( albumIndex, index.row(), mCollectionData ); |
|
393 } |
|
394 |
|
395 /*! |
|
396 Slot to be called to fetch the songs for an album. |
|
397 */ |
|
398 void MpMediaWallView::fetchAlbumSongs(QModelIndex index) |
|
399 { |
|
400 if ( !mCollectionData->setCurrentAlbum( index.row() ) ) { |
|
401 mEngine->findAlbumSongs( index.row() ); |
|
402 } |
|
403 } |
|
404 |
|
405 /*! |
|
406 Loads the media wall widget. |
|
407 */ |
|
408 void MpMediaWallView::setUpMediaWallWidget() |
|
409 { |
|
410 HbIcon defaultIcon( "qtg_large_album_art" ); |
|
411 defaultIcon.setSize(mMediaWallWidget->itemSize()); |
|
412 mMediaWallWidget->setDefaultImage( defaultIcon.pixmap().toImage() ); |
|
413 mMediaWallWidget->enableReflections( true ); |
|
414 mMediaWallWidget->setModel( mModel ); |
|
415 if ( mPlaybackData->playbackState() != MpPlaybackData::NotPlaying ) { |
|
416 scrollToNowPlaying(); |
|
417 } |
|
418 //The rest of the cases are attepting to balance the items on screen. |
|
419 else if ( mModel->rowCount() >= 5 ) { |
|
420 /* 5 and more |
|
421 [0] [1] [X] [3] [4]... |
|
422 */ |
|
423 QModelIndex index; |
|
424 index = mModel->index( 2 ); |
|
425 mMediaWallWidget->scrollTo( index ); |
|
426 } |
|
427 else if ( mModel->rowCount() >=3 ) { |
|
428 /* 4 and 3 |
|
429 __ [0] [X] [2] [3] |
|
430 __ [0] [X] [2] __ |
|
431 */ |
|
432 QModelIndex index; |
|
433 index = mModel->index( 1 ); |
|
434 mMediaWallWidget->scrollTo( index ); |
|
435 } |
|
436 else { |
|
437 /* 2 and 1 |
|
438 __ __ [X] [1] __ |
|
439 __ __ [X] __ __ |
|
440 */ |
|
441 QModelIndex index; |
|
442 index = mModel->index( 0 ); |
|
443 mMediaWallWidget->scrollTo( index ); |
|
444 } |
|
445 mMediaWallWidget->setTitleFontSpec( HbFontSpec( HbFontSpec::Primary ) ); |
|
446 mMediaWallWidget->setDescriptionFontSpec( HbFontSpec( HbFontSpec::Secondary ) ); |
|
447 mMediaWallWidget->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOn ); //HgWidget::ScrollBarAutoHide |
|
448 mMediaWallWidget->scrollBar()->setInteractive( true ); |
|
449 mMediaWallWidget->setIndexFeedbackPolicy( HgWidget::IndexFeedbackSingleCharacter ); |
|
450 connect(mMediaWallWidget, SIGNAL(animationAboutToEnd(QModelIndex)), SLOT(fetchAlbumSongs(QModelIndex))); |
|
451 connect(mMediaWallWidget, SIGNAL(activated(QModelIndex)), SLOT(showTrackList())); |
|
452 connect(mMediaWallWidget, SIGNAL(scrollingStarted()), SLOT(dismissListClosingAnimation())); |
|
453 } |
|
454 |
|
455 /*! |
|
456 Scrolls the media wall to now playing position. |
|
457 */ |
|
458 void MpMediaWallView::scrollToNowPlaying() |
|
459 { |
|
460 if ( mMediaWallWidget && mPlaybackData->playbackState() != MpPlaybackData::NotPlaying ) { |
|
461 int albumId = mPlaybackData->albumId(); |
|
462 QModelIndex index; |
|
463 index = mModel->index( mCollectionData->itemIndex( albumId ) ); |
|
464 mMediaWallWidget->scrollTo( index ); |
|
465 } |
|
466 } |
|
467 |
|
468 /*! |
|
469 Sets up the album and list animation. |
|
470 */ |
|
471 void MpMediaWallView::setUpListAnimation() |
|
472 { |
|
473 if ( !mListShowAnimationGroup ) { |
|
474 mListShowAnimationGroup = new QParallelAnimationGroup( this ); |
|
475 mCoverShowListAnimation = new QPropertyAnimation(mAlbumCover, "geometry", this ); |
|
476 mCoverShowListAnimation->setDuration( 400 ); |
|
477 mCoverShowListAnimation->setEasingCurve(QEasingCurve::InOutCubic); |
|
478 mListShowAnimationGroup->addAnimation(mCoverShowListAnimation); |
|
479 mListShowListAnimation = new QPropertyAnimation( mTrackList, "geometry", this ); |
|
480 mListShowListAnimation->setDuration( 400 ); |
|
481 mListShowListAnimation->setEasingCurve(QEasingCurve::InOutCubic); |
|
482 mListShowAnimationGroup->addAnimation(mListShowListAnimation); |
|
483 } |
|
484 |
|
485 //Get the current album cover geometry. |
|
486 QPolygonF poly; |
|
487 QModelIndex index = mMediaWallWidget->currentIndex(); |
|
488 if ( !mMediaWallWidget->getItemOutline( index, poly ) ) { |
|
489 return; |
|
490 } |
|
491 QRectF itemRect = poly.boundingRect(); |
|
492 |
|
493 //Get the album cover icon. |
|
494 QVariant image = mModel->data(index, Qt::DecorationRole); |
|
495 if ( image.canConvert<HbIcon>() ) { |
|
496 mAlbumCover->setIcon(image.value<HbIcon>()); |
|
497 } |
|
498 else { |
|
499 mAlbumCover->setIcon(HbIcon()); |
|
500 } |
|
501 |
|
502 //Mapping form local media wall coords to window coors. |
|
503 itemRect.moveTo( mMediaWallWidget->geometry().topLeft() + itemRect.topLeft()); |
|
504 //Calculate start and end position of items for the animation. |
|
505 QRectF endRect = itemRect; |
|
506 endRect.moveTo( endRect.topLeft().x() - endRect.size().width() / 2.0, endRect.topLeft().y() ); |
|
507 mCoverShowListAnimation->setStartValue(itemRect); |
|
508 mCoverShowListAnimation->setEndValue(endRect); |
|
509 endRect.moveTo( endRect.topRight() ); |
|
510 mListShowListAnimation->setStartValue(itemRect); |
|
511 mListShowListAnimation->setEndValue(endRect); |
|
512 |
|
513 //set initial condition and show to prevent flicker. |
|
514 mAlbumCover->setPos(itemRect.topLeft()); |
|
515 mTrackList->setPos(itemRect.topLeft()); |
|
516 mTrackList->setGeometry(itemRect); |
|
517 mAlbumCover->show(); |
|
518 mTrackList->show(); |
|
519 } |
|
520 |