diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 507d43c44..3aeabfeb7 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -197,6 +197,7 @@ set( libSources widgets/HeaderLabel.cpp widgets/HeaderWidget.cpp widgets/combobox.cpp + widgets/ToggleButton.cpp widgets/SocialPlaylistWidget.cpp widgets/infowidgets/sourceinfowidget.cpp widgets/infowidgets/ArtistInfoWidget.cpp @@ -395,6 +396,7 @@ set( libHeaders widgets/HeaderLabel.h widgets/HeaderWidget.h widgets/combobox.h + widgets/ToggleButton.h widgets/SocialPlaylistWidget.h widgets/infowidgets/sourceinfowidget.h widgets/infowidgets/ArtistInfoWidget.h diff --git a/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp index d4b638a80..b187111af 100644 --- a/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/generic/lastfmplugin.cpp @@ -419,20 +419,20 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash criteria, case InfoChartCapabilities: { QList track_charts; - track_charts.append(Chart("chart.getTopTracks", "Top Tracks", "tracks")); - track_charts.append(Chart("chart.getLovedTracks", "Loved Tracks", "tracks")); - track_charts.append(Chart("chart.getHypedTracks", "Hyped Tracks", "tracks")); + track_charts.append( Chart( "chart.getTopTracks", "Top Tracks", "tracks" ) ); + track_charts.append( Chart( "chart.getLovedTracks", "Loved Tracks", "tracks" ) ); + track_charts.append( Chart( "chart.getHypedTracks", "Hyped Tracks", "tracks" ) ); QList artist_charts; - artist_charts.append(Chart("chart.getTopArtists", "Top Artists", "artists")); - artist_charts.append(Chart("chart.getHypedArtists", "Hyped Artists", "artists")); + artist_charts.append( Chart( "chart.getTopArtists", "Top Artists", "artists" ) ); + artist_charts.append( Chart( "chart.getHypedArtists", "Hyped Artists", "artists" ) ); QVariantMap charts; - charts.insert("Tracks", QVariant::fromValue >(track_charts)); - charts.insert("Artists", QVariant::fromValue >(artist_charts)); + charts.insert( "Tracks", QVariant::fromValue >( track_charts ) ); + charts.insert( "Artists", QVariant::fromValue >( artist_charts ) ); QVariantMap result; - result.insert("Last.fm", QVariant::fromValue(charts)); + result.insert( "Last.fm", QVariant::fromValue( charts ) ); emit info( requestId, @@ -533,6 +533,7 @@ LastFmPlugin::similarArtistsReturned() emit updateCache( criteria, 2419200000, requestData.type, returnedData ); } + void LastFmPlugin::chartReturned() { @@ -544,7 +545,8 @@ LastFmPlugin::chartReturned() const QRegExp artists_rx( "chart\\.\\S+artists\\S*", Qt::CaseInsensitive ); const QString url = reply->url().toString(); - if( url.contains( tracks_rx ) ) { + if ( url.contains( tracks_rx ) ) + { QList tracks = parseTrackList( reply ); QList top_tracks; foreach( const lastfm::Track &t, tracks ) { @@ -557,7 +559,9 @@ LastFmPlugin::chartReturned() returnedData["tracks"] = QVariant::fromValue( top_tracks ); returnedData["type"] = "tracks"; - } else if( url.contains( artists_rx ) ) { + } + else if ( url.contains( artists_rx ) ) + { QList list = lastfm::Artist::list( reply ); QStringList al; tDebug() << "LastFmPlugin:"<< "\tgot " << list.size() << " artists"; @@ -565,7 +569,9 @@ LastFmPlugin::chartReturned() al << a.toString(); returnedData["artists"] = al; returnedData["type"] = "artists"; - } else { + } + else + { tDebug() << "LastfmPlugin:: got non tracks and non artists"; } @@ -579,6 +585,7 @@ LastFmPlugin::chartReturned() // TODO update cache } + void LastFmPlugin::topTracksReturned() { diff --git a/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.cpp index d64f2f88c..fe0fedff7 100644 --- a/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.cpp @@ -31,7 +31,7 @@ MusicBrainzPlugin::MusicBrainzPlugin() : InfoPlugin() { qDebug() << Q_FUNC_INFO; - m_supportedGetTypes << Tomahawk::InfoSystem::InfoArtistReleases; + m_supportedGetTypes << Tomahawk::InfoSystem::InfoArtistReleases << Tomahawk::InfoSystem::InfoAlbumSongs; } @@ -44,7 +44,6 @@ MusicBrainzPlugin::~MusicBrainzPlugin() void MusicBrainzPlugin::namChangedSlot( QNetworkAccessManager *nam ) { - qDebug() << Q_FUNC_INFO; if ( !nam ) return; @@ -55,8 +54,6 @@ MusicBrainzPlugin::namChangedSlot( QNetworkAccessManager *nam ) void MusicBrainzPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) { - qDebug() << Q_FUNC_INFO; - if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() ) { emit info( requestId, requestData, QVariant() ); @@ -69,16 +66,39 @@ MusicBrainzPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestDat return; } - if ( requestData.type == InfoArtistReleases ) + switch ( requestData.type ) { - QString requestString( "http://musicbrainz.org/ws/2/artist" ); - QUrl url( requestString ); - url.addQueryItem( "query", hash["artist"] ); - QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) ); - reply->setProperty( "requestId", requestId ); - reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); + case InfoArtistReleases: + { + QString requestString( "http://musicbrainz.org/ws/2/artist" ); + QUrl url( requestString ); + url.addQueryItem( "query", hash["artist"] ); + QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) ); + reply->setProperty( "requestId", requestId ); + reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); - connect( reply, SIGNAL( finished() ), SLOT( artistSearchSlot() ) ); + connect( reply, SIGNAL( finished() ), SLOT( artistSearchSlot() ) ); + break; + } + + case InfoAlbumSongs: + { + QString requestString( "http://musicbrainz.org/ws/2/artist" ); + QUrl url( requestString ); + url.addQueryItem( "query", hash["artist"] ); + QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) ); + reply->setProperty( "requestId", requestId ); + reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); + + connect( reply, SIGNAL( finished() ), SLOT( albumSearchSlot() ) ); + break; + } + + default: + { + Q_ASSERT( false ); + break; + } } } @@ -86,7 +106,6 @@ MusicBrainzPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestDat bool MusicBrainzPlugin::isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) { - qDebug() << Q_FUNC_INFO; if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QVariantMap >() ) { emit info( requestId, requestData, QVariant() ); @@ -113,7 +132,6 @@ MusicBrainzPlugin::isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoR void MusicBrainzPlugin::artistSearchSlot() { - qDebug() << Q_FUNC_INFO; QNetworkReply* oldReply = qobject_cast( sender() ); if ( !oldReply ) return; //timeout will handle it @@ -131,17 +149,89 @@ MusicBrainzPlugin::artistSearchSlot() QString requestString( "http://musicbrainz.org/ws/2/release?status=official&type=album|ep" ); QUrl url( requestString ); url.addQueryItem( "artist", artist_id ); + QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) ); newReply->setProperty( "requestId", oldReply->property( "requestId" ) ); newReply->setProperty( "requestData", oldReply->property( "requestData" ) ); - connect( newReply, SIGNAL( finished() ), SLOT( albumSearchSlot() ) ); + connect( newReply, SIGNAL( finished() ), SLOT( albumFoundSlot() ) ); } void MusicBrainzPlugin::albumSearchSlot() { - qDebug() << Q_FUNC_INFO; + QNetworkReply* oldReply = qobject_cast( sender() ); + if ( !oldReply ) + return; //timeout will handle it + + QDomDocument doc; + doc.setContent( oldReply->readAll() ); + QDomNodeList domNodeList = doc.elementsByTagName( "artist" ); + if ( domNodeList.isEmpty() ) + { + emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); + return; + } + + QString artist_id = domNodeList.at( 0 ).toElement().attribute( "id" ); + QString requestString( "http://musicbrainz.org/ws/2/release?status=official&type=album|ep" ); + QUrl url( requestString ); + url.addQueryItem( "artist", artist_id ); + + QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) ); + newReply->setProperty( "requestId", oldReply->property( "requestId" ) ); + newReply->setProperty( "requestData", oldReply->property( "requestData" ) ); + connect( newReply, SIGNAL( finished() ), SLOT( tracksSearchSlot() ) ); +} + + +void +MusicBrainzPlugin::tracksSearchSlot() +{ + QNetworkReply* oldReply = qobject_cast( sender() ); + if ( !oldReply ) + return; //timeout will handle it + + QDomDocument doc; + doc.setContent( oldReply->readAll() ); + QDomNodeList domNodeList = doc.elementsByTagName( "release" ); + if ( domNodeList.isEmpty() ) + { + emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); + return; + } + + Tomahawk::InfoSystem::InfoRequestData requestData = oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); + InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >(); + + QDomElement element; + for ( int i = 0; i < domNodeList.count(); i++ ) + { + QDomNodeList albumNodeList = domNodeList.at( i ).toElement().elementsByTagName( "title" ); + if ( albumNodeList.at( 0 ).toElement().text() == hash["album"] ) + element = domNodeList.at( i ).toElement(); + } + + if ( element.isNull() ) + { + emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); + return; + } + + QString release_id = element.attribute( "id" ); + QString requestString = QString( "http://musicbrainz.org/ws/2/release/%1?inc=recordings" ).arg( release_id ); + QUrl url( requestString ); + + QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) ); + newReply->setProperty( "requestId", oldReply->property( "requestId" ) ); + newReply->setProperty( "requestData", oldReply->property( "requestData" ) ); + connect( newReply, SIGNAL( finished() ), SLOT( tracksFoundSlot() ) ); +} + + +void +MusicBrainzPlugin::albumFoundSlot() +{ QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() ); if ( !reply ) return; //timeout will handle it @@ -163,6 +253,55 @@ MusicBrainzPlugin::albumSearchSlot() albums << album; } - qDebug() << Q_FUNC_INFO << "Found albums:" << albums; - emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant( albums ) ); + Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); + QVariantMap returnedData; + returnedData["albums"] = albums; + emit info( reply->property( "requestId" ).toUInt(), requestData, returnedData ); + + Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>(); + Tomahawk::InfoSystem::InfoCriteriaHash criteria; + criteria["artist"] = origData["artist"]; + emit updateCache( criteria, 0, requestData.type, returnedData ); +} + + +void +MusicBrainzPlugin::tracksFoundSlot() +{ + QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() ); + if ( !reply ) + return; //timeout will handle it + + QDomDocument doc; + doc.setContent( reply->readAll() ); + QDomNodeList domNodeList = doc.elementsByTagName( "recording" ); + if ( domNodeList.isEmpty() ) + { + emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); + return; + } + + QStringList tracks; + for ( int i = 0; i < domNodeList.count(); i++ ) + { + QDomNodeList trackNodeList = domNodeList.at( i ).toElement().elementsByTagName( "title" ); + + for ( int j = 0; j < trackNodeList.count(); j++ ) + { + QString track = trackNodeList.at( j ).toElement().text(); + if ( !tracks.contains( track ) ) + tracks << track; + } + } + + Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); + QVariantMap returnedData; + returnedData["tracks"] = tracks; + emit info( reply->property( "requestId" ).toUInt(), requestData, returnedData ); + + Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>(); + Tomahawk::InfoSystem::InfoCriteriaHash criteria; + criteria["artist"] = origData["artist"]; + criteria["album"] = origData["album"]; + emit updateCache( criteria, 0, requestData.type, returnedData ); } diff --git a/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.h b/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.h index c1ccb0733..9586fa1af 100644 --- a/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.h +++ b/src/libtomahawk/infosystem/infoplugins/generic/musicbrainzPlugin.h @@ -61,6 +61,10 @@ virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaH private slots: void artistSearchSlot(); void albumSearchSlot(); + void tracksSearchSlot(); + + void albumFoundSlot(); + void tracksFoundSlot(); private: bool isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ); diff --git a/src/libtomahawk/playlist/trackmodelitem.cpp b/src/libtomahawk/playlist/trackmodelitem.cpp index 36f1883c1..3f363fbc0 100644 --- a/src/libtomahawk/playlist/trackmodelitem.cpp +++ b/src/libtomahawk/playlist/trackmodelitem.cpp @@ -109,11 +109,7 @@ TrackModelItem::setupItem( const Tomahawk::query_ptr& query, TrackModelItem* par m_isPlaying = false; toberemoved = false; m_query = query; - if ( query->numResults() ) - { -// emit dataChanged(); - } - else + if ( !query->numResults() ) { connect( query.data(), SIGNAL( resultsAdded( QList ) ), SIGNAL( dataChanged() ) ); diff --git a/src/libtomahawk/playlist/treeitemdelegate.cpp b/src/libtomahawk/playlist/treeitemdelegate.cpp index 4d18f60d2..1328b15cd 100644 --- a/src/libtomahawk/playlist/treeitemdelegate.cpp +++ b/src/libtomahawk/playlist/treeitemdelegate.cpp @@ -69,9 +69,9 @@ TreeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, { text = item->album()->name(); } - else if ( !item->result().isNull() ) + else if ( !item->result().isNull() || !item->query().isNull() ) { - float opacity = item->result()->score(); + float opacity = item->result().isNull() ? 0.0 : item->result()->score(); opacity = qMax( (float)0.3, opacity ); QColor textColor = TomahawkUtils::alphaBlend( option.palette.color( QPalette::Foreground ), option.palette.color( QPalette::Background ), opacity ); diff --git a/src/libtomahawk/playlist/treemodel.cpp b/src/libtomahawk/playlist/treemodel.cpp index 8d5b634ab..9da5eda58 100644 --- a/src/libtomahawk/playlist/treemodel.cpp +++ b/src/libtomahawk/playlist/treemodel.cpp @@ -29,15 +29,15 @@ #include "utils/tomahawkutils.h" #include "utils/logger.h" -static QString s_tmInfoIdentifier = QString( "TREEMODEL" ); - using namespace Tomahawk; TreeModel::TreeModel( QObject* parent ) : QAbstractItemModel( parent ) , m_rootItem( new TreeModelItem( 0, this ) ) + , m_infoId( uuid() ) , m_columnStyle( AllColumns ) + , m_mode( Database ) { setIcon( QPixmap( RESPATH "images/music-icon.png" ) ); @@ -100,7 +100,7 @@ TreeModel::getCover( const QModelIndex& index ) trackInfo["pptr"] = QString::number( (qlonglong)item ); m_coverHash.insert( (qlonglong)item, index ); - requestData.caller = s_tmInfoIdentifier; + requestData.caller = m_infoId; requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ); requestData.customData = QVariantMap(); Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); @@ -261,7 +261,7 @@ TreeModel::data( const QModelIndex& index, int role ) const if ( role == Qt::SizeHintRole ) { - if ( !entry->result().isNull() ) + if ( !entry->result().isNull() || !entry->query().isNull() ) { return QSize( 128, 20 ); } @@ -288,7 +288,7 @@ TreeModel::data( const QModelIndex& index, int role ) const { return entry->album()->name(); } - else + else if ( !entry->result().isNull() ) { const result_ptr& result = entry->result(); switch( index.column() ) @@ -322,6 +322,10 @@ TreeModel::data( const QModelIndex& index, int role ) const return QVariant(); } } + else if ( !entry->query().isNull() && index.column() == Name ) + { + return entry->query()->track(); + } return QVariant(); } @@ -408,7 +412,7 @@ TreeModel::mimeData( const QModelIndexList &indexes ) const // lets try with album only fail = false; resultData.clear(); - foreach ( const QModelIndex& i, indexes) + foreach ( const QModelIndex& i, indexes ) { if ( i.column() > 0 || indexes.contains( i.parent() ) ) continue; @@ -436,11 +440,10 @@ TreeModel::mimeData( const QModelIndexList &indexes ) const return mimeData; } - // lets try with tracks only fail = false; resultData.clear(); - foreach ( const QModelIndex& i, indexes) + foreach ( const QModelIndex& i, indexes ) { if ( i.column() > 0 || indexes.contains( i.parent() ) ) continue; @@ -549,8 +552,6 @@ TreeModel::addAllCollections() void TreeModel::addArtists( const artist_ptr& artist ) { - qDebug() << Q_FUNC_INFO; - if ( artist.isNull() ) return; @@ -565,37 +566,70 @@ TreeModel::addArtists( const artist_ptr& artist ) void TreeModel::addAlbums( const artist_ptr& artist, const QModelIndex& parent ) { - qDebug() << Q_FUNC_INFO; - emit loadingStarted(); - DatabaseCommand_AllAlbums* cmd = new DatabaseCommand_AllAlbums( m_collection, artist ); - cmd->setData( parent.row() ); - connect( cmd, SIGNAL( albums( QList, QVariant ) ), - SLOT( onAlbumsAdded( QList, QVariant ) ) ); + if ( m_mode == Database ) + { + DatabaseCommand_AllAlbums* cmd = new DatabaseCommand_AllAlbums( m_collection, artist ); + cmd->setData( parent.row() ); - Database::instance()->enqueue( QSharedPointer( cmd ) ); + connect( cmd, SIGNAL( albums( QList, QVariant ) ), + SLOT( onAlbumsAdded( QList, QVariant ) ) ); + + Database::instance()->enqueue( QSharedPointer( cmd ) ); + } + else if ( m_mode == InfoSystem ) + { + Tomahawk::InfoSystem::InfoCriteriaHash artistInfo; + artistInfo["artist"] = artist->name(); + + Tomahawk::InfoSystem::InfoRequestData requestData; + requestData.caller = m_infoId; + requestData.customData["row"] = parent.row(); + requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( artistInfo ); + requestData.type = Tomahawk::InfoSystem::InfoArtistReleases; + Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); + } + else + Q_ASSERT( false ); } void TreeModel::addTracks( const album_ptr& album, const QModelIndex& parent ) { - qDebug() << Q_FUNC_INFO; - emit loadingStarted(); - DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_collection ); - cmd->setAlbum( album.data() ); QList< QVariant > rows; rows << parent.row(); rows << parent.parent().row(); - cmd->setData( QVariant( rows ) ); - connect( cmd, SIGNAL( tracks( QList, QVariant ) ), - SLOT( onTracksAdded( QList, QVariant ) ) ); + if ( m_mode == Database ) + { + DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_collection ); + cmd->setAlbum( album.data() ); + cmd->setData( QVariant( rows ) ); - Database::instance()->enqueue( QSharedPointer( cmd ) ); + connect( cmd, SIGNAL( tracks( QList, QVariant ) ), + SLOT( onTracksAdded( QList, QVariant ) ) ); + + Database::instance()->enqueue( QSharedPointer( cmd ) ); + } + else if ( m_mode == InfoSystem ) + { + Tomahawk::InfoSystem::InfoCriteriaHash artistInfo; + artistInfo["artist"] = album->artist()->name(); + artistInfo["album"] = album->name(); + + Tomahawk::InfoSystem::InfoRequestData requestData; + requestData.caller = m_infoId; + requestData.customData["rows"] = QVariant( rows ); + requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( artistInfo ); + requestData.type = Tomahawk::InfoSystem::InfoAlbumSongs; + Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); + } + else + Q_ASSERT( false ); } @@ -714,6 +748,7 @@ TreeModel::onTracksAdded( const QList& tracks, const QVaria return; QList< QVariant > rows = data.toList(); + tDebug() << "Adding to:" << rows; QModelIndex parent = index( rows.first().toUInt(), 0, index( rows.at( 1 ).toUInt(), 0, QModelIndex() ) ); TreeModelItem* parentItem = itemFromIndex( parent ); @@ -728,8 +763,11 @@ TreeModel::onTracksAdded( const QList& tracks, const QVaria TreeModelItem* item = 0; foreach( const query_ptr& query, tracks ) { - qDebug() << query->toString(); - item = new TreeModelItem( query->results().first(), parentItem ); + if ( query->numResults() ) + item = new TreeModelItem( query->results().first(), parentItem ); + else + item = new TreeModelItem( query, parentItem ); + item->index = createIndex( parentItem->children.count() - 1, 0, item ); connect( item, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) ); @@ -742,35 +780,84 @@ TreeModel::onTracksAdded( const QList& tracks, const QVaria void TreeModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) { - if ( requestData.caller != s_tmInfoIdentifier || - ( requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt && requestData.type != Tomahawk::InfoSystem::InfoArtistImages ) ) + if ( requestData.caller != m_infoId ) { return; } - if ( !output.canConvert< QVariantMap >() ) + switch ( requestData.type ) { - qDebug() << "Cannot convert fetched art from a QByteArray"; - return; - } + case Tomahawk::InfoSystem::InfoAlbumCoverArt: + case Tomahawk::InfoSystem::InfoArtistImages: + { + Tomahawk::InfoSystem::InfoCriteriaHash pptr = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >(); + QVariantMap returnedData = output.value< QVariantMap >(); + const QByteArray ba = returnedData["imgbytes"].toByteArray(); + if ( ba.length() ) + { + QPixmap pm; + pm.loadFromData( ba ); + bool ok; + qlonglong p = pptr["pptr"].toLongLong( &ok ); + TreeModelItem* ai = itemFromIndex( m_coverHash.take( p ) ); + if ( !ai ) + return; - Tomahawk::InfoSystem::InfoCriteriaHash pptr = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >(); - QVariantMap returnedData = output.value< QVariantMap >(); - const QByteArray ba = returnedData["imgbytes"].toByteArray(); - if ( ba.length() ) - { - QPixmap pm; - pm.loadFromData( ba ); - bool ok; - qlonglong p = pptr["pptr"].toLongLong( &ok ); - TreeModelItem* ai = itemFromIndex( m_coverHash.take( p ) ); - if ( !ai ) - return; + if ( !pm.isNull() ) + ai->cover = pm; - if ( !pm.isNull() ) - ai->cover = pm; + emit dataChanged( ai->index, ai->index.sibling( ai->index.row(), columnCount( QModelIndex() ) - 1 ) ); + } - emit dataChanged( ai->index, ai->index.sibling( ai->index.row(), columnCount( QModelIndex() ) - 1 ) ); + break; + } + + case Tomahawk::InfoSystem::InfoArtistReleases: + { + QVariantMap returnedData = output.value< QVariantMap >(); + QStringList albums = returnedData[ "albums" ].toStringList(); + QList al; + + InfoSystem::InfoCriteriaHash inputInfo; + inputInfo = requestData.input.value< InfoSystem::InfoCriteriaHash >(); + artist_ptr artist = Artist::get( inputInfo[ "artist" ], false ); + Q_ASSERT( !artist.isNull() ); + + foreach ( const QString& albumName, albums ) + { + int albumId = 0; + Tomahawk::album_ptr album = Tomahawk::Album::get( albumId, albumName, artist ); + al << album; + } + onAlbumsAdded( al, requestData.customData[ "row" ] ); + + break; + } + + case Tomahawk::InfoSystem::InfoAlbumSongs: + { + QVariantMap returnedData = output.value< QVariantMap >(); + QStringList tracks = returnedData[ "tracks" ].toStringList(); + QList ql; + + InfoSystem::InfoCriteriaHash inputInfo; + inputInfo = requestData.input.value< InfoSystem::InfoCriteriaHash >(); + + foreach ( const QString& trackName, tracks ) + { + query_ptr query = Query::get( inputInfo[ "artist" ], trackName, inputInfo[ "album" ], uuid() ); + ql << query; + } + onTracksAdded( ql, requestData.customData[ "rows" ] ); + + break; + } + + default: + { + Q_ASSERT( false ); + break; + } } } @@ -779,7 +866,6 @@ void TreeModel::infoSystemFinished( QString target ) { Q_UNUSED( target ); -// qDebug() << Q_FUNC_INFO; } @@ -836,10 +922,3 @@ TreeModel::indexFromArtist( const Tomahawk::artist_ptr& artist ) const return QModelIndex(); } - - -QModelIndex -TreeModel::indexFromAlbum( const Tomahawk::album_ptr& album ) const -{ - return QModelIndex(); -} diff --git a/src/libtomahawk/playlist/treemodel.h b/src/libtomahawk/playlist/treemodel.h index 6f04d1645..2828784d2 100644 --- a/src/libtomahawk/playlist/treemodel.h +++ b/src/libtomahawk/playlist/treemodel.h @@ -50,9 +50,12 @@ public: AlbumPosition }; - enum ColumnStyle // Default style is AllColumns + enum ColumnStyle { AllColumns = 0, TrackOnly }; + enum ModelMode + { Database = 0, InfoSystem }; + explicit TreeModel( QObject* parent = 0 ); virtual ~TreeModel(); @@ -65,15 +68,16 @@ public: 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 void clear(); + virtual ModelMode mode() const { return m_mode; } + virtual void setMode( ModelMode mode ) { m_mode = 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& indexes ); @@ -106,8 +110,6 @@ public: 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; - TreeModelItem* itemFromIndex( const QModelIndex& index ) const { if ( index.isValid() ) @@ -155,11 +157,13 @@ private slots: private: QPersistentModelIndex m_currentIndex; TreeModelItem* m_rootItem; + QString m_infoId; QString m_title; QString m_description; QPixmap m_icon; ColumnStyle m_columnStyle; + ModelMode m_mode; QList m_artistsFilter; diff --git a/src/libtomahawk/playlist/treemodelitem.cpp b/src/libtomahawk/playlist/treemodelitem.cpp index a9e07a1e3..8d3c14880 100644 --- a/src/libtomahawk/playlist/treemodelitem.cpp +++ b/src/libtomahawk/playlist/treemodelitem.cpp @@ -135,3 +135,108 @@ TreeModelItem::TreeModelItem( const Tomahawk::result_ptr& result, TreeModelItem* toberemoved = false; } + + +TreeModelItem::TreeModelItem( const Tomahawk::query_ptr& query, TreeModelItem* parent, int row ) + : QObject( parent ) + , m_query( query ) +{ + this->parent = parent; + fetchingMore = false; + m_isPlaying = false; + + if ( parent ) + { + if ( row < 0 ) + { + parent->children.append( this ); + row = parent->children.count() - 1; + } + else + { + parent->children.insert( row, this ); + } + + this->model = parent->model; + } + + toberemoved = false; + + connect( query.data(), SIGNAL( resultsAdded( QList ) ), + SLOT( onResultsChanged() ) ); + + connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ), + SLOT( onResultsChanged() ) ); + + connect( query.data(), SIGNAL( resultsChanged() ), + SLOT( onResultsChanged() ) ); +} + + +void +TreeModelItem::onResultsChanged() +{ + if ( m_query->numResults() ) + m_result = m_query->results().first(); + else + m_result = result_ptr(); + + emit dataChanged(); +} + + +QString +TreeModelItem::name() const +{ + if ( !m_artist.isNull() ) + { + return m_artist->name(); + } + else if ( !m_album.isNull() ) + { + return m_album->name(); + } + else if ( !m_result.isNull() ) + { + return m_result->track(); + } + else if ( !m_query.isNull() ) + { + return m_query->track(); + } + + Q_ASSERT( false ); + return QString(); +} + + +QString +TreeModelItem::artistName() const +{ + if ( !m_result.isNull() ) + { + return m_result->artist()->name(); + } + else if ( !m_query.isNull() ) + { + return m_query->artist(); + } + + return QString(); +} + + +QString +TreeModelItem::albumName() const +{ + if ( !m_result.isNull() && !m_result->album().isNull() ) + { + return m_result->album()->name(); + } + else if ( !m_query.isNull() ) + { + return m_query->album(); + } + + return QString(); +} diff --git a/src/libtomahawk/playlist/treemodelitem.h b/src/libtomahawk/playlist/treemodelitem.h index 01f3b226e..e3d650c08 100644 --- a/src/libtomahawk/playlist/treemodelitem.h +++ b/src/libtomahawk/playlist/treemodelitem.h @@ -39,16 +39,22 @@ public: explicit TreeModelItem( const Tomahawk::artist_ptr& artist, TreeModelItem* parent = 0, int row = -1 ); explicit TreeModelItem( const Tomahawk::album_ptr& album, TreeModelItem* parent = 0, int row = -1 ); explicit TreeModelItem( const Tomahawk::result_ptr& result, TreeModelItem* parent = 0, int row = -1 ); + explicit TreeModelItem( const Tomahawk::query_ptr& query, TreeModelItem* parent = 0, int row = -1 ); const Tomahawk::artist_ptr& artist() const { return m_artist; }; const Tomahawk::album_ptr& album() const { return m_album; }; const Tomahawk::result_ptr& result() const { return m_result; }; + const Tomahawk::query_ptr& query() const { return m_query; }; bool isPlaying() { return m_isPlaying; } void setIsPlaying( bool b ) { m_isPlaying = b; emit dataChanged(); } void setCover( const QPixmap& cover ) { this->cover = cover; emit dataChanged(); } + QString name() const; + QString artistName() const; + QString albumName() const; + TreeModelItem* parent; QList children; QHash hash; @@ -63,10 +69,14 @@ public: signals: void dataChanged(); +private slots: + void onResultsChanged(); + private: Tomahawk::artist_ptr m_artist; Tomahawk::album_ptr m_album; Tomahawk::result_ptr m_result; + Tomahawk::query_ptr m_query; bool m_isPlaying; }; diff --git a/src/libtomahawk/playlist/treeproxymodel.cpp b/src/libtomahawk/playlist/treeproxymodel.cpp index 9f73b3b74..0550a9b86 100644 --- a/src/libtomahawk/playlist/treeproxymodel.cpp +++ b/src/libtomahawk/playlist/treeproxymodel.cpp @@ -181,7 +181,7 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent TreeModelItem* pi = sourceModel()->itemFromIndex( sourceModel()->index( sourceRow, 0, sourceParent ) ); Q_ASSERT( pi ); - if ( !pi->result().isNull() ) + if ( m_model->mode() == TreeModel::Database && !pi->result().isNull() ) { QList< Tomahawk::result_ptr > rl = m_cache.values( sourceParent ); foreach ( const Tomahawk::result_ptr& result, rl ) @@ -201,7 +201,7 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent TreeModelItem* ti = sourceModel()->itemFromIndex( sourceModel()->index( i, 0, sourceParent ) ); - if ( ti->result()->track() == pi->result()->track() && + if ( ti->name() == pi->name() && ( ti->result()->albumpos() == pi->result()->albumpos() || ti->result()->albumpos() == 0 ) ) { if ( !pi->result()->isOnline() && ti->result()->isOnline() ) @@ -227,13 +227,9 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent QStringList sl = m_filter.split( " ", QString::SkipEmptyParts ); foreach( const QString& s, sl ) { - QString album; - if ( !pi->result()->album().isNull() ) - album = pi->result()->album()->name(); - - if ( !pi->result()->track().contains( s, Qt::CaseInsensitive ) && - !album.contains( s, Qt::CaseInsensitive ) && - !pi->result()->album()->artist()->name().contains( s, Qt::CaseInsensitive ) ) + if ( !pi->name().contains( s, Qt::CaseInsensitive ) && + !pi->albumName().contains( s, Qt::CaseInsensitive ) && + !pi->artistName().contains( s, Qt::CaseInsensitive ) ) { return false; } @@ -254,6 +250,11 @@ TreeProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) co if ( !p2 ) return false; + if ( !p1->result().isNull() && p2->result().isNull() ) + return true; + if ( p1->result().isNull() && !p2->result().isNull() ) + return false; + const QString& lefts = textForItem( p1 ); const QString& rights = textForItem( p2 ); @@ -370,6 +371,10 @@ TreeProxyModel::textForItem( TreeModelItem* item ) const { return DatabaseImpl::sortname( item->result()->track() ); } + else if ( !item->query().isNull() ) + { + return item->query()->track(); + } return QString(); } diff --git a/src/libtomahawk/widgets/HeaderWidget.cpp b/src/libtomahawk/widgets/HeaderWidget.cpp index 94dd03ca4..fb126db72 100644 --- a/src/libtomahawk/widgets/HeaderWidget.cpp +++ b/src/libtomahawk/widgets/HeaderWidget.cpp @@ -18,25 +18,29 @@ #include "HeaderWidget.h" - #include "utils/stylehelper.h" #include #include #include -HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) + +HeaderWidget::HeaderWidget( QWidget* parent ) + : QWidget( parent ) { } + HeaderWidget::~HeaderWidget() { } -void HeaderWidget::paintEvent(QPaintEvent *e) + +void +HeaderWidget::paintEvent( QPaintEvent* e ) { - QStylePainter p(this); + QStylePainter p( this ); QRect r = e->rect(); - StyleHelper::horizontalHeader(&p, r); + StyleHelper::horizontalHeader( &p, r ); } diff --git a/src/libtomahawk/widgets/HeaderWidget.h b/src/libtomahawk/widgets/HeaderWidget.h index be13a276c..1912d9185 100644 --- a/src/libtomahawk/widgets/HeaderWidget.h +++ b/src/libtomahawk/widgets/HeaderWidget.h @@ -25,7 +25,6 @@ #include "dllmacro.h" - /** * \class HeaderWidget * \brief A QWidget subclass with a background for use in headers. @@ -35,16 +34,10 @@ class DLLEXPORT HeaderWidget : public QWidget Q_OBJECT public: - HeaderWidget(QWidget *parent = 0); + HeaderWidget( QWidget* parent = 0 ); virtual ~HeaderWidget(); - virtual void paintEvent(QPaintEvent *); - - -private: - - + virtual void paintEvent( QPaintEvent* ); }; - #endif diff --git a/src/libtomahawk/widgets/combobox.cpp b/src/libtomahawk/widgets/combobox.cpp index 6a53b8fb5..e02016cf1 100644 --- a/src/libtomahawk/widgets/combobox.cpp +++ b/src/libtomahawk/widgets/combobox.cpp @@ -18,7 +18,6 @@ #include "combobox.h" - #include "utils/stylehelper.h" #include @@ -26,36 +25,41 @@ #include #include -ComboBox::ComboBox(QWidget *parent) : QComboBox(parent) + +ComboBox::ComboBox( QWidget* parent ) + : QComboBox( parent ) { } + ComboBox::~ComboBox() { } -void ComboBox::paintEvent(QPaintEvent *) + +void +ComboBox::paintEvent( QPaintEvent* ) { - QStylePainter p(this); - p.setPen(palette().color(QPalette::Text)); + QStylePainter p( this ); + p.setPen( palette().color( QPalette::Text ) ); QStyleOptionComboBox cb; - initStyleOption(&cb); + initStyleOption( &cb ); QRect r = cb.rect; + StyleHelper::horizontalHeader( &p, r ); - StyleHelper::horizontalHeader(&p, r); - - if( cb.state & QStyle::State_MouseOver ) { - QRect highlightRect(r); - QSize shrink(3,4); - QSize hS(highlightRect.size()); + if ( cb.state & QStyle::State_MouseOver ) + { + QRect highlightRect( r ); + QSize shrink( 3, 4 ); + QSize hS( highlightRect.size() ); hS -= shrink; - highlightRect.setSize(hS); - highlightRect.translate(0,2); + highlightRect.setSize( hS ); + highlightRect.translate( 0, 2 ); p.save(); - p.setRenderHint(QPainter::Antialiasing); + p.setRenderHint( QPainter::Antialiasing ); p.setBrush( StyleHelper::headerHighlightColor() ); - p.drawRoundedRect(highlightRect, 10.0, 10.0); + p.drawRoundedRect( highlightRect, 10.0, 10.0 ); p.restore(); } @@ -65,15 +69,13 @@ void ComboBox::paintEvent(QPaintEvent *) p.setBrush( StyleHelper::headerTextColor() ); p.drawText( r, cb.currentText, to ); - bool reverse = cb.direction == Qt::RightToLeft; int menuButtonWidth = 12; int left = !reverse ? r.right() - menuButtonWidth : r.left(); int right = !reverse ? r.right() : r.left() + menuButtonWidth; - QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), r.center().y() - 3, 9, 9); + QRect arrowRect( ( left + right ) / 2 + ( reverse ? 6 : -6 ), r.center().y() - 3, 9, 9 ); //FIXME: no consts please QStyleOption arrowOpt = cb; arrowOpt.rect = arrowRect; - StyleHelper::drawArrow(QStyle::PE_IndicatorArrowDown, &p, &arrowOpt); - + StyleHelper::drawArrow( QStyle::PE_IndicatorArrowDown, &p, &arrowOpt ); } diff --git a/src/libtomahawk/widgets/combobox.h b/src/libtomahawk/widgets/combobox.h index 2cf672a6d..18176bf87 100644 --- a/src/libtomahawk/widgets/combobox.h +++ b/src/libtomahawk/widgets/combobox.h @@ -33,16 +33,10 @@ class DLLEXPORT ComboBox : public QComboBox Q_OBJECT public: - ComboBox(QWidget *parent = 0); + ComboBox( QWidget* parent = 0 ); virtual ~ComboBox(); - virtual void paintEvent(QPaintEvent *); - - -private: - - + virtual void paintEvent( QPaintEvent* ); }; - #endif diff --git a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp index 1e0fb7890..6f03385e6 100644 --- a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp +++ b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp @@ -26,6 +26,7 @@ #include "database/databasecommand_alltracks.h" #include "database/databasecommand_allalbums.h" +#include "utils/stylehelper.h" #include "utils/tomahawkutils.h" #include "utils/logger.h" @@ -52,8 +53,11 @@ ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget* TomahawkUtils::unmarginLayout( layout() ); TomahawkUtils::unmarginLayout( ui->layoutWidget->layout() ); TomahawkUtils::unmarginLayout( ui->layoutWidget1->layout() ); + TomahawkUtils::unmarginLayout( ui->layoutWidget2->layout() ); + TomahawkUtils::unmarginLayout( ui->albumHeader->layout() ); m_albumsModel = new TreeModel( ui->albums ); + m_albumsModel->setMode( TreeModel::InfoSystem ); ui->albums->setTreeModel( m_albumsModel ); m_relatedModel = new TreeModel( ui->relatedArtists ); @@ -64,8 +68,14 @@ ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget* m_topHitsModel->setStyle( TrackModel::Short ); ui->topHits->setTrackModel( m_topHitsModel ); + ui->albumHeader->setContentsMargins( 0, 0, 4, 0 ); + ui->button->setFixedWidth( 200 ); + ui->button->setDown( true ); + m_pixmap = QPixmap( RESPATH "images/no-album-art-placeholder.png" ).scaledToWidth( 48, Qt::SmoothTransformation ); + connect( ui->button, SIGNAL( toggled( bool ) ), SLOT( onModeToggle( bool ) ) ); + connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); @@ -82,9 +92,19 @@ ArtistInfoWidget::~ArtistInfoWidget() } +void +ArtistInfoWidget::onModeToggle( bool officialReleases ) +{ + m_albumsModel->setMode( officialReleases ? TreeModel::InfoSystem : TreeModel::Database ); + m_albumsModel->clear(); + m_albumsModel->addAlbums( m_artist, QModelIndex() ); +} + + void ArtistInfoWidget::load( const artist_ptr& artist ) { + m_artist = artist; m_title = artist->name(); m_albumsModel->addAlbums( artist, QModelIndex() ); @@ -109,9 +129,6 @@ ArtistInfoWidget::load( const artist_ptr& artist ) requestData.type = Tomahawk::InfoSystem::InfoArtistSongs; Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); - - requestData.type = Tomahawk::InfoSystem::InfoArtistReleases; - Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); } diff --git a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h index b9e97259d..a5e49d2d4 100644 --- a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h +++ b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.h @@ -90,6 +90,8 @@ private slots: void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); void infoSystemFinished( QString target ); + void onModeToggle( bool officialReleases ); + private: Ui::ArtistInfoWidget *ui; diff --git a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.ui b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.ui index aa6b45159..bc6115712 100644 --- a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.ui +++ b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.ui @@ -66,13 +66,26 @@ - - + + - - - Albums - + + + + + + Albums + + + + + + + Official Releases Only + + + + @@ -95,6 +108,16 @@ QLabel
widgets/HeaderLabel.h
+ + HeaderWidget + QWidget +
widgets/HeaderWidget.h
+
+ + ToggleButton + QPushButton +
widgets/ToggleButton.h
+
ArtistView QTreeView