~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/libtomahawk/playlist/PlayableModel.cpp

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
 
2
 *
 
3
 *   Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
 
4
 *   Copyright 2011       Leo Franchi <lfranchi@kde.org>
 
5
 *   Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
 
6
 *
 
7
 *   Tomahawk is free software: you can redistribute it and/or modify
 
8
 *   it under the terms of the GNU General Public License as published by
 
9
 *   the Free Software Foundation, either version 3 of the License, or
 
10
 *   (at your option) any later version.
 
11
 *
 
12
 *   Tomahawk is distributed in the hope that it will be useful,
 
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
15
 *   GNU General Public License for more details.
 
16
 *
 
17
 *   You should have received a copy of the GNU General Public License
 
18
 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#include "PlayableModel.h"
 
22
 
 
23
#include <QDateTime>
 
24
#include <QMimeData>
 
25
#include <QTreeView>
 
26
 
 
27
#include "Artist.h"
 
28
#include "Album.h"
 
29
#include "Pipeline.h"
 
30
#include "PlayableItem.h"
 
31
#include "PlayableProxyModel.h"
 
32
#include "Source.h"
 
33
#include "Typedefs.h"
 
34
#include "audio/AudioEngine.h"
 
35
#include "utils/TomahawkUtils.h"
 
36
#include "utils/Logger.h"
 
37
 
 
38
using namespace Tomahawk;
 
39
 
 
40
 
 
41
PlayableModel::PlayableModel( QObject* parent, bool loading )
 
42
    : QAbstractItemModel( parent )
 
43
    , m_rootItem( new PlayableItem( 0 ) )
 
44
    , m_readOnly( true )
 
45
    , m_loading( loading )
 
46
{
 
47
    connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection );
 
48
    connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection );
 
49
 
 
50
    m_header << tr( "Artist" ) << tr( "Title" ) << tr( "Composer" ) << tr( "Album" ) << tr( "Track" ) << tr( "Duration" )
 
51
             << tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Accuracy" ) << tr( "Name" );
 
52
}
 
53
 
 
54
 
 
55
PlayableModel::~PlayableModel()
 
56
{
 
57
}
 
58
 
 
59
 
 
60
QModelIndex
 
61
PlayableModel::createIndex( int row, int column, PlayableItem* item ) const
 
62
{
 
63
    if ( item->query() )
 
64
    {
 
65
        connect( item->query().data(), SIGNAL( playableStateChanged( bool ) ), SLOT( onQueryBecamePlayable( bool ) ), Qt::UniqueConnection );
 
66
        connect( item->query().data(), SIGNAL( resolvingFinished( bool ) ), SLOT( onQueryResolved( bool ) ), Qt::UniqueConnection );
 
67
    }
 
68
 
 
69
    return QAbstractItemModel::createIndex( row, column, item );
 
70
}
 
71
 
 
72
 
 
73
QModelIndex
 
74
PlayableModel::index( int row, int column, const QModelIndex& parent ) const
 
75
{
 
76
    if ( !m_rootItem || row < 0 || column < 0 )
 
77
        return QModelIndex();
 
78
 
 
79
    PlayableItem* parentItem = itemFromIndex( parent );
 
80
    PlayableItem* childItem = parentItem->children.value( row );
 
81
    if ( !childItem )
 
82
        return QModelIndex();
 
83
 
 
84
    return createIndex( row, column, childItem );
 
85
}
 
86
 
 
87
 
 
88
int
 
89
PlayableModel::rowCount( const QModelIndex& parent ) const
 
90
{
 
91
    if ( parent.column() > 0 )
 
92
        return 0;
 
93
 
 
94
    PlayableItem* parentItem = itemFromIndex( parent );
 
95
    if ( !parentItem )
 
96
        return 0;
 
97
 
 
98
    return parentItem->children.count();
 
99
}
 
100
 
 
101
 
 
102
int
 
103
PlayableModel::columnCount( const QModelIndex& parent ) const
 
104
{
 
105
    Q_UNUSED( parent );
 
106
 
 
107
    return 12;
 
108
}
 
