1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-21 00:09:47 +01:00

* TreeModel inherits PlayableModel now. Will be renamed to CollectionModel soon.

This commit is contained in:
Christian Muehlhaeuser 2012-05-31 21:29:12 +02:00
parent bff7f01e22
commit ca3b01362c
2 changed files with 19 additions and 670 deletions

View File

@ -38,12 +38,10 @@ using namespace Tomahawk;
TreeModel::TreeModel( QObject* parent )
: QAbstractItemModel( parent )
, m_rootItem( new PlayableItem( 0, this ) )
, m_infoId( uuid() )
, m_columnStyle( AllColumns )
: PlayableModel( parent )
, m_mode( DatabaseMode )
{
setStyle( Collection );
setIcon( QPixmap( RESPATH "images/music-icon.png" ) );
connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection );
@ -58,24 +56,6 @@ TreeModel::TreeModel( QObject* parent )
TreeModel::~TreeModel()
{
tDebug() << Q_FUNC_INFO;
delete m_rootItem;
}
void
TreeModel::clear()
{
if ( rowCount( QModelIndex() ) )
{
emit loadingFinished();
emit beginResetModel();
delete m_rootItem;
m_rootItem = 0;
m_rootItem = new PlayableItem( 0, this );
emit endResetModel();
}
}
@ -107,45 +87,6 @@ TreeModel::getCover( const QModelIndex& index )
}
void
TreeModel::setCurrentItem( const QModelIndex& index )
{
qDebug() << Q_FUNC_INFO;
PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
if ( oldEntry )
{
oldEntry->setIsPlaying( false );
}
PlayableItem* entry = itemFromIndex( index );
if ( entry )
{
m_currentIndex = index;
entry->setIsPlaying( true );
}
else
{
m_currentIndex = QModelIndex();
}
}
QModelIndex
TreeModel::index( int row, int column, const QModelIndex& parent ) const
{
if ( !m_rootItem || row < 0 || column < 0 )
return QModelIndex();
PlayableItem* parentItem = itemFromIndex( parent );
PlayableItem* childItem = parentItem->children.value( row );
if ( !childItem )
return QModelIndex();
return createIndex( row, column, childItem );
}
bool
TreeModel::canFetchMore( const QModelIndex& parent ) const
{
@ -190,388 +131,11 @@ TreeModel::fetchMore( const QModelIndex& parent )
}
bool
TreeModel::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() );
}
int
TreeModel::rowCount( const QModelIndex& parent ) const
{
if ( parent.column() > 0 )
return 0;
PlayableItem* parentItem = itemFromIndex( parent );
if ( !parentItem )
return 0;
return parentItem->children.count();
}
int
TreeModel::columnCount( const QModelIndex& parent ) const
{
Q_UNUSED( parent );
if ( m_columnStyle == AllColumns )
return 8;
else if ( m_columnStyle == TrackOnly )
return 1;
// UH..
return 0;
}
QModelIndex
TreeModel::parent( const QModelIndex& child ) const
{
PlayableItem* entry = itemFromIndex( child );
if ( !entry )
return QModelIndex();
PlayableItem* parentEntry = entry->parent();
if ( !parentEntry )
return QModelIndex();
PlayableItem* grandparentEntry = parentEntry->parent();
if ( !grandparentEntry )
return QModelIndex();
int row = grandparentEntry->children.indexOf( parentEntry );
return createIndex( row, 0, parentEntry );
}
QVariant
TreeModel::data( const QModelIndex& index, int role ) const
{
PlayableItem* entry = itemFromIndex( index );
if ( !entry )
return QVariant();
if ( role == Qt::SizeHintRole )
{
if ( !entry->result().isNull() || !entry->query().isNull() )
{
return QSize( 128, 20 );
}
else if ( !entry->album().isNull() )
{
return QSize( 128, 32 );
}
else if ( !entry->artist().isNull() )
{
return QSize( 128, 44 );
}
return QSize( 128, 0 );
}
if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
return QVariant();
if ( !entry->artist().isNull() && index.column() == Name )
{
return entry->artist()->name();
}
else if ( !entry->album().isNull() && index.column() == Name )
{
return entry->album()->name();
}
else if ( !entry->result().isNull() )
{
const result_ptr& result = entry->result();
unsigned int discnumber = 0;
if ( !entry->query().isNull() )
discnumber = entry->query()->discnumber();
if ( discnumber == 0 )
discnumber = result->discnumber();
unsigned int albumpos = 0;
if ( !entry->query().isNull() )
albumpos = entry->query()->albumpos();
if ( albumpos == 0 )
albumpos = result->albumpos();
switch( index.column() )
{
case Name:
return QString( "%1%2%3" ).arg( discnumber > 0 ? QString( "%1." ).arg( discnumber ) : QString() )
.arg( albumpos > 0 ? QString( "%1. ").arg( albumpos ) : QString() )
.arg( result->track() );
case Duration:
return TomahawkUtils::timeToString( result->duration() );
case Bitrate:
if ( result->bitrate() > 0 )
return result->bitrate();
break;
case Age:
return TomahawkUtils::ageToString( QDateTime::fromTime_t( result->modificationTime() ) );
case Year:
if ( result->year() != 0 )
return result->year();
break;
case Filesize:
return TomahawkUtils::filesizeToString( result->size() );
case Origin:
return result->friendlySource();
case AlbumPosition:
return result->albumpos();
case Composer:
if ( !result->composer().isNull() )
return result->composer()->name();
break;
default:
return QVariant();
}
}
else if ( !entry->query().isNull() )
{
const query_ptr& query = entry->query();
switch( index.column() )
{
case Name:
return QString( "%1%2%3" ).arg( query->discnumber() > 0 ? QString( "%1." ).arg( query->discnumber() ) : QString() )
.arg( query->albumpos() > 0 ? QString( "%1. ").arg( query->albumpos() ) : QString() )
.arg( query->track() );
case AlbumPosition:
return entry->query()->albumpos();
default:
return QVariant();
}
}
return QVariant();
}
QVariant
TreeModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
QStringList headers;
headers << tr( "Name" ) << tr( "Composer" ) << tr( "Duration" ) << tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" );
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 )
{
return headers.at( section );
}
return QVariant();
}
Qt::ItemFlags
TreeModel::flags( const QModelIndex& index ) const
{
Qt::ItemFlags defaultFlags = QAbstractItemModel::flags( index );
if ( index.isValid() && index.column() == 0 )
{
PlayableItem* item = itemFromIndex( index );
if ( item && !item->result().isNull() )
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
if ( item && ( !item->album().isNull() || !item->artist().isNull() ) )
return Qt::ItemIsDragEnabled | defaultFlags;
}
return defaultFlags;
}
QStringList
TreeModel::mimeTypes() const
{
QStringList types;
types << "application/tomahawk.mixed";
return types;
}
QMimeData*
TreeModel::mimeData( const QModelIndexList &indexes ) const
{
qDebug() << Q_FUNC_INFO;
QByteArray resultData;
QDataStream resultStream( &resultData, QIODevice::WriteOnly );
// lets try with artist only
bool fail = false;
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 << 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 );
}
}
QMimeData* mimeData = new QMimeData();
mimeData->setData( "application/tomahawk.mixed", resultData );
return mimeData;
}
void
TreeModel::removeIndex( const QModelIndex& index )
{
qDebug() << Q_FUNC_INFO;
if ( index.column() > 0 )
return;
PlayableItem* item = itemFromIndex( index );
if ( item )
{
emit beginRemoveRows( index.parent(), index.row(), index.row() );
delete item;
emit endRemoveRows();
}
}
void
TreeModel::removeIndexes( const QList<QModelIndex>& indexes )
{
foreach( const QModelIndex& idx, indexes )
{
removeIndex( idx );
}
}
void
TreeModel::addAllCollections()
{
emit loadingStarted();
startLoading();
DatabaseCommand_AllArtists* cmd = new DatabaseCommand_AllArtists();
connect( cmd, SIGNAL( artists( QList<Tomahawk::artist_ptr> ) ),
@ -587,7 +151,7 @@ TreeModel::addAllCollections()
connect( source->collection().data(), SIGNAL( changed() ), SLOT( onCollectionChanged() ), Qt::UniqueConnection );
}
m_title = tr( "All Artists" );
setTitle( tr( "All Artists" ) );
}
@ -597,7 +161,7 @@ TreeModel::addArtists( const artist_ptr& artist )
if ( artist.isNull() )
return;
emit loadingStarted();
startLoading();
QList<Tomahawk::artist_ptr> artists;
artists << artist;
@ -608,7 +172,7 @@ TreeModel::addArtists( const artist_ptr& artist )
void
TreeModel::fetchAlbums( const artist_ptr& artist )
{
emit loadingStarted();
startLoading();
connect( artist.data(), SIGNAL( albumsAdded( QList<Tomahawk::album_ptr>, Tomahawk::ModelMode ) ),
SLOT( onAlbumsFound( QList<Tomahawk::album_ptr>, Tomahawk::ModelMode ) ), Qt::UniqueConnection );
@ -624,7 +188,7 @@ TreeModel::onAlbumsFound( const QList<Tomahawk::album_ptr>& albums, ModelMode mo
if ( m_mode != mode )
return;
Artist* artist = qobject_cast< Artist* >( sender() );
Tomahawk::Artist* artist = qobject_cast< Tomahawk::Artist* >( sender() );
if ( !artist )
return;
@ -640,7 +204,7 @@ TreeModel::onAlbumsFound( const QList<Tomahawk::album_ptr>& albums, ModelMode mo
void
TreeModel::addAlbums( const QModelIndex& parent, const QList<Tomahawk::album_ptr>& albums )
{
emit loadingFinished();
finishLoading();
if ( !albums.count() )
return;
@ -672,7 +236,7 @@ TreeModel::addTracks( const album_ptr& album, const QModelIndex& parent, bool au
{
Q_UNUSED( autoRefetch );
emit loadingStarted();
startLoading();
connect( album.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
SLOT( onTracksFound( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
@ -755,12 +319,7 @@ TreeModel::onCollectionChanged()
void
TreeModel::onArtistsAdded( const QList<Tomahawk::artist_ptr>& artists )
{
emit loadingFinished();
if ( !artists.count() )
{
emit itemCountChanged( rowCount( QModelIndex() ) );
return;
}
finishLoading();
int c = rowCount( QModelIndex() );
QPair< int, int > crows;
@ -772,20 +331,19 @@ TreeModel::onArtistsAdded( const QList<Tomahawk::artist_ptr>& artists )
PlayableItem* artistitem;
foreach( const artist_ptr& artist, artists )
{
artistitem = new PlayableItem( artist, m_rootItem );
artistitem->index = createIndex( m_rootItem->children.count() - 1, 0, artistitem );
artistitem = new PlayableItem( artist, rootItem() );
artistitem->index = createIndex( rootItem()->children.count() - 1, 0, artistitem );
connect( artistitem, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) );
}
emit endInsertRows();
emit itemCountChanged( rowCount( QModelIndex() ) );
}
void
TreeModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const QModelIndex& parent )
{
emit loadingFinished();
finishLoading();
if ( !tracks.count() )
return;
@ -817,135 +375,17 @@ TreeModel::onTracksFound( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::Mo
if ( mode != m_mode || collection != m_collection )
return;
Album* album = qobject_cast<Album*>( sender() );
Tomahawk::Album* album = qobject_cast<Tomahawk::Album*>( sender() );
QModelIndex idx = indexFromAlbum( album->weakRef().toStrongRef() );
onTracksAdded( tracks, idx );
}
void
TreeModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
if ( requestData.caller != m_infoId )
{
return;
}
switch ( requestData.type )
{
case Tomahawk::InfoSystem::InfoAlbumSongs:
{
m_receivedInfoData.append( requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >() );
QVariantMap returnedData = output.value< QVariantMap >();
if ( !returnedData.isEmpty() )
{
emit loadingFinished();
QList< QVariant > rows = requestData.customData[ "rows" ].toList();
QModelIndex idx = index( rows.first().toUInt(), 0, index( rows.at( 1 ).toUInt(), 0, QModelIndex() ) );
if ( rowCount( idx ) )
return;
Tomahawk::InfoSystem::InfoStringHash inputInfo;
inputInfo = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
QStringList tracks = returnedData[ "tracks" ].toStringList();
QList<query_ptr> ql;
//TODO: Figure out how to do this with a multi-disk album without breaking the
// current behaviour. I just know too little about InfoSystem to deal with
// it right now, I've only taken the liberty of adding Query::setDiscNumber
// which should make this easier. --Teo 11/2011
unsigned int trackNo = 1;
foreach ( const QString& trackName, tracks )
{
query_ptr query = Query::get( inputInfo[ "artist" ], trackName, inputInfo[ "album" ] );
query->setAlbumPos( trackNo++ );
ql << query;
}
Pipeline::instance()->resolve( ql );
onTracksAdded( ql, idx );
}
else if ( m_receivedInfoData.count() == 2 /* FIXME */ )
{
// If the second load got no data, but the first load did, don't do anything
QList< QVariant > rows = requestData.customData[ "rows" ].toList();
QModelIndex idx = index( rows.first().toUInt(), 0, index( rows.at( 1 ).toUInt(), 0, QModelIndex() ) );
if ( rowCount( idx ) )
return;
if ( requestData.customData[ "refetch" ].toBool() )
{
setMode( DatabaseMode );
Tomahawk::InfoSystem::InfoStringHash inputInfo;
inputInfo = requestData.input.value< InfoSystem::InfoStringHash >();
artist_ptr artist = Artist::get( inputInfo[ "artist" ], false );
album_ptr album = Album::get( artist, inputInfo[ "album" ], false );
addTracks( album, QModelIndex() );
}
else
emit loadingFinished();
}
break;
}
default:
{
Q_ASSERT( false );
break;
}
}
}
void
TreeModel::onPlaybackStarted( const Tomahawk::result_ptr& result )
{
PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
if ( oldEntry && ( oldEntry->result().isNull() || oldEntry->result().data() != result.data() ) )
{
oldEntry->setIsPlaying( false );
}
}
void
TreeModel::onPlaybackStopped()
{
PlayableItem* oldEntry = itemFromIndex( m_currentIndex );
if ( oldEntry )
{
oldEntry->setIsPlaying( false );
}
}
void
TreeModel::onDataChanged()
{
PlayableItem* p = (PlayableItem*)sender();
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount( QModelIndex() ) - 1 ) );
}
void
TreeModel::setColumnStyle( TreeModel::ColumnStyle style )
{
m_columnStyle = style;
}
QModelIndex
TreeModel::indexFromArtist( const Tomahawk::artist_ptr& artist ) const
{
for ( int i = 0; i < rowCount(); i++ )
for ( int i = 0; i < rowCount( QModelIndex() ); i++ )
{
QModelIndex idx = index( i, 0, QModelIndex() );
PlayableItem* item = itemFromIndex( idx );

View File

@ -27,11 +27,10 @@
#include "Album.h"
#include "Query.h"
#include "Result.h"
#include "PlayableModel.h"
#include "PlaylistInterface.h"
#include "database/DatabaseCommand_AllArtists.h"
#include "infosystem/InfoSystem.h"
#include "DllMacro.h"
#include "Typedefs.h"
@ -39,57 +38,17 @@ class QMetaData;
class PlayableItem;
class DLLEXPORT TreeModel : public QAbstractItemModel
class DLLEXPORT TreeModel : public PlayableModel
{
Q_OBJECT
public:
enum Columns {
Name = 0,
Composer,
Duration,
Bitrate,
Age,
Year,
Filesize,
Origin,
AlbumPosition
};
enum ColumnStyle
{ AllColumns = 0, TrackOnly };
explicit TreeModel( QObject* parent = 0 );
virtual ~TreeModel();
virtual QModelIndex index( int row, int column, const QModelIndex& parent ) const;
virtual QModelIndex parent( const QModelIndex& child ) const;
virtual bool isReadOnly() const { return true; }
virtual int trackCount() const { return rowCount( QModelIndex() ); }
virtual int albumCount() const { return rowCount( QModelIndex() ); }
virtual bool hasChildren( const QModelIndex& parent = QModelIndex() ) const;
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;
virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const;
virtual Tomahawk::ModelMode mode() const { return m_mode; }
virtual void setMode( Tomahawk::ModelMode mode );
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
virtual void clear();
virtual void removeIndex( const QModelIndex& index );
virtual void removeIndexes( const QList<QModelIndex>& indexes );
virtual QMimeData* mimeData( const QModelIndexList& indexes ) const;
virtual QStringList mimeTypes() const;
virtual Qt::ItemFlags flags( const QModelIndex& index ) const;
virtual QPersistentModelIndex currentItem() { return m_currentIndex; }
Tomahawk::collection_ptr collection() const;
void addAllCollections();
@ -102,47 +61,14 @@ public:
void getCover( const QModelIndex& index );
ColumnStyle columnStyle() const { return m_columnStyle; }
void setColumnStyle( ColumnStyle style );
virtual QString title() const { return m_title; }
virtual QString description() const { return m_description; }
virtual QPixmap icon() const { return m_icon; }
virtual void setTitle( const QString& title ) { m_title = title; }
virtual void setDescription( const QString& description ) { m_description = description; }
virtual void setIcon( const QPixmap& pixmap ) { m_icon = pixmap; }
QModelIndex indexFromArtist( const Tomahawk::artist_ptr& artist ) const;
QModelIndex indexFromAlbum( const Tomahawk::album_ptr& album ) const;
PlayableItem* itemFromIndex( const QModelIndex& index ) const
{
if ( index.isValid() )
{
return static_cast<PlayableItem*>( index.internalPointer() );
}
else
{
return m_rootItem;
}
}
public slots:
virtual void setCurrentItem( const QModelIndex& index );
virtual void setRepeatMode( Tomahawk::PlaylistModes::RepeatMode /*mode*/ ) {}
virtual void setShuffled( bool /*shuffled*/ ) {}
void addAlbums( const QModelIndex& parent, const QList<Tomahawk::album_ptr>& albums );
signals:
void repeatModeChanged( Tomahawk::PlaylistModes::RepeatMode mode );
void shuffleModeChanged( bool enabled );
void modeChanged( Tomahawk::ModelMode mode );
void itemCountChanged( unsigned int items );
void loadingStarted();
void loadingFinished();
protected:
bool canFetchMore( const QModelIndex& parent ) const;
@ -154,31 +80,14 @@ private slots:
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const QModelIndex& index );
void onTracksFound( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::ModelMode mode, Tomahawk::collection_ptr collection );
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void onPlaybackStarted( const Tomahawk::result_ptr& result );
void onPlaybackStopped();
void onDataChanged();
void onSourceAdded( const Tomahawk::source_ptr& source );
void onCollectionChanged();
private:
QPersistentModelIndex m_currentIndex;
PlayableItem* m_rootItem;
QString m_infoId;
QString m_title;
QString m_description;
QPixmap m_icon;
ColumnStyle m_columnStyle;
Tomahawk::ModelMode m_mode;
Tomahawk::collection_ptr m_collection;
QList<Tomahawk::artist_ptr> m_artistsFilter;
Tomahawk::collection_ptr m_collection;
QList<Tomahawk::InfoSystem::InfoStringHash> m_receivedInfoData;
};
#endif // ALBUMMODEL_H