1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 11:20:22 +02:00

* PlayableModel is now capable of dealing with trees.

This commit is contained in:
Christian Muehlhaeuser
2012-05-31 21:22:18 +02:00
parent 623850a281
commit 751f029564
2 changed files with 273 additions and 57 deletions

View File

@@ -42,9 +42,16 @@ PlayableModel::PlayableModel( QObject* parent )
, m_rootItem( new PlayableItem( 0, this ) ) , m_rootItem( new PlayableItem( 0, this ) )
, m_readOnly( true ) , m_readOnly( true )
, m_style( Detailed ) , m_style( Detailed )
, m_loading( false )
{ {
connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection ); connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection );
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection ); connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection );
m_header << tr( "Artist" ) << tr( "Title" ) << tr( "Composer" ) << tr( "Album" ) << tr( "Track" ) << tr( "Duration" )
<< tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Score" ) << tr( "Name" );
m_headerStyle[ Detailed ] << Artist << Track << Composer << Album << AlbumPos << Duration << Bitrate << Age << Year << Filesize << Origin << Score;
m_headerStyle[ Collection ] << Name << Composer << Duration << Bitrate << Age << Year << Filesize << Origin;
} }
@@ -95,6 +102,10 @@ PlayableModel::columnCount( const QModelIndex& parent ) const
return 1; return 1;
break; break;
case Collection:
return 8;
break;
case Detailed: case Detailed:
default: default:
return 12; return 12;
@@ -103,6 +114,20 @@ PlayableModel::columnCount( const QModelIndex& parent ) const
} }
bool
PlayableModel::hasChildren( const QModelIndex& parent ) const
{
PlayableItem* parentItem = itemFromIndex( parent );
if ( !parentItem )
return false;
if ( parentItem == m_rootItem )
return true;
return ( !parentItem->artist().isNull() || !parentItem->album().isNull() );
}
QModelIndex QModelIndex
PlayableModel::parent( const QModelIndex& child ) const PlayableModel::parent( const QModelIndex& child ) const
{ {
@@ -124,42 +149,50 @@ PlayableModel::parent( const QModelIndex& child ) const
QVariant QVariant
PlayableModel::data( const QModelIndex& index, int role ) const PlayableModel::artistData( const artist_ptr& artist, int role ) const
{ {
PlayableItem* entry = itemFromIndex( index );
if ( !entry )
return QVariant();
if ( role == Qt::DecorationRole )
{
return QVariant();
}
if ( role == Qt::SizeHintRole ) if ( role == Qt::SizeHintRole )
{ return QSize( 0, 44 );
return QSize( 0, 18 );
}
if ( role == Qt::TextAlignmentRole )
{
return QVariant( columnAlignment( index.column() ) );
}
if ( role == StyleRole )
{
return m_style;
}
if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole ) if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
return QVariant(); return QVariant();
const query_ptr& query = entry->query()->displayQuery(); return artist->name();
switch( index.column() ) }
QVariant
PlayableModel::albumData( const album_ptr& album, int role ) const
{
if ( role == Qt::SizeHintRole )
return QSize( 0, 32 );
if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
return QVariant();
return album->name();
}
QVariant
PlayableModel::queryData( const query_ptr& query, int column, int role ) const
{
if ( role == Qt::SizeHintRole )
return QSize( 0, 18 );
if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
return QVariant();
if ( !m_headerStyle.contains( m_style ) )
return query->track();
switch( m_headerStyle[ m_style ].at( column ) )
{ {
case Artist: case Artist:
return query->artist(); return query->artist();
break; break;
case Name:
case Track: case Track:
return query->track(); return query->track();
break; break;
@@ -191,7 +224,7 @@ PlayableModel::data( const QModelIndex& index, int role ) const
} }
if ( query->numResults() ) if ( query->numResults() )
{ {
switch( index.column() ) switch( m_headerStyle[ m_style ].at( column ) )
{ {
case Bitrate: case Bitrate:
if ( query->results().first()->bitrate() > 0 ) if ( query->results().first()->bitrate() > 0 )
@@ -225,16 +258,58 @@ PlayableModel::data( const QModelIndex& index, int role ) const
} }
QVariant
PlayableModel::data( const QModelIndex& index, int role ) const
{
PlayableItem* entry = itemFromIndex( index );
if ( !entry )
return QVariant();
if ( role == Qt::DecorationRole )
{
return QVariant();
}
if ( role == Qt::TextAlignmentRole )
{
return QVariant( columnAlignment( index.column() ) );
}
if ( role == StyleRole )
{
return m_style;
}
if ( !entry->query().isNull() )
{
return queryData( entry->query()->displayQuery(), index.column(), role );
}
else if ( !entry->artist().isNull() )
{
return artistData( entry->artist(), role );
}
else if ( !entry->album().isNull() )
{
return albumData( entry->album(), role );
}
return QVariant();
}
QVariant QVariant
PlayableModel::headerData( int section, Qt::Orientation orientation, int role ) const PlayableModel::headerData( int section, Qt::Orientation orientation, int role ) const
{ {
Q_UNUSED( orientation ); Q_UNUSED( orientation );
QStringList headers;
headers << tr( "Artist" ) << tr( "Title" ) << tr( "Composer" ) << tr( "Album" ) << tr( "Track" ) << tr( "Duration" ) << tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Score" );
if ( role == Qt::DisplayRole && section >= 0 ) if ( role == Qt::DisplayRole && section >= 0 )
{ {
return headers.at( section ); if ( m_headerStyle.contains( m_style ) )
{
return m_header.at( m_headerStyle[ m_style ].at( section ) );
}
else
return tr( "Name" );
} }
if ( role == Qt::TextAlignmentRole ) if ( role == Qt::TextAlignmentRole )
@@ -315,7 +390,7 @@ QStringList
PlayableModel::mimeTypes() const PlayableModel::mimeTypes() const
{ {
QStringList types; QStringList types;
types << "application/tomahawk.query.list"; types << "application/tomahawk.mixed";
return types; return types;
} }
@@ -325,26 +400,134 @@ PlayableModel::mimeData( const QModelIndexList &indexes ) const
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
QByteArray queryData; QByteArray resultData;
QDataStream queryStream( &queryData, QIODevice::WriteOnly ); QDataStream resultStream( &resultData, QIODevice::WriteOnly );
foreach ( const QModelIndex& i, indexes ) // lets try with artist only
bool fail = false;
foreach ( const QModelIndex& i, indexes)
{ {
if ( i.column() > 0 ) if ( i.column() > 0 || indexes.contains( i.parent() ) )
continue; continue;
QModelIndex idx = index( i.row(), 0, i.parent() ); PlayableItem* item = itemFromIndex( i );
PlayableItem* item = itemFromIndex( idx ); if ( !item )
if ( item ) continue;
if ( !item->artist().isNull() )
{
const artist_ptr& artist = item->artist();
resultStream << artist->name();
}
else
{
fail = true;
break;
}
}
if ( !fail )
{
QMimeData* mimeData = new QMimeData();
mimeData->setData( "application/tomahawk.metadata.artist", resultData );
return mimeData;
}
// lets try with album only
fail = false;
resultData.clear();
foreach ( const QModelIndex& i, indexes )
{
if ( i.column() > 0 || indexes.contains( i.parent() ) )
continue;
PlayableItem* item = itemFromIndex( i );
if ( !item )
continue;
if ( !item->album().isNull() )
{
const album_ptr& album = item->album();
resultStream << album->artist()->name();
resultStream << album->name();
}
else
{
fail = true;
break;
}
}
if ( !fail )
{
QMimeData* mimeData = new QMimeData();
mimeData->setData( "application/tomahawk.metadata.album", resultData );
return mimeData;
}
// lets try with tracks only
fail = false;
resultData.clear();
foreach ( const QModelIndex& i, indexes )
{
if ( i.column() > 0 || indexes.contains( i.parent() ) )
continue;
PlayableItem* item = itemFromIndex( i );
if ( !item )
continue;
if ( !item->result().isNull() )
{
const result_ptr& result = item->result();
resultStream << qlonglong( &result );
}
else
{
fail = true;
break;
}
}
if ( !fail )
{
QMimeData* mimeData = new QMimeData();
mimeData->setData( "application/tomahawk.result.list", resultData );
return mimeData;
}
// Ok... we have to use mixed
resultData.clear();
foreach ( const QModelIndex& i, indexes )
{
if ( i.column() > 0 || indexes.contains( i.parent() ) )
continue;
PlayableItem* item = itemFromIndex( i );
if ( !item )
continue;
if ( !item->artist().isNull() )
{
const artist_ptr& artist = item->artist();
resultStream << QString( "application/tomahawk.metadata.artist" ) << artist->name();
}
else if ( !item->album().isNull() )
{
const album_ptr& album = item->album();
resultStream << QString( "application/tomahawk.metadata.album" ) << album->artist()->name() << album->name();
}
else if ( !item->result().isNull() )
{
const result_ptr& result = item->result();
resultStream << QString( "application/tomahawk.result.list" ) << qlonglong( &result );
}
else if ( !item->result().isNull() )
{ {
const query_ptr& query = item->query(); const query_ptr& query = item->query();
queryStream << qlonglong( &query ); resultStream << QString( "application/tomahawk.query.list" ) << qlonglong( &query );
} }
} }
QMimeData* mimeData = new QMimeData(); QMimeData* mimeData = new QMimeData();
mimeData->setData( "application/tomahawk.query.list", queryData ); mimeData->setData( "application/tomahawk.mixed", resultData );
return mimeData; return mimeData;
} }
@@ -354,7 +537,7 @@ PlayableModel::clear()
{ {
if ( rowCount( QModelIndex() ) ) if ( rowCount( QModelIndex() ) )
{ {
emit loadingFinished(); finishLoading();
emit beginResetModel(); emit beginResetModel();
delete m_rootItem; delete m_rootItem;
@@ -508,20 +691,6 @@ PlayableModel::remove( const QList<QPersistentModelIndex>& indexes )
} }
PlayableItem*
PlayableModel::itemFromIndex( const QModelIndex& index ) const
{
if ( index.isValid() )
{
return static_cast<PlayableItem*>( index.internalPointer() );
}
else
{
return m_rootItem;
}
}
void void
PlayableModel::onPlaybackStarted( const Tomahawk::result_ptr& result ) PlayableModel::onPlaybackStarted( const Tomahawk::result_ptr& result )
{ {
@@ -591,3 +760,33 @@ PlayableModel::onDataChanged()
if ( p && p->index.isValid() ) if ( p && p->index.isValid() )
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) ); emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) );
} }
void
PlayableModel::startLoading()
{
m_loading = true;
emit loadingStarted();
}
void
PlayableModel::finishLoading()
{
m_loading = false;
emit loadingFinished();
}
PlayableItem*
PlayableModel::itemFromIndex( const QModelIndex& index ) const
{
if ( index.isValid() )
{
return static_cast<PlayableItem*>( index.internalPointer() );
}
else
{
return m_rootItem;
}
}

View File

@@ -22,6 +22,7 @@
#define PLAYABLEMODEL_H #define PLAYABLEMODEL_H
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QPixmap>
#include "PlaylistInterface.h" #include "PlaylistInterface.h"
#include "Typedefs.h" #include "Typedefs.h"
@@ -38,7 +39,7 @@ Q_OBJECT
public: public:
enum PlayableItemStyle enum PlayableItemStyle
{ Detailed = 0, Short = 1, ShortWithAvatars = 2, Large = 3 }; { Detailed = 0, Short = 1, ShortWithAvatars = 2, Large = 3, Collection = 4 };
enum PlayableModelRole enum PlayableModelRole
{ StyleRole = Qt::UserRole + 1 }; { StyleRole = Qt::UserRole + 1 };
@@ -55,7 +56,8 @@ public:
Year = 8, Year = 8,
Filesize = 9, Filesize = 9,
Origin = 10, Origin = 10,
Score = 11 Score = 11,
Name = 12
}; };
explicit PlayableModel( QObject* parent = 0 ); explicit PlayableModel( QObject* parent = 0 );
@@ -69,19 +71,27 @@ public:
virtual bool isReadOnly() const { return m_readOnly; } virtual bool isReadOnly() const { return m_readOnly; }
virtual void setReadOnly( bool b ) { m_readOnly = b; } virtual void setReadOnly( bool b ) { m_readOnly = b; }
virtual bool isLoading() const { return m_loading; }
virtual QString title() const { return m_title; } virtual QString title() const { return m_title; }
virtual void setTitle( const QString& title ) { m_title = title; } virtual void setTitle( const QString& title ) { m_title = title; }
virtual QString description() const { return m_description; } virtual QString description() const { return m_description; }
virtual void setDescription( const QString& description ) { m_description = description; } virtual void setDescription( const QString& description ) { m_description = description; }
virtual QPixmap icon() const { return m_icon; }
virtual void setIcon( const QPixmap& pixmap ) { m_icon = pixmap; }
virtual int trackCount() const { return rowCount( QModelIndex() ); } virtual int trackCount() const { return rowCount( QModelIndex() ); }
virtual int rowCount( const QModelIndex& parent ) const; virtual int rowCount( const QModelIndex& parent ) const;
virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const; virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const;
virtual bool hasChildren( const QModelIndex& parent ) const;
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const; virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const; virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
virtual QVariant artistData( const Tomahawk::artist_ptr& artist, int role = Qt::DisplayRole ) const;
virtual QVariant albumData( const Tomahawk::album_ptr& album, int role = Qt::DisplayRole ) const;
virtual QVariant queryData( const Tomahawk::query_ptr&, int column, int role = Qt::DisplayRole ) const;
virtual QMimeData* mimeData( const QModelIndexList& indexes ) const; virtual QMimeData* mimeData( const QModelIndexList& indexes ) const;
virtual QStringList mimeTypes() const; virtual QStringList mimeTypes() const;
@@ -134,6 +144,8 @@ public slots:
protected: protected:
PlayableItem* rootItem() const { return m_rootItem; } PlayableItem* rootItem() const { return m_rootItem; }
void startLoading();
void finishLoading();
private slots: private slots:
void onDataChanged(); void onDataChanged();
@@ -152,8 +164,13 @@ private:
QString m_title; QString m_title;
QString m_description; QString m_description;
QPixmap m_icon;
QHash< PlayableItemStyle, QList<Columns> > m_headerStyle;
QStringList m_header;
PlayableItemStyle m_style; PlayableItemStyle m_style;
bool m_loading;
}; };
#endif // PLAYABLEMODEL_H #endif // PLAYABLEMODEL_H