109
 
 
110
 
 
111
bool
 
112
PlayableModel::hasChildren( const QModelIndex& parent ) const
 
113
{
 
114
    PlayableItem* parentItem = itemFromIndex( parent );
 
115
    if ( !parentItem )
 
116
        return false;
 
117
 
 
118
    if ( parentItem == m_rootItem )
 
119
        return true;
 
120
 
 
121
    return ( !parentItem->artist().isNull() || !parentItem->album().isNull() );
 
122
}
 
123
 
 
124
 
 
125
QModelIndex
 
126
PlayableModel::parent( const QModelIndex& child ) const
 
127
{
 
128
    PlayableItem* entry = itemFromIndex( child );
 
129
    if ( !entry )
 
130
        return QModelIndex();
 
131
 
 
132
    PlayableItem* parentEntry = entry->parent();
 
133
    if ( !parentEntry )
 
134
        return QModelIndex();
 
135
 
 
136
    PlayableItem* grandparentEntry = parentEntry->parent();
 
137
    if ( !grandparentEntry )
 
138
        return QModelIndex();
 
139
 
 
140
    int row = grandparentEntry->children.indexOf( parentEntry );
 
141
    return createIndex( row, 0, parentEntry );
 
142
}
 
143
 
 
144
 
 
145
QVariant
 
146
PlayableModel::artistData( const artist_ptr& artist, int role ) const
 
147
{
 
148
    if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
 
149
        return QVariant();
 
150
 
 
151
    return artist->name();
 
152
}
 
153
 
 
154
 
 
155
QVariant
 
156
PlayableModel::albumData( const album_ptr& album, int role ) const
 
157
{
 
158
    if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
 
159
        return QVariant();
 
160
 
 
161
    return album->name();
 
162
}
 
163
 
 
164
 
 
165
QVariant
 
166
PlayableModel::queryData( const query_ptr& query, int column, int role ) const
 
167
{
 
168
    if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
 
169
        return QVariant();
 
170
 
 
171
    switch ( column )
 
172
    {
 
173
        case Artist:
 
174
            return query->artist();
 
175
            break;
 
176
 
 
177
        case Name:
 
178
        case Track:
 
179
            return query->track();
 
180
            break;
 
181
 
 
182
        case Album:
 
183
            return query->album();
 
184
            break;
 
185
 
 
186
        case Composer:
 
187
            return query->composer();
 
188
            break;
 
189
 
 
190
        case Duration:
 
191
            return TomahawkUtils::timeToString( query->duration() );
 
192
            break;
 
193
 
 
194
        case AlbumPos:
 
195
        {
 
196
            QString tPos;
 
197
            if ( query->albumpos() != 0 )
 
198
            {
 
199
                tPos = QString::number( query->albumpos() );
 
200
                if ( query->discnumber() == 0 )
 
201
                    return tPos;
 
202
                else
 
203
                    return QString( "%1.%2" ).arg( QString::number( query->discnumber() ) )
 
204
                                             .arg( tPos );
 
205
            }
 
206
        }
 
207
        break;
 
208
 
 
209
        default:
 
210
            break;
 
211
    }
 
212
    if ( query->numResults() )
 
213
    {
 
214
        switch ( column )
 
215
        {
 
216
            case Bitrate:
 
217
                if ( query->results().first()->bitrate() > 0 )
 
218
                    return query->results().first()->bitrate();
 
219
                break;
 
220
 
 
221
            case Age:
 
222
                return TomahawkUtils::ageToString( QDateTime::fromTime_t( query->results().first()->modificationTime() ) );
 
223
                break;
 
224
 
 
225
            case Year:
 
226
                if ( query->results().first()->year() != 0 )
 
227
                    return query->results().first()->year();
 
228
                break;
 
229
 
 
230
            case Filesize:
 
231
                return TomahawkUtils::filesizeToString( query->results().first()->size() );
 
232
                break;
 
233
 
 
234
            case Origin:
 
235
                return query->results().first()->friendlySource();
 
236
                break;
 
237
 
 
238
            case Score:
 
239
            {
 
240
                float score = query->results().first()->score();
 
241
                if ( score == 1.0 )
 
242
                    return tr( "Perfect match" );
 
243
                if ( score > 0.9 )
 
244
                    return tr( "Very good match" );
 
245
                if ( score > 0.7 )
 
246
                    return tr( "Good match" );
 
247
                if ( score > 0.5 )
 
248
                    return tr( "Vague match" );
 
249
                if ( score > 0.3 )
 
250
                    return tr( "Bad match" );
 
251
                if ( score > 0.0 )
 
252
                    return tr( "Very bad match" );
 
253
                
 
254
                return tr( "Not available" );
 
255
                break;
 
256
            }
 
257
 
 
258
            default:
 
259
                break;
 
260
        }
 
261
    }
 
262
 
 
263
    return QVariant();
 
264
}
 
