34
|
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 collection container definition - Artists.
|
|
15 |
*
|
|
16 |
*/
|
|
17 |
|
|
18 |
#include <QtCore>
|
|
19 |
|
|
20 |
#include <hbdocumentloader.h>
|
|
21 |
#include <hblistview.h>
|
|
22 |
#include <hbgroupbox.h>
|
|
23 |
#include <hbindexfeedback.h>
|
|
24 |
|
35
|
25 |
#include <hgmediawall.h>
|
|
26 |
|
34
|
27 |
#include "mpcollectioncontainerartists.h"
|
|
28 |
#include "mpmpxcollectiondata.h"
|
35
|
29 |
#include "mpcollectiondatamodel.h"
|
|
30 |
#include "mpcollectiontbonelistdatamodel.h"
|
34
|
31 |
#include "mptrace.h"
|
|
32 |
|
|
33 |
/*!
|
|
34 |
\class MpCollectionContainerArtists
|
|
35 |
\brief Music Player collection container definition - Artists.
|
|
36 |
|
|
37 |
'Artists' collection container implements the interface specified
|
|
38 |
by MpCollectionContainer. It provides a layout and widgets for the
|
|
39 |
'Artists' view.
|
|
40 |
|
|
41 |
This container handles the following contexts:
|
|
42 |
\li ECollectionContextArtists
|
|
43 |
\li ECollectionContextArtistAlbums
|
35
|
44 |
\li ECollectionContextArtistAlbumsTBone
|
|
45 |
\li ECollectionContextArtistAllSongs
|
|
46 |
|
34
|
47 |
\sa MpCollectionContainer
|
|
48 |
*/
|
|
49 |
|
|
50 |
/*!
|
|
51 |
Constructs the collection container.
|
|
52 |
*/
|
|
53 |
MpCollectionContainerArtists::MpCollectionContainerArtists( HbDocumentLoader *loader, QGraphicsItem *parent )
|
|
54 |
: MpCollectionListContainer(loader, parent),
|
35
|
55 |
mInfoBar(0),
|
|
56 |
mTBone(0),
|
|
57 |
mTBoneListModel(0),
|
|
58 |
mCurrentArtistIndex(0),
|
|
59 |
mCurrentAlbumIndex(0)
|
34
|
60 |
{
|
|
61 |
TX_LOG
|
35
|
62 |
mCollectionContext = ECollectionContextArtists;
|
34
|
63 |
}
|
|
64 |
|
|
65 |
/*!
|
|
66 |
Destructs the collection container.
|
|
67 |
*/
|
|
68 |
MpCollectionContainerArtists::~MpCollectionContainerArtists()
|
|
69 |
{
|
|
70 |
TX_ENTRY
|
|
71 |
delete mInfoBar;
|
35
|
72 |
delete mTBone;
|
34
|
73 |
delete mList;
|
35
|
74 |
delete mTBoneListModel;
|
|
75 |
TX_EXIT
|
|
76 |
}
|
|
77 |
|
|
78 |
/*!
|
|
79 |
Sets the data model for the container.
|
|
80 |
*/
|
|
81 |
void MpCollectionContainerArtists::setDataModel( MpCollectionDataModel *dataModel )
|
|
82 |
{
|
|
83 |
TX_ENTRY_ARGS("mCollectionContext=" << mCollectionContext);
|
|
84 |
MpCollectionContainer::setDataModel(dataModel);
|
|
85 |
int count = mCollectionData->count();
|
|
86 |
switch ( mCollectionContext ) {
|
|
87 |
case ECollectionContextArtists:
|
|
88 |
if ( mList ) {
|
|
89 |
mList->setModel(dataModel);
|
|
90 |
if ( count ) {
|
|
91 |
if ( mCurrentArtistIndex >= count ) {
|
|
92 |
// This can happen if the last item is deleted
|
|
93 |
mCurrentArtistIndex = count - 1;
|
|
94 |
}
|
|
95 |
mList->scrollTo( dataModel->index(mCurrentArtistIndex, 0) );
|
|
96 |
}
|
|
97 |
// Reset the current album index for navigation:
|
|
98 |
// ECollectionContextArtistAlbums -> ECollectionContextArtists
|
|
99 |
mCurrentAlbumIndex = 0;
|
|
100 |
}
|
|
101 |
break;
|
|
102 |
case ECollectionContextArtistAlbums:
|
|
103 |
if ( mList ) {
|
|
104 |
mList->setModel(dataModel);
|
|
105 |
if ( count ) {
|
|
106 |
if ( mCurrentAlbumIndex >= count ) {
|
|
107 |
// This can happen if the last item is deleted
|
|
108 |
mCurrentAlbumIndex = count - 1;
|
|
109 |
}
|
|
110 |
mList->scrollTo( dataModel->index(mCurrentAlbumIndex, 0) );
|
|
111 |
}
|
|
112 |
// Reset the album index offset for navigation:
|
|
113 |
// ECollectionContextArtistAlbumsTBone -> ECollectionContextArtistAlbums
|
|
114 |
mAlbumIndexOffset = 0;
|
|
115 |
}
|
|
116 |
break;
|
|
117 |
case ECollectionContextArtistAlbumsTBone:
|
|
118 |
if ( mTBone ) {
|
|
119 |
if ( count > 1 ) {
|
|
120 |
// Selected artist has more than 1 album and therefore the
|
|
121 |
// artist's "All songs" exist. Since we don't show artist's
|
|
122 |
// "All songs" in TBone, we need to set an offset.
|
|
123 |
mAlbumIndexOffset = 1;
|
|
124 |
}
|
|
125 |
else {
|
|
126 |
// Selected artist has exactly 1 album and therefore the
|
|
127 |
// artist's "All songs" doesn't exist.
|
|
128 |
mAlbumIndexOffset = 0;
|
|
129 |
}
|
|
130 |
if ( mCurrentAlbumIndex >= count ) {
|
|
131 |
// This can happen if the last item is deleted
|
|
132 |
mCurrentAlbumIndex = count - 1;
|
|
133 |
}
|
|
134 |
mTBone->setModel(dataModel);
|
|
135 |
mTBone->scrollTo( dataModel->index(mCurrentAlbumIndex - mAlbumIndexOffset, 0) );
|
|
136 |
if ( mTBoneListModel == 0 ) {
|
|
137 |
mTBoneListModel = new MpCollectionTBoneListDataModel(mCollectionData);
|
|
138 |
connect( mTBoneListModel, SIGNAL(albumDataChanged()), this, SLOT(albumDataChanged()) );
|
|
139 |
}
|
|
140 |
mList->setModel(mTBoneListModel);
|
|
141 |
|
|
142 |
if ( !mCollectionData->setCurrentAlbum(mCurrentAlbumIndex) ) {
|
|
143 |
emit findAlbumSongs(mCurrentAlbumIndex);
|
|
144 |
}
|
|
145 |
}
|
|
146 |
break;
|
|
147 |
case ECollectionContextArtistAllSongs:
|
|
148 |
if ( mList ) {
|
|
149 |
mList->setModel(dataModel);
|
|
150 |
}
|
|
151 |
break;
|
|
152 |
default:
|
|
153 |
break;
|
|
154 |
}
|
34
|
155 |
TX_EXIT
|
|
156 |
}
|
|
157 |
|
|
158 |
/*!
|
|
159 |
Slot to be called when an item is selected by the user.
|
|
160 |
*/
|
|
161 |
void MpCollectionContainerArtists::itemActivated( const QModelIndex &index )
|
|
162 |
{
|
|
163 |
int row = index.row();
|
35
|
164 |
TX_ENTRY_ARGS("mCollectionContext=" << mCollectionContext << "index=" << row);
|
|
165 |
switch ( mCollectionContext ) {
|
|
166 |
case ECollectionContextArtists:
|
|
167 |
mCurrentArtistIndex = row;
|
|
168 |
TX_LOG_ARGS("mCurrentArtistIndex=" << mCurrentArtistIndex);
|
|
169 |
MpCollectionListContainer::itemActivated(index);
|
|
170 |
break;
|
|
171 |
case ECollectionContextArtistAlbums:
|
|
172 |
mCurrentAlbumIndex = row;
|
|
173 |
TX_LOG_ARGS("mCurrentAlbumIndex=" << mCurrentAlbumIndex);
|
|
174 |
MpCollectionListContainer::itemActivated(index);
|
|
175 |
break;
|
|
176 |
case ECollectionContextArtistAlbumsTBone:
|
|
177 |
TX_LOG_ARGS("mCurrentAlbumIndex=" << mCurrentAlbumIndex);
|
|
178 |
if ( mViewMode == MpCommon::FetchView ) {
|
|
179 |
MpCollectionListContainer::itemActivated(index);
|
|
180 |
}
|
|
181 |
else {
|
|
182 |
emit playAlbumSongs(mCurrentAlbumIndex, row);
|
|
183 |
}
|
|
184 |
break;
|
|
185 |
case ECollectionContextArtistAllSongs:
|
|
186 |
MpCollectionListContainer::itemActivated(index);
|
|
187 |
break;
|
|
188 |
default:
|
|
189 |
break;
|
|
190 |
}
|
|
191 |
TX_EXIT
|
|
192 |
}
|
|
193 |
|
|
194 |
/*!
|
|
195 |
Slot to be called when scrolling ends in media wall and an album is centered.
|
|
196 |
*/
|
|
197 |
void MpCollectionContainerArtists::albumCentered()
|
|
198 |
{
|
|
199 |
TX_ENTRY
|
|
200 |
int index = mTBone->currentIndex().row();
|
|
201 |
TX_LOG_ARGS("index=" << index);
|
|
202 |
index += mAlbumIndexOffset;
|
|
203 |
if ( mCurrentAlbumIndex != index ) {
|
|
204 |
// Prevent reloading if user just moves the center album a little
|
|
205 |
// and the same album re-centers.
|
|
206 |
mCurrentAlbumIndex = index;
|
|
207 |
TX_LOG_ARGS("mCurrentAlbumIndex=" << mCurrentAlbumIndex);
|
|
208 |
if ( !mCollectionData->setCurrentAlbum(mCurrentAlbumIndex) ) {
|
|
209 |
emit findAlbumSongs(mCurrentAlbumIndex);
|
34
|
210 |
}
|
|
211 |
}
|
35
|
212 |
TX_EXIT
|
|
213 |
}
|
|
214 |
|
|
215 |
/*!
|
|
216 |
Slot to be called data model has new data. This occurs after a delete operation is complete.
|
|
217 |
Two cases:
|
|
218 |
1) User deleted an artist.
|
|
219 |
2) User deleted last song in an album.
|
|
220 |
*/
|
|
221 |
void MpCollectionContainerArtists::dataReloaded()
|
|
222 |
{
|
|
223 |
TX_ENTRY
|
|
224 |
if ( mCollectionContext == ECollectionContextArtistAlbumsTBone ) {
|
|
225 |
if ( mCurrentAlbumIndex > 0 ) {
|
|
226 |
--mCurrentAlbumIndex;
|
|
227 |
}
|
|
228 |
mTBone->scrollTo( mDataModel->index(mCurrentAlbumIndex - mAlbumIndexOffset, 0) );
|
|
229 |
if ( !mCollectionData->setCurrentAlbum(mCurrentAlbumIndex) ) {
|
|
230 |
emit findAlbumSongs(mCurrentAlbumIndex);
|
34
|
231 |
}
|
|
232 |
}
|
35
|
233 |
else {
|
|
234 |
MpCollectionListContainer::dataReloaded();
|
|
235 |
}
|
|
236 |
TX_EXIT
|
|
237 |
}
|
|
238 |
|
|
239 |
/*!
|
|
240 |
Slot to be called data model has new data.
|
|
241 |
User has deleted one of the songs from TBone list.
|
|
242 |
*/
|
|
243 |
void MpCollectionContainerArtists::albumDataChanged()
|
|
244 |
{
|
|
245 |
TX_ENTRY
|
|
246 |
emit findAlbumSongs(mCurrentAlbumIndex);
|
34
|
247 |
TX_EXIT
|
|
248 |
}
|
|
249 |
|
|
250 |
/*!
|
|
251 |
Sets up the container by organizing widgets according to its layout.
|
|
252 |
|
|
253 |
\reimp
|
|
254 |
*/
|
|
255 |
void MpCollectionContainerArtists::setupContainer()
|
|
256 |
{
|
|
257 |
TX_ENTRY_ARGS("mCollectionContext=" << mCollectionContext);
|
|
258 |
if ( mCollectionData->count() ) {
|
|
259 |
bool ok = false;
|
|
260 |
QGraphicsWidget *widget;
|
35
|
261 |
QString artist;
|
|
262 |
switch ( mCollectionContext ) {
|
|
263 |
case ECollectionContextArtists:
|
|
264 |
mDocumentLoader->load(QString(":/docml/musiccollection.docml"), "artists", &ok);
|
|
265 |
if ( !ok ) {
|
|
266 |
TX_LOG_ARGS("Error: invalid xml file.");
|
|
267 |
Q_ASSERT_X(ok, "MpCollectionContainerArtists::setupContainer", "invalid xml file");
|
|
268 |
}
|
|
269 |
if ( !mList ) {
|
|
270 |
widget = mDocumentLoader->findWidget(QString("artistsList"));
|
|
271 |
mList = qobject_cast<HbListView*>(widget);
|
|
272 |
mIndexFeedback->setItemView(mList);
|
|
273 |
initializeList();
|
|
274 |
}
|
|
275 |
if ( mInfoBar ) {
|
|
276 |
delete mInfoBar;
|
|
277 |
mInfoBar = 0;
|
|
278 |
}
|
|
279 |
if ( mTBone ) {
|
|
280 |
delete mTBone;
|
|
281 |
mTBone = 0;
|
|
282 |
}
|
|
283 |
break;
|
|
284 |
case ECollectionContextArtistAlbums:
|
|
285 |
mDocumentLoader->load(QString(":/docml/musiccollection.docml"), "artistAlbums", &ok);
|
|
286 |
if ( !ok ) {
|
|
287 |
TX_LOG_ARGS("Error: invalid xml file.");
|
|
288 |
Q_ASSERT_X(ok, "MpCollectionContainerArtists::setupContainer", "invalid xml file");
|
|
289 |
}
|
|
290 |
widget = mDocumentLoader->findWidget(QString("artistDetail"));
|
|
291 |
mInfoBar = qobject_cast<HbGroupBox*>(widget);
|
|
292 |
|
|
293 |
artist = mCollectionData->collectionTitle();
|
|
294 |
if ( artist.isEmpty() ) {
|
|
295 |
artist = hbTrId("txt_mus_subtitle_unknown");
|
|
296 |
}
|
|
297 |
mInfoBar->setHeading(artist);
|
|
298 |
if ( mTBone ) {
|
|
299 |
delete mTBone;
|
|
300 |
mTBone = 0;
|
|
301 |
}
|
|
302 |
break;
|
|
303 |
case ECollectionContextArtistAlbumsTBone:
|
|
304 |
{
|
|
305 |
if ( mViewMode == MpCommon::FetchView ) {
|
|
306 |
mDocumentLoader->load(QString(":/docml/musiccollection.docml"), "artistAlbumTBoneFetcher", &ok);
|
|
307 |
if ( !ok ) {
|
|
308 |
TX_LOG_ARGS("Error: invalid xml file.");
|
|
309 |
Q_ASSERT_X(ok, "MpCollectionContainerAlbums::setupContainer", "invalid xml file");
|
|
310 |
}
|
|
311 |
widget = mDocumentLoader->findWidget(QString("artistDetail"));
|
|
312 |
mInfoBar = qobject_cast<HbGroupBox*>(widget);
|
|
313 |
mInfoBar->setHeading( hbTrId("txt_mus_subtitle_select_a_song") );
|
|
314 |
}
|
|
315 |
else {
|
|
316 |
mDocumentLoader->load(QString(":/docml/musiccollection.docml"), "artistAlbumTBone", &ok);
|
|
317 |
if ( !ok ) {
|
|
318 |
TX_LOG_ARGS("Error: invalid xml file.");
|
|
319 |
Q_ASSERT_X(ok, "MpCollectionContainerAlbums::setupContainer", "invalid xml file");
|
|
320 |
}
|
|
321 |
if ( mInfoBar ) {
|
|
322 |
delete mInfoBar;
|
|
323 |
mInfoBar = 0;
|
|
324 |
}
|
|
325 |
}
|
|
326 |
widget = mDocumentLoader->findWidget(QString("artistAlbumWall"));
|
|
327 |
mTBone = qobject_cast<HgMediawall*>(widget);
|
|
328 |
HbIcon defaultIcon( "qtg_large_music_album" );
|
|
329 |
defaultIcon.setSize(mTBone->itemSize());
|
|
330 |
mTBone->setDefaultImage( defaultIcon.pixmap().toImage() );
|
|
331 |
mTBone->setTitleFontSpec( HbFontSpec(HbFontSpec::Primary) );
|
|
332 |
mTBone->setDescriptionFontSpec( HbFontSpec(HbFontSpec::Secondary) );
|
|
333 |
mTBone->setScrollBarPolicy( HgWidget::ScrollBarAlwaysOff );
|
|
334 |
mTBone->enableReflections(true);
|
|
335 |
connect( mTBone, SIGNAL(scrollingEnded()), this, SLOT(albumCentered()) );
|
|
336 |
}
|
|
337 |
break;
|
|
338 |
case ECollectionContextArtistAllSongs:
|
|
339 |
// No need to load anything. Just reuse the section "artistAlbums" loaded
|
|
340 |
// in ECollectionContextArtistAlbums context.
|
|
341 |
if ( mViewMode == MpCommon::FetchView ) {
|
|
342 |
mInfoBar->setHeading( hbTrId("txt_mus_subtitle_select_a_song") );
|
|
343 |
}
|
|
344 |
else {
|
|
345 |
artist = mCollectionData->collectionTitle();
|
|
346 |
if ( artist.isEmpty() ) {
|
|
347 |
artist = hbTrId("txt_mus_subtitle_unknown_all");
|
|
348 |
}
|
|
349 |
else {
|
|
350 |
artist = hbTrId("txt_mus_subtitle_1_all").arg(artist);
|
|
351 |
}
|
|
352 |
mInfoBar->setHeading(artist);
|
|
353 |
}
|
|
354 |
break;
|
|
355 |
default:
|
|
356 |
break;
|
34
|
357 |
}
|
35
|
358 |
}
|
34
|
359 |
else {
|
35
|
360 |
// Must delete widgets when last song is deleted and view is reloaded.
|
34
|
361 |
if ( mInfoBar ) {
|
|
362 |
delete mInfoBar;
|
|
363 |
mInfoBar = 0;
|
|
364 |
}
|
35
|
365 |
if ( mTBone ) {
|
|
366 |
delete mTBone;
|
|
367 |
mTBone = 0;
|
|
368 |
}
|
34
|
369 |
// Call empty list from base class
|
|
370 |
setupEmptyListContainer();
|
|
371 |
}
|
|
372 |
TX_EXIT
|
|
373 |
}
|
|
374 |
|