diff --git a/src/audiocontrols.cpp b/src/audiocontrols.cpp index f536be7c6..20c7637c9 100644 --- a/src/audiocontrols.cpp +++ b/src/audiocontrols.cpp @@ -264,11 +264,11 @@ AudioControls::onAlbumCoverUpdated() void AudioControls::setAlbumCover() { - if ( !m_currentTrack->album()->cover().isNull() ) + if ( !m_currentTrack->album()->cover( ui->coverImage->size() ).isNull() ) { QPixmap cover; - cover.loadFromData( m_currentTrack->album()->cover() ); - ui->coverImage->setPixmap( cover.scaled( ui->coverImage->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ); + cover = m_currentTrack->album()->cover( ui->coverImage->size() ); + ui->coverImage->setPixmap( cover ); } else ui->coverImage->setPixmap( m_defaultCover ); diff --git a/src/libtomahawk/album.cpp b/src/libtomahawk/album.cpp index fd56e8409..846dc15a6 100644 --- a/src/libtomahawk/album.cpp +++ b/src/libtomahawk/album.cpp @@ -32,6 +32,7 @@ using namespace Tomahawk; Album::~Album() { + delete m_cover; } @@ -71,6 +72,7 @@ Album::Album( unsigned int id, const QString& name, const Tomahawk::artist_ptr& , m_id( id ) , m_name( name ) , m_artist( artist ) + , m_cover( 0 ) , m_infoLoaded( false ) { connect( Tomahawk::InfoSystem::InfoSystem::instance(), @@ -97,11 +99,14 @@ Album::artist() const } -QByteArray -Album::cover() const +#ifndef ENABLE_HEADLESS +QPixmap +Album::cover( const QSize& size, bool forceLoad ) const { if ( !m_infoLoaded ) { + if ( !forceLoad ) + return QPixmap(); m_uuid = uuid(); Tomahawk::InfoSystem::InfoStringHash trackInfo; @@ -117,8 +122,31 @@ Album::cover() const Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); } - return m_cover; + if ( !m_cover ) + m_cover = new QPixmap(); + + if ( m_cover->isNull() && !m_coverBuffer.isEmpty() ) + { + m_cover->loadFromData( m_coverBuffer ); + } + + if ( !m_cover->isNull() && !size.isEmpty() ) + { + if ( m_coverCache.contains( size.width() ) ) + { + return m_coverCache.value( size.width() ); + } + else + { + QPixmap scaledCover; + scaledCover = m_cover->scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); + m_coverCache.insert( size.width(), scaledCover ); + } + } + + return *m_cover; } +#endif void @@ -137,7 +165,7 @@ Album::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVaria const QByteArray ba = returnedData["imgbytes"].toByteArray(); if ( ba.length() ) { - m_cover = ba; + m_coverBuffer = ba; } } diff --git a/src/libtomahawk/album.h b/src/libtomahawk/album.h index b929e9b49..741c7d65a 100644 --- a/src/libtomahawk/album.h +++ b/src/libtomahawk/album.h @@ -19,8 +19,13 @@ #ifndef TOMAHAWKALBUM_H #define TOMAHAWKALBUM_H +#include "config.h" + #include #include +#ifndef ENABLE_HEADLESS + #include +#endif #include "typedefs.h" #include "playlistinterface.h" @@ -44,7 +49,9 @@ public: unsigned int id() const { return m_id; } QString name() const { return m_name; } artist_ptr artist() const; - QByteArray cover() const; +#ifndef ENABLE_HEADLESS + QPixmap cover( const QSize& size, bool forceLoad = true ) const; +#endif bool infoLoaded() const { return m_infoLoaded; } Tomahawk::playlistinterface_ptr playlistInterface(); @@ -64,10 +71,13 @@ private: unsigned int m_id; QString m_name; artist_ptr m_artist; - QByteArray m_cover; + QByteArray m_coverBuffer; + mutable QPixmap* m_cover; bool m_infoLoaded; mutable QString m_uuid; + mutable QHash< int, QPixmap > m_coverCache; + Tomahawk::playlistinterface_ptr m_playlistInterface; }; diff --git a/src/libtomahawk/artist.cpp b/src/libtomahawk/artist.cpp index 0c0ba332c..534e15825 100644 --- a/src/libtomahawk/artist.cpp +++ b/src/libtomahawk/artist.cpp @@ -31,6 +31,7 @@ using namespace Tomahawk; Artist::~Artist() { + delete m_cover; } @@ -69,6 +70,7 @@ Artist::Artist( unsigned int id, const QString& name ) : QObject() , m_id( id ) , m_name( name ) + , m_cover( 0 ) , m_infoLoaded( false ) { m_sortname = DatabaseImpl::sortname( name, true ); @@ -89,11 +91,14 @@ Artist::onTracksAdded( const QList& tracks ) } -QByteArray -Artist::cover() const +#ifndef ENABLE_HEADLESS +QPixmap +Artist::cover( const QSize& size, bool forceLoad ) const { if ( !m_infoLoaded ) { + if ( !forceLoad ) + return QPixmap(); m_uuid = uuid(); Tomahawk::InfoSystem::InfoStringHash trackInfo; @@ -108,8 +113,31 @@ Artist::cover() const Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); } - return m_cover; + if ( !m_cover ) + m_cover = new QPixmap(); + + if ( m_cover->isNull() && !m_coverBuffer.isEmpty() ) + { + m_cover->loadFromData( m_coverBuffer ); + } + + if ( !m_cover->isNull() && !size.isEmpty() ) + { + if ( m_coverCache.contains( size.width() ) ) + { + return m_coverCache.value( size.width() ); + } + else + { + QPixmap scaledCover; + scaledCover = m_cover->scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); + m_coverCache.insert( size.width(), scaledCover ); + } + } + + return *m_cover; } +#endif void @@ -128,7 +156,7 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari const QByteArray ba = returnedData["imgbytes"].toByteArray(); if ( ba.length() ) { - m_cover = ba; + m_coverBuffer = ba; } } diff --git a/src/libtomahawk/artist.h b/src/libtomahawk/artist.h index 3e1442023..05efe48eb 100644 --- a/src/libtomahawk/artist.h +++ b/src/libtomahawk/artist.h @@ -19,8 +19,13 @@ #ifndef TOMAHAWKARTIST_H #define TOMAHAWKARTIST_H +#include "config.h" + #include #include +#ifndef ENABLE_HEADLESS + #include +#endif #include "typedefs.h" #include "dllmacro.h" @@ -43,7 +48,9 @@ public: unsigned int id() const { return m_id; } QString name() const { return m_name; } QString sortname() const { return m_sortname; } - QByteArray cover() const; +#ifndef ENABLE_HEADLESS + QPixmap cover( const QSize& size, bool forceLoad = true ) const; +#endif bool infoLoaded() const { return m_infoLoaded; } Tomahawk::playlistinterface_ptr playlistInterface(); @@ -63,10 +70,13 @@ private: unsigned int m_id; QString m_name; QString m_sortname; - QByteArray m_cover; + QByteArray m_coverBuffer; + mutable QPixmap* m_cover; bool m_infoLoaded; mutable QString m_uuid; + mutable QHash< int, QPixmap > m_coverCache; + Tomahawk::playlistinterface_ptr m_playlistInterface; }; diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 226d99a3f..256b8603f 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -333,7 +333,7 @@ AudioEngine::sendNowPlayingNotification() else { connect( m_currentTrack->album().data(), SIGNAL( updated() ), SLOT( onNowPlayingInfoReady() ), Qt::UniqueConnection ); - m_currentTrack->album()->cover(); + m_currentTrack->album()->cover( QSize( 0, 0 ) ); } } @@ -358,7 +358,7 @@ AudioEngine::onNowPlayingInfoReady() if ( !m_currentTrack->album().isNull() ) { QImage cover; - cover.loadFromData( m_currentTrack->album()->cover() ); + cover = m_currentTrack->album()->cover( QSize( 0, 0 ) ).toImage(); playInfo["image"] = QVariant( cover ); } diff --git a/src/libtomahawk/playlist/albumitemdelegate.cpp b/src/libtomahawk/playlist/albumitemdelegate.cpp index e28208248..f6baeceba 100644 --- a/src/libtomahawk/playlist/albumitemdelegate.cpp +++ b/src/libtomahawk/playlist/albumitemdelegate.cpp @@ -89,21 +89,20 @@ AlbumItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, painter->drawLine( shadowRect.bottomLeft() + QPoint( 0, 4 ), shadowRect.bottomRight() + QPoint( 0, 4 ) ); } + QRect r = option.rect.adjusted( 6, 5, -6, -41 ); QPixmap cover; if ( !item->album().isNull() ) { - cover.loadFromData( item->album()->cover() ); + cover = item->album()->cover( r.size() ); } else if ( !item->artist().isNull() ) { - cover.loadFromData( item->artist()->cover() ); + cover = item->artist()->cover( r.size() ); } if ( cover.isNull() ) cover = m_defaultCover; - QRect r = option.rect.adjusted( 6, 5, -6, -41 ); - if ( option.state & QStyle::State_Selected ) { #if defined(Q_WS_MAC) || defined(Q_WS_WIN) @@ -123,17 +122,7 @@ AlbumItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, #endif } - QPixmap scover; - if ( m_cache.contains( cover.cacheKey() ) ) - { - scover = m_cache.value( cover.cacheKey() ); - } - else - { - scover = cover.scaled( r.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ); - m_cache.insert( cover.cacheKey(), scover ); - } - painter->drawPixmap( r, scover ); + painter->drawPixmap( r, cover ); painter->setPen( opt.palette.color( QPalette::Text ) ); QTextOption to; diff --git a/src/libtomahawk/playlist/albumitemdelegate.h b/src/libtomahawk/playlist/albumitemdelegate.h index 86b31bdf5..43de6e0e8 100644 --- a/src/libtomahawk/playlist/albumitemdelegate.h +++ b/src/libtomahawk/playlist/albumitemdelegate.h @@ -49,7 +49,6 @@ private: QAbstractItemView* m_view; AlbumProxyModel* m_model; - mutable QHash< qint64, QPixmap > m_cache; mutable QHash< QPersistentModelIndex, QRect > m_artistNameRects; QPersistentModelIndex m_hoveringOver; diff --git a/src/libtomahawk/playlist/artistview.cpp b/src/libtomahawk/playlist/artistview.cpp index 808b6c8c5..ff83b2eeb 100644 --- a/src/libtomahawk/playlist/artistview.cpp +++ b/src/libtomahawk/playlist/artistview.cpp @@ -80,6 +80,11 @@ ArtistView::ArtistView( QWidget* parent ) setFont( f ); #endif + m_timer.setInterval( SCROLL_TIMEOUT ); + connect( verticalScrollBar(), SIGNAL( rangeChanged( int, int ) ), SLOT( onViewChanged() ) ); + connect( verticalScrollBar(), SIGNAL( valueChanged( int ) ), SLOT( onViewChanged() ) ); + connect( &m_timer, SIGNAL( timeout() ), SLOT( onScrollTimeout() ) ); + connect( this, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) ); connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) ); connect( m_contextMenu, SIGNAL( triggered( int ) ), SLOT( onMenuTriggered( int ) ) ); @@ -129,6 +134,7 @@ ArtistView::setTreeModel( TreeModel* model ) connect( m_model, SIGNAL( itemCountChanged( unsigned int ) ), SLOT( onItemCountChanged( unsigned int ) ) ); connect( m_proxyModel, SIGNAL( filterChanged( QString ) ), SLOT( onFilterChanged( QString ) ) ); + connect( m_proxyModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), SLOT( onViewChanged() ) ); guid(); // this will set the guid on the header @@ -145,6 +151,43 @@ ArtistView::setTreeModel( TreeModel* model ) } +void +ArtistView::onViewChanged() +{ + if ( m_timer.isActive() ) + m_timer.stop(); + + m_timer.start(); +} + + +void +ArtistView::onScrollTimeout() +{ + if ( m_timer.isActive() ) + m_timer.stop(); + + QModelIndex left = indexAt( viewport()->rect().topLeft() ); + while ( left.isValid() && left.parent().isValid() ) + left = left.parent(); + + QModelIndex right = indexAt( viewport()->rect().bottomLeft() ); + while ( right.isValid() && right.parent().isValid() ) + right = right.parent(); + + int max = m_proxyModel->playlistInterface()->trackCount(); + if ( right.isValid() ) + max = right.row() + 1; + + if ( !max ) + return; + + for ( int i = left.row(); i < max; i++ ) + { + m_model->getCover( m_proxyModel->mapToSource( m_proxyModel->index( i, 0 ) ) ); + } +} + void ArtistView::currentChanged( const QModelIndex& current, const QModelIndex& previous ) { diff --git a/src/libtomahawk/playlist/artistview.h b/src/libtomahawk/playlist/artistview.h index 8167f9b73..061bca781 100644 --- a/src/libtomahawk/playlist/artistview.h +++ b/src/libtomahawk/playlist/artistview.h @@ -95,6 +95,8 @@ private slots: void onItemCountChanged( unsigned int items ); void onFilterChanged( const QString& filter ); void onFilteringStarted(); + void onViewChanged(); + void onScrollTimeout(); void onCustomContextMenu( const QPoint& pos ); void onMenuTriggered( int action ); @@ -113,6 +115,7 @@ private: Tomahawk::ContextMenu* m_contextMenu; bool m_showModes; + QTimer m_timer; mutable QString m_guid; }; diff --git a/src/libtomahawk/playlist/treeitemdelegate.cpp b/src/libtomahawk/playlist/treeitemdelegate.cpp index 90fbe4aa7..22fc81247 100644 --- a/src/libtomahawk/playlist/treeitemdelegate.cpp +++ b/src/libtomahawk/playlist/treeitemdelegate.cpp @@ -155,14 +155,13 @@ TreeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, QPixmap cover; if ( !item->album().isNull() ) { - cover.loadFromData( item->album()->cover() ); + cover = item->album()->cover( r.size(), false ); } else if ( !item->artist().isNull() ) { - cover.loadFromData( item->artist()->cover() ); + cover = item->artist()->cover( r.size(), false ); } - QPixmap scover; if ( cover.isNull() ) { if ( !item->artist().isNull() ) @@ -171,16 +170,7 @@ TreeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, cover = m_defaultAlbumCover; } - if ( m_cache.contains( cover.cacheKey() ) ) - { - scover = m_cache.value( cover.cacheKey() ); - } - else - { - scover = cover.scaled( r.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ); - m_cache.insert( cover.cacheKey(), scover ); - } - painter->drawPixmap( r, scover ); + painter->drawPixmap( r, cover ); QTextOption to; to.setAlignment( Qt::AlignVCenter ); diff --git a/src/libtomahawk/playlist/treeitemdelegate.h b/src/libtomahawk/playlist/treeitemdelegate.h index 07fff9423..da84fcec9 100644 --- a/src/libtomahawk/playlist/treeitemdelegate.h +++ b/src/libtomahawk/playlist/treeitemdelegate.h @@ -43,8 +43,6 @@ private: ArtistView* m_view; TreeProxyModel* m_model; - mutable QHash< qint64, QPixmap > m_cache; - QPixmap m_nowPlayingIcon; QPixmap m_defaultAlbumCover; QPixmap m_defaultArtistImage; diff --git a/src/libtomahawk/playlist/treemodel.cpp b/src/libtomahawk/playlist/treemodel.cpp index 24e3073e0..63f40b3b2 100644 --- a/src/libtomahawk/playlist/treemodel.cpp +++ b/src/libtomahawk/playlist/treemodel.cpp @@ -87,6 +87,18 @@ TreeModel::collection() const } +void +TreeModel::getCover( const QModelIndex& index ) +{ + TreeModelItem* item = itemFromIndex( index ); + + if ( !item->artist().isNull() && !item->artist()->infoLoaded() ) + item->artist()->cover( QSize( 0, 0 ) ); + else if ( !item->album().isNull() && !item->album()->infoLoaded() ) + item->album()->cover( QSize( 0, 0 ) ); +} + + void TreeModel::setCurrentItem( const QModelIndex& index ) { diff --git a/src/libtomahawk/playlist/treemodel.h b/src/libtomahawk/playlist/treemodel.h index 53578bc8b..fb645cf28 100644 --- a/src/libtomahawk/playlist/treemodel.h +++ b/src/libtomahawk/playlist/treemodel.h @@ -98,6 +98,8 @@ public: void addAlbums( const Tomahawk::artist_ptr& artist, const QModelIndex& parent, bool autoRefetch = false ); void addTracks( const Tomahawk::album_ptr& album, const QModelIndex& parent, bool autoRefetch = false ); + void getCover( const QModelIndex& index ); + ColumnStyle columnStyle() const { return m_columnStyle; } void setColumnStyle( ColumnStyle style ); diff --git a/src/libtomahawk/widgets/infowidgets/AlbumInfoWidget.cpp b/src/libtomahawk/widgets/infowidgets/AlbumInfoWidget.cpp index 62b048704..c91cb37ab 100644 --- a/src/libtomahawk/widgets/infowidgets/AlbumInfoWidget.cpp +++ b/src/libtomahawk/widgets/infowidgets/AlbumInfoWidget.cpp @@ -243,10 +243,10 @@ AlbumInfoWidget::loadAlbums( bool autoRefetch ) void AlbumInfoWidget::onAlbumCoverUpdated() { - if ( m_album->cover().isNull() ) + if ( m_album->cover( QSize( 0, 0 ) ).isNull() ) return; - m_pixmap.loadFromData( m_album->cover() ); + m_pixmap = m_album->cover( QSize( 0, 0 ) ); emit pixmapChanged( m_pixmap ); } diff --git a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp index 178713c04..96e4dfc8b 100644 --- a/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp +++ b/src/libtomahawk/widgets/infowidgets/ArtistInfoWidget.cpp @@ -289,10 +289,10 @@ ArtistInfoWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestD void ArtistInfoWidget::onArtistImageUpdated() { - if ( m_artist->cover().isNull() ) + if ( m_artist->cover( QSize( 0, 0 ) ).isNull() ) return; - m_pixmap.loadFromData( m_artist->cover() ); + m_pixmap = m_artist->cover( QSize( 0, 0 ) ); emit pixmapChanged( m_pixmap ); } diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index 058b7bed1..5855a2b37 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -543,10 +543,7 @@ TomahawkApp::spotifyApiCheckFinished() QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() ); Q_ASSERT( reply ); - if ( reply->error() ) - DropJob::setCanParseSpotifyPlaylists( false ); - else - DropJob::setCanParseSpotifyPlaylists( true ); + DropJob::setCanParseSpotifyPlaylists( !reply->error() ); #endif }