265
 
 
266
 
 
267
QVariant
 
268
PlayableModel::data( const QModelIndex& index, int role ) const
 
269
{
 
270
    PlayableItem* entry = itemFromIndex( index );
 
271
    if ( !entry )
 
272
        return QVariant();
 
273
 
 
274
    if ( role == Qt::DecorationRole )
 
275
    {
 
276
        return QVariant();
 
277
    }
 
278
    else if ( role == Qt::TextAlignmentRole )
 
279
    {
 
280
        return QVariant( columnAlignment( index.column() ) );
 
281
    }
 
282
    else if ( role == PlayableProxyModel::TypeRole )
 
283
    {
 
284
        if ( entry->result() )
 
285
        {
 
286
            return Tomahawk::TypeResult;
 
287
        }
 
288
        else if ( entry->query() )
 
289
        {
 
290
            return Tomahawk::TypeQuery;
 
291
        }
 
292
        else if ( entry->artist() )
 
293
        {
 
294
            return Tomahawk::TypeArtist;
 
295
        }
 
296
        else if ( entry->album() )
 
297
        {
 
298
            return Tomahawk::TypeAlbum;
 
299
        }
 
300
    }
 
301
 
 
302
    if ( !entry->query().isNull() )
 
303
    {
 
304
        return queryData( entry->query()->displayQuery(), index.column(), role );
 
305
    }
 
306
    else if ( !entry->artist().isNull() )
 
307
    {
 
308
        return artistData( entry->artist(), role );
 
309
    }
 
310
    else if ( !entry->album().isNull() )
 
311
    {
 
312
        return albumData( entry->album(), role );
 
313
    }
 
314
 
 
315
    return QVariant();
 
316
}
 
317
 
 
318
 
 
319
QVariant
 
320
PlayableModel::headerData( int section, Qt::Orientation orientation, int role ) const
 
321
{
 
322
    Q_UNUSED( orientation );
 
323
 
 
324
    if ( role == Qt::DisplayRole && section >= 0 )
 
325
    {
 
326
        if ( section < m_header.count() )
 
327
            return m_header.at( section );
 
328
        else
 
329
            return tr( "Name" );
 
330
    }
 
331
 
 
332
    if ( role == Qt::TextAlignmentRole )
 
333
    {
 
334
        return QVariant( columnAlignment( section ) );
 
335
    }
 
336
 
 
337
    return QVariant();
 
338
}
 
339
 
 
340
 
 
341
void
 
342
PlayableModel::setCurrentIndex( const QModelIndex& index )
 
343
{
 
344
    PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
 
345
    if ( oldEntry )
 
346
    {
 
347
        oldEntry->setIsPlaying( false );
 
348
    }
 
349
 
 
350
    PlayableItem* entry = itemFromIndex( index );
 
351
    if ( index.isValid() && entry && !entry->query().isNull() )
 
352
    {
 
353
        m_currentIndex = index;
 
354
        m_currentUuid = entry->query()->id();
 
355
        entry->setIsPlaying( true );
 
356
    }
 
357
    else
 
358
    {
 
359
        m_currentIndex = QModelIndex();
 
360
        m_currentUuid = QString();
 
361
    }
 
362
 
 
363
    emit currentIndexChanged();
 
364
}
 
365
 
 
366
 
 
367
Qt::DropActions
 
368
PlayableModel::supportedDropActions() const
 
369
{
 
370
    return Qt::CopyAction | Qt::MoveAction;
 
371
}
 
372
 
 
373
 
 
374
Qt::ItemFlags
 
375
PlayableModel::flags( const QModelIndex& index ) const
 
376
{
 
377
    Qt::ItemFlags defaultFlags = QAbstractItemModel::flags( index );
 
378
 
 
379
    if ( index.isValid() && index.column() == 0 )
 
380
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
 
381
    else
 
382
        return Qt::ItemIsDropEnabled | defaultFlags;
 
383
}
 
384
 
 
385
 
 
386
QStringList
 
387
PlayableModel::mimeTypes() const
 
388
{
 
389
    QStringList types;
 
390
    types << "application/tomahawk.mixed";
 
391
    return types;
 
392
}
 
393
 
 
394
 
 
395
QMimeData*
 
396
PlayableModel::mimeData( const QModelIndexList &indexes ) const
 
397
{
 
398
    qDebug() << Q_FUNC_INFO;
 
399
 
 
400
    QByteArray resultData;
 
401
    QDataStream resultStream( &resultData, QIODevice::WriteOnly );
 
402
 
 
403
    // lets try with artist only
 
404
    bool fail = false;
 
405
    foreach ( const QModelIndex& i, indexes )
 
406
    {
 
407
        if ( i.column() > 0 || indexes.contains( i.parent() ) )
 
408
            continue;
 
409
 
 
410
        PlayableItem* item = itemFromIndex( i );
 
411
        if ( !item )
 
412
            continue;
 
413
 
 
414
        if ( !item->artist().isNull() )
 
415
        {
 
416
            const artist_ptr& artist = item->artist();
 
417
            resultStream << artist->name();
 
418
        }
 
419
        else
 
420
        {
 
421
            fail = true;
 
422
            break;
 
423
        }
 
424
    }
 
425
    if ( !fail )
 
426
    {
 
427
        QMimeData* mimeData = new QMimeData();
 
428
        mimeData->setData( "application/tomahawk.metadata.artist", resultData );
 
429
        return mimeData;
 
430
    }
 
431
 
 
432
    // lets try with album only
 
433
    fail = false;
 
434
    resultData.clear();
 
435
    foreach ( const QModelIndex& i, indexes )
 
436
    {
 
437
        if ( i.column() > 0 || indexes.contains( i.parent() ) )
 
438
            continue;
 
439
 
 
440
        PlayableItem* item = itemFromIndex( i );
 
441
        if ( !item )
 
442
            continue;
 
443
 
 
444
        if ( !item->album().isNull() )
 
445
        {
 
446
            const album_ptr& album = item->album();
 
447
            resultStream << album->artist()->name();
 
448
            resultStream << album->name();
 
449
        }
 
450
        else
 
451
        {
 
452
            fail = true;
 
453
            break;
 
454
        }
 
455
    }
 
456
    if ( !fail )
 
457
    {
 
458
        QMimeData* mimeData = new QMimeData();
 
459
        mimeData->setData( "application/tomahawk.metadata.album", resultData );
 
460
        return mimeData;
 
461
    }
 
462
 
 
463
    // lets try with tracks only
 
464
    fail = false;
 
465
    resultData.clear();
 
466
    foreach ( const QModelIndex& i, indexes )
 
467
    {
 
468
        if ( i.column() > 0 || indexes.contains( i.parent() ) )
 
469
            continue;
 
470
 
 
471
        PlayableItem* item = itemFromIndex( i );
 
472
        if ( !item )
 
473
            continue;
 
474
 
 
475
        if ( !item->result().isNull() )
 
476
        {
 
477
            const result_ptr& result = item->result();
 
478
            resultStream << qlonglong( &result );
 
479
        }
 
480
        else
 
481
        {
 
482
            fail = true;
 
483
            break;
 
484
        }
 
485
    }
 
486
    if ( !fail )
 
487
    {
 
488
        QMimeData* mimeData = new QMimeData();
 
489
        mimeData->setData( "application/tomahawk.result.list", resultData );
 
490
        return mimeData;
 
491
    }
 
492
 
 
493
    // Ok... we have to use mixed
 
494
    resultData.clear();
 
495
    QDataStream mixedStream( &resultData, QIODevice::WriteOnly );
 
496
    foreach ( const QModelIndex& i, indexes )
 
497
    {
 
498
        if ( i.column() > 0 || indexes.contains( i.parent() ) )
 
499
            continue;
 
500
 
 
501
        PlayableItem* item = itemFromIndex( i );
 
502
        if ( !item )
 
503
            continue;
 
504
 
 
505
        if ( !item->artist().isNull() )
 
506
        {
 
507
            const artist_ptr& artist = item->artist();
 
508
            mixedStream << QString( "application/tomahawk.metadata.artist" ) << artist->name();
 
509
        }
 
510
        else if ( !item->album().isNull() )
 
511
        {
 
512
            const album_ptr& album = item->album();
 
513
            mixedStream << QString( "application/tomahawk.metadata.album" ) << album->artist()->name() << album->name();
 
514
        }
 
515
        else if ( !item->result().isNull() )
 
516
        {
 
517
            const result_ptr& result = item->result();
 
518
            mixedStream << QString( "application/tomahawk.result.list" ) << qlonglong( &result );
 
519
        }
 
520
        else if ( !item->query().isNull() )
 
521
        {
 
522
            const query_ptr& query = item->query();
 
523
            mixedStream << QString( "application/tomahawk.query.list" ) << qlonglong( &query );
 
524
        }
 
525
    }
 
526
 
 
527
    QMimeData* mimeData = new QMimeData();
 
528
    mimeData->setData( "application/tomahawk.mixed", resultData );
 
529
    return mimeData;
 
530
}
 
531
 
 
532
 
 
533
void
 
534
PlayableModel::clear()
 
535
{
 
536
    if ( rowCount( QModelIndex() ) )
 
537
    {
 
538
        finishLoading();
 
539
 
 
540
        emit beginResetModel();
 
541
        delete m_rootItem;
 
542
        m_rootItem = 0;
 
543
        m_rootItem = new PlayableItem( 0 );
 
544
        emit endResetModel();
 
545
    }
 
546
}
 
547
 
 
548
 
 
549
QList< query_ptr >
 
550
PlayableModel::queries() const
 
551
{
 
552
    Q_ASSERT( m_rootItem );
 
553
 
 
554
    QList< query_ptr > tracks;
 
555
    foreach ( PlayableItem* item, m_rootItem->children )
 
556
    {
 
557
        tracks << item->query();
 
558
    }
 
559
 
 
560
    return tracks;
 
561
}
 
562
 
 
563
 
 
564
template <typename T>
 
565
void
 
566
PlayableModel::insertInternal( const QList< T >& items, int row )
 
567
{
 
568
    if ( !items.count() )
 
569
    {
 
570
        emit itemCountChanged( rowCount( QModelIndex() ) );
 
571
 
 
572
        finishLoading();
 
573
        return;
 
574
    }
 
575
 
 
576
    int c = row;
 
577
    QPair< int, int > crows;
 
578
    crows.first = c;
 
579
    crows.second = c + items.count() - 1;
 
580
 
 
581
    emit beginInsertRows( QModelIndex(), crows.first, crows.second );
 
582
 
 
583
    int i = 0;
 
584
    PlayableItem* plitem;
 
585
    foreach ( const T& item, items )
 
586
    {
 
587
        plitem = new PlayableItem( item, m_rootItem, row + i );
 
588
        plitem->index = createIndex( row + i, 0, plitem );
 
589
        i++;
 
590
 
 
591
/*        if ( item->id() == currentItemUuid() )
 
592
            setCurrentItem( plitem->index );*/
 
593
 
 
594
        connect( plitem, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) );
 
595
    }
 
596
 
 
597
    emit endInsertRows();
 
598
    emit itemCountChanged( rowCount( QModelIndex() ) );
 
599
    finishLoading();
 
600
}
 
601
 
 
602
 
 
603
void
 
604
PlayableModel::remove( int row, bool moreToCome )
 
605
{
 
606
    removeIndex( index( row, 0, QModelIndex() ), moreToCome );
 
607
}
 
608
 
 
609
 
 
610
void
 
611
PlayableModel::removeIndex( const QModelIndex& index, bool moreToCome )
 
612
{
 
613
    if ( QThread::currentThread() != thread() )
 
614
    {
 
615
        QMetaObject::invokeMethod( this, "remove",
 
616
                                   Qt::QueuedConnection,
 
617
                                   Q_ARG(const QModelIndex, index),
 
618
                                   Q_ARG(bool, moreToCome) );
 
619
        return;
 
620
    }
 
621
 
 
622
    if ( index.column() > 0 )
 
623
        return;
 
624
 
 
625
    PlayableItem* item = itemFromIndex( index );
 
626
    if ( item )
 
627
    {
 
628
        if ( index == m_currentIndex )
 
629
            setCurrentIndex( QModelIndex() );
 
630
            
 
631
        emit beginRemoveRows( index.parent(), index.row(), index.row() );
 
632
        delete item;
 
633
        emit endRemoveRows();
 
634
    }
 
635
 
 
636
    if ( !moreToCome )
 
637
        emit itemCountChanged( rowCount( QModelIndex() ) );
 
638
}
 
639
 
 
640
 
 
641
void
 
642
PlayableModel::removeIndexes( const QList<QModelIndex>& indexes )
 
643
{
 
644
    QList<QPersistentModelIndex> pil;
 
645
    foreach ( const QModelIndex& idx, indexes )
 
646
    {
 
647
        pil << idx;
 
648
    }
 
649
 
 
650
    removeIndexes( pil );
 
651
}
 
652
 
 
653
 
 
654
void
 
655
PlayableModel::removeIndexes( const QList<QPersistentModelIndex>& indexes )
 
656
{
 
657
    QList<QPersistentModelIndex> finalIndexes;
 
658
    foreach ( const QPersistentModelIndex index, indexes )
 
659
    {
 
660
        if ( index.column() > 0 )
 
661
            continue;
 
662
        finalIndexes << index;
 
663
    }
 
664
 
 
665
    for ( int i = 0; i < finalIndexes.count(); i++ )
 
666
    {
 
667
        removeIndex( finalIndexes.at( i ), i + 1 != finalIndexes.count() );
 
668
    }
 
669
}
 
670
 
 
671
 
 
672
void
 
673
PlayableModel::onPlaybackStarted( const Tomahawk::result_ptr& result )
 
674
{
 
675
    PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
 
676
    if ( oldEntry && ( oldEntry->query().isNull() || !oldEntry->query()->numResults() || oldEntry->query()->results().first().data() != result.data() ) )
 
677
    {
 
678
        oldEntry->setIsPlaying( false );
 
679
    }
 
680
}
 
681
 
 
682
 
 
683
void
 
684
PlayableModel::onPlaybackStopped()
 
685
{
 
686
    PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
 
687
    if ( oldEntry )
 
688
    {
 
689
        oldEntry->setIsPlaying( false );
 
690
    }
 
691
}
 
692
 
 
693
 
 
694
void
 
695
PlayableModel::ensureResolved()
 
696
{
 
697
    for( int i = 0; i < rowCount( QModelIndex() ); i++ )
 
698
    {
 
699
        query_ptr query = itemFromIndex( index( i, 0, QModelIndex() ) )->query();
 
700
 
 
701
        if ( !query->resolvingFinished() )
 
702
            Pipeline::instance()->resolve( query );
 
703
    }
 
704
}
 
705
 
 
706
 
 
707
Qt::Alignment
 
708
PlayableModel::columnAlignment( int column ) const
 
709
{
 
710
    switch ( column )
 
711
    {
 
712
        case Age:
 
713
        case AlbumPos:
 
714
        case Bitrate:
 
715
        case Duration:
 
716
        case Filesize:
 
717
        case Score:
 
718
        case Year:
 
719
            return Qt::AlignHCenter;
 
720
            break;
 
721
 
 
722
        default:
 
723
            return Qt::AlignLeft;
 
724
    }
 
725
}
 
726
 
 
727
 
 
728
void
 
729
PlayableModel::onDataChanged()
 
730
{
 
731
    PlayableItem* p = (PlayableItem*)sender();
 
732
    if ( p && p->index.isValid() )
 
733
        emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) );
 
734
}
 
735
 
 
736
 
 
737
void
 
738
PlayableModel::startLoading()
 
739
{
 
740
    m_loading = true;
 
741
    emit loadingStarted();
 
742
}
 
743
 
 
744
 
 
745
void
 
746
PlayableModel::finishLoading()
 
747
{
 
748
    m_loading = false;
 
749
    emit loadingFinished();
 
750
}
 
751
 
 
752
 
 
753
PlayableItem*
 
754
PlayableModel::itemFromIndex( const QModelIndex& index ) const
 
755
{
 
756
    if ( index.isValid() )
 
757
    {
 
758
        return static_cast<PlayableItem*>( index.internalPointer() );
 
759
    }
 
760
    else
 
761
    {
 
762
        return m_rootItem;
 
763
    }
 
764
}
 
765
 
 
766
 
 
767
void
 
768
PlayableModel::appendArtist( const Tomahawk::artist_ptr& artist )
 
769
{
 
770
    QList< artist_ptr > artists;
 
771
    artists << artist;
 
772
 
 
773
    appendArtists( artists );
 
774
}
 
775
 
 
776
 
 
777
void
 
778
PlayableModel::appendAlbum( const Tomahawk::album_ptr& album )
 
779
{
 
780
    QList< album_ptr > albums;
 
781
    albums << album;
 
782
 
 
783
    appendAlbums( albums );
 
784
}
 
785
 
 
786
 
 
787
void
 
788
PlayableModel::appendQuery( const Tomahawk::query_ptr& query )
 
789
{
 
790
    QList< query_ptr > queries;
 
791
    queries << query;
 
792
 
 
793
    appendQueries( queries );
 
794
}
 
795
 
 
796
 
 
797
void
 
798
PlayableModel::appendArtists( const QList< Tomahawk::artist_ptr >& artists )
 
799
{
 
800
    insertArtists( artists, rowCount( QModelIndex() ) );
 
801
}
 
802
 
 
803
 
 
804
void
 
805
PlayableModel::appendAlbums( const QList< Tomahawk::album_ptr >& albums )
 
806
{
 
807
    insertAlbums( albums, rowCount( QModelIndex() ) );
 
808
}
 
809
 
 
810
 
 
811
void
 
812
PlayableModel::appendQueries( const QList< Tomahawk::query_ptr >& queries )
 
813
{
 
814
    insertQueries( queries, rowCount( QModelIndex() ) );
 
815
}
 
816
 
 
817
 
 
818
void
 
819
PlayableModel::insertArtist( const Tomahawk::artist_ptr& artist, int row )
 
820
{
 
821
    QList< artist_ptr > artists;
 
822
    artists << artist;
 
823
 
 
824
    insertArtists( artists, row );
 
825
}
 
826
 
 
827
 
 
828
void
 
829
PlayableModel::insertAlbum( const Tomahawk::album_ptr& album, int row )
 
830
{
 
831
    QList< album_ptr > albums;
 
832
    albums << album;
 
833
 
 
834
    insertAlbums( albums, row );
 
835
}
 
836
 
 
837
 
 
838
void
 
839
PlayableModel::insertQuery( const Tomahawk::query_ptr& query, int row )
 
840
{
 
841
    QList< query_ptr > queries;
 
842
    queries << query;
 
843
 
 
844
    insertQueries( queries, row );
 
845
}
 
846
 
 
847
 
 
848
void
 
849
PlayableModel::insertArtists( const QList< Tomahawk::artist_ptr >& artists, int row )
 
850
{
 
851
    insertInternal( artists, row );
 
852
}
 
853
 
 
854
 
 
855
void
 
856
PlayableModel::insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row )
 
857
{
 
858
    insertInternal( albums, row );
 
859
}
 
860
 
 
861
 
 
862
void
 
863
PlayableModel::insertQueries( const QList< Tomahawk::query_ptr >& queries, int row )
 
864
{
 
865
    insertInternal( queries, row );
 
866
}
 
867
 
 
868
 
 
869
void
 
870
PlayableModel::setTitle( const QString& title )
 
871
{
 
872
    m_title = title;
 
873
    emit changed();
 
874
}
 
875
 
 
876
 
 
877
void
 
878
PlayableModel::setDescription( const QString& description )
 
879
{
 
880
    m_description = description;
 
881
    emit changed();
 
882
}
 
883
 
 
884
 
 
885
void
 
886
PlayableModel::setIcon( const QPixmap& pixmap )
 
887
{
 
888
    m_icon = pixmap;
 
889
    emit changed();
 
890
}
 
891
 
 
892
 
 
893
void
 
894
PlayableModel::onQueryBecamePlayable( bool playable )
 
895
{
 
896
    Q_UNUSED( playable );
 
897
 
 
898
    Tomahawk::Query* q = qobject_cast< Query* >( sender() );
 
899
    if ( !q )
 
900
    {
 
901
        // Track has been removed from the playlist by now
 
902
        return;
 
903
    }
 
904
 
 
905
    Tomahawk::query_ptr query = q->weakRef().toStrongRef();
 
906
    PlayableItem* item = itemFromQuery( query );
 
907
 
 
908
    if ( item )
 
909
    {
 
910
        emit indexPlayable( item->index );
 
911
    }
 
912
}
 
913
 
 
914
 
 
915
void
 
916
PlayableModel::onQueryResolved( bool hasResults )
 
917
{
 
918
    Q_UNUSED( hasResults );
 
919
    
 
920
    Tomahawk::Query* q = qobject_cast< Query* >( sender() );
 
921
    if ( !q )
 
922
    {
 
923
        // Track has been removed from the playlist by now
 
924
        return;
 
925
    }
 
926
    
 
927
    Tomahawk::query_ptr query = q->weakRef().toStrongRef();
 
928
    PlayableItem* item = itemFromQuery( query );
 
929
    
 
930
    if ( item )
 
931
    {
 
932
        emit indexResolved( item->index );
 
933
    }
 
934
}
 
935
 
 
936
 
 
937
PlayableItem*
 
938
PlayableModel::itemFromQuery( const Tomahawk::query_ptr& query ) const
 
939
{
 
940
    if ( !query )
 
941
        return 0;
 
942
 
 
943
    for ( int i = 0; i < rowCount( QModelIndex() ); i++ )
 
944
    {
 
945
        QModelIndex idx = index( i, 0, QModelIndex() );
 
946
        PlayableItem* item = itemFromIndex( idx );
 
947
        if ( item && item->query() == query )
 
948
        {
 
949
            return item;
 
950
        }
 
951
    }
 
952
 
 
953
    tDebug() << "Could not find item for query:" << query->toString();
 
954
    return 0;
 
955
}
 
956
 
 
957
 
 
958
PlayableItem*
 
959
PlayableModel::itemFromResult( const Tomahawk::result_ptr& result ) const
 
960
{
 
961
    if ( !result )
 
962
        return 0;
 
963
 
 
964
    for ( int i = 0; i < rowCount( QModelIndex() ); i++ )
 
965
    {
 
966
        QModelIndex idx = index( i, 0, QModelIndex() );
 
967
        PlayableItem* item = itemFromIndex( idx );
 
968
        if ( item && item->result() == result )
 
969
        {
 
970
            return item;
 
971
        }
 
972
    }
 
973
 
 
974
    tDebug() << "Could not find item for result:" << result->toString();
 
975
    return 0;
 
976
}