1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-06 06:07:37 +02:00

Add spotify support to jobsview

This commit is contained in:
Leo Franchi
2011-09-17 12:23:31 -04:00
parent d40ed14d80
commit b6c1d06165
16 changed files with 158 additions and 61 deletions

View File

@@ -63,10 +63,6 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
sourcetree/items/genericpageitems.cpp sourcetree/items/genericpageitems.cpp
sourcetree/items/temporarypageitem.cpp sourcetree/items/temporarypageitem.cpp
jobview/JobStatusView.cpp
jobview/JobStatusModel.cpp
jobview/JobStatusDelegate.cpp
jobview/PipelineStatusItem.cpp
# breakpad/BreakPad.cpp # breakpad/BreakPad.cpp
transferview.cpp transferview.cpp
@@ -118,12 +114,6 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
sourcetree/items/genericpageitems.h sourcetree/items/genericpageitems.h
sourcetree/items/temporarypageitem.h sourcetree/items/temporarypageitem.h
jobview/JobStatusView.h
jobview/JobStatusModel.h
jobview/JobStatusDelegate.h
jobview/JobStatusItem.h
jobview/PipelineStatusItem.h
transferview.h transferview.h
tomahawktrayicon.h tomahawktrayicon.h
audiocontrols.h audiocontrols.h

View File

@@ -215,6 +215,11 @@ set( libSources
widgets/headerbreadcrumb.cpp widgets/headerbreadcrumb.cpp
widgets/siblingcrumbbutton.cpp widgets/siblingcrumbbutton.cpp
jobview/JobStatusView.cpp
jobview/JobStatusModel.cpp
jobview/JobStatusDelegate.cpp
jobview/PipelineStatusItem.cpp
thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp
thirdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp thirdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp
thirdparty/kdsingleapplicationguard/kdtoolsglobal.cpp thirdparty/kdsingleapplicationguard/kdtoolsglobal.cpp
@@ -421,6 +426,12 @@ set( libHeaders
widgets/headerbreadcrumb.h widgets/headerbreadcrumb.h
widgets/siblingcrumbbutton.h widgets/siblingcrumbbutton.h
jobview/JobStatusView.h
jobview/JobStatusModel.h
jobview/JobStatusDelegate.h
jobview/JobStatusItem.h
jobview/PipelineStatusItem.h
thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.h thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.h
thirdparty/Qocoa/qsearchfield.h thirdparty/Qocoa/qsearchfield.h
) )

View File

@@ -178,13 +178,7 @@ DropJob::parseMimeData( const QMimeData *data )
else if ( data->hasFormat( "text/plain" ) ) else if ( data->hasFormat( "text/plain" ) )
{ {
const QString plainData = QString::fromUtf8( data->data( "text/plain" ) ); const QString plainData = QString::fromUtf8( data->data( "text/plain" ) );
handleAllUrls( plainData );
if ( plainData.contains( "xspf" ) )
handleXspf( data->data( "text/plain" ).trimmed() );
else if ( plainData.contains( "spotify" ) && plainData.contains( "playlist" ) && s_canParseSpotifyPlaylists )
handleSpPlaylist( plainData );
else
handleTrackUrls ( plainData );
} }
m_resultList.append( results ); m_resultList.append( results );
@@ -415,6 +409,18 @@ DropJob::handleSpPlaylist( const QString& url )
m_queryCount++; m_queryCount++;
} }
void
DropJob::handleAllUrls( const QString& urls )
{
if ( urls.contains( "xspf" ) )
handleXspf( urls );
else if ( urls.contains( "spotify" ) && urls.contains( "playlist" ) && s_canParseSpotifyPlaylists )
handleSpPlaylist( urls );
else
handleTrackUrls ( urls );
}
void void
DropJob::handleTrackUrls( const QString& urls ) DropJob::handleTrackUrls( const QString& urls )
{ {
@@ -471,7 +477,7 @@ void
DropJob::expandedUrls( QStringList urls ) DropJob::expandedUrls( QStringList urls )
{ {
m_queryCount--; m_queryCount--;
handleTrackUrls( urls.join( "\n" ) ); handleAllUrls( urls.join( "\n" ) );
} }
void void

View File

@@ -105,7 +105,7 @@ private slots:
private: private:
/// handle parsing mime data /// handle parsing mime data
void handleAllUrls( const QString& urls );
void handleTrackUrls( const QString& urls ); void handleTrackUrls( const QString& urls );
QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d ); QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d );
QList< Tomahawk::query_ptr > tracksFromResultList( const QMimeData* d ); QList< Tomahawk::query_ptr > tracksFromResultList( const QMimeData* d );

View File

@@ -17,7 +17,9 @@
*/ */
#include "JobStatusModel.h" #include "JobStatusModel.h"
#include "JobStatusItem.h" #include "JobStatusItem.h"
#include "utils/logger.h"
JobStatusModel::JobStatusModel( QObject* parent ) JobStatusModel::JobStatusModel( QObject* parent )
: QAbstractListModel ( parent ) : QAbstractListModel ( parent )
@@ -34,11 +36,15 @@ JobStatusModel::~JobStatusModel()
void void
JobStatusModel::addJob( JobStatusItem* item ) JobStatusModel::addJob( JobStatusItem* item )
{ {
connect( item, SIGNAL( statusChanged() ), this, SLOT( itemUpdated() ) );
connect( item, SIGNAL( finished() ), this, SLOT( itemFinished() ) );
if ( item->collapseItem() ) if ( item->collapseItem() )
{ {
if ( m_collapseCount.contains( item->type() ) ) if ( m_collapseCount.contains( item->type() ) )
{ {
m_collapseCount[ item->type() ].append( item ); m_collapseCount[ item->type() ].append( item );
qDebug() << "Adding item:" << item << "TO COLLAPSE ONLY";
return; // we're done, no new rows return; // we're done, no new rows
} }
else else
@@ -47,9 +53,7 @@ JobStatusModel::addJob( JobStatusItem* item )
} }
} }
qDebug() << "Adding item:" << item;
connect( item, SIGNAL( statusChanged() ), this, SLOT( itemUpdated() ) );
connect( item, SIGNAL( finished() ), this, SLOT( itemFinished() ) );
beginInsertRows( QModelIndex(), 0, 0 ); beginInsertRows( QModelIndex(), 0, 0 );
m_items.prepend( item ); m_items.prepend( item );
@@ -108,15 +112,36 @@ JobStatusModel::itemFinished()
JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() ); JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() );
Q_ASSERT( item ); Q_ASSERT( item );
// tDebug() << "Got item finished:" << item->type() << item->mainText() << item;
// foreach( JobStatusItem* item, m_items )
// {
// qDebug() << "ITEM #:" << item;
// }
// foreach( const QString& str, m_collapseCount.keys() )
// {
// tDebug() << "\t" << str;
// foreach( JobStatusItem* chain, m_collapseCount[ str ] )
// qDebug() << "\t\t" << chain;
// }
if ( m_collapseCount.contains( item->type() ) ) if ( m_collapseCount.contains( item->type() ) )
{ {
const int indexOf = m_items.indexOf( m_collapseCount[ item->type() ].first() );
// tDebug() << "index in main list of collapsed irst item:" << indexOf;
if ( m_collapseCount[ item->type() ].first() == item &&
m_items.contains( m_collapseCount[ item->type() ].first() ) && m_collapseCount[ item->type() ].size() > 1 )
{
// the placeholder we use that links m_items and m_collapsecount is done, so choose another one
m_items.replace( m_items.indexOf( m_collapseCount[ item->type() ].first() ), m_collapseCount[ item->type() ][ 1 ] );
// qDebug() << "Replaced" << m_collapseCount[ item->type() ].first() << "with:" << m_collapseCount[ item->type() ][ 1 ] << m_items;
}
m_collapseCount[ item->type() ].removeAll( item ); m_collapseCount[ item->type() ].removeAll( item );
// tDebug() << "New collapse count list:" << m_collapseCount[ item->type() ];
if ( m_collapseCount[ item->type() ].isEmpty() ) if ( m_collapseCount[ item->type() ].isEmpty() )
m_collapseCount.remove( item->type() ); m_collapseCount.remove( item->type() );
else else
{ {
// One less to count, but item is still there // One less to count, but item is still there
const QModelIndex idx = index( m_items.indexOf( m_collapseCount[ item->type() ].first() ), 0, QModelIndex() ); const QModelIndex idx = index( indexOf, 0, QModelIndex() );
emit dataChanged( idx, idx ); emit dataChanged( idx, idx );
return; return;
} }

View File

@@ -19,10 +19,12 @@
#ifndef JOBSTATUSMODEL_H #ifndef JOBSTATUSMODEL_H
#define JOBSTATUSMODEL_H #define JOBSTATUSMODEL_H
#include "dllmacro.h"
#include <QModelIndex> #include <QModelIndex>
class JobStatusItem; class JobStatusItem;
class JobStatusModel : public QAbstractListModel class DLLEXPORT JobStatusModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -34,11 +34,14 @@
using namespace Tomahawk; using namespace Tomahawk;
JobStatusView* JobStatusView::s_instance = 0;
JobStatusView::JobStatusView( AnimatedSplitter* parent ) JobStatusView::JobStatusView( AnimatedSplitter* parent )
: AnimatedWidget( parent ) : AnimatedWidget( parent )
, m_parent( parent ) , m_parent( parent )
{ {
s_instance = this;
setHiddenSize( QSize( 0, 0 ) ); setHiddenSize( QSize( 0, 0 ) );
setLayout( new QVBoxLayout() ); setLayout( new QVBoxLayout() );
m_view = new QListView( this ); m_view = new QListView( this );
@@ -73,8 +76,9 @@ JobStatusView::JobStatusView( AnimatedSplitter* parent )
} }
void void
JobStatusView::setModel( QAbstractItemModel* m ) JobStatusView::setModel( JobStatusModel* m )
{ {
m_model = m;
m_view->setModel( m ); m_view->setModel( m );
m_view->setItemDelegate( new JobStatusDelegate( m_view ) ); m_view->setItemDelegate( new JobStatusDelegate( m_view ) );
@@ -90,6 +94,8 @@ JobStatusView::checkCount()
else if ( isHidden() && m_view->model()->rowCount() > 0 ) else if ( isHidden() && m_view->model()->rowCount() > 0 )
emit showWidget(); emit showWidget();
emit sizeChanged( sizeHint() );
} }

View File

@@ -22,17 +22,22 @@
#include "typedefs.h" #include "typedefs.h"
#include "widgets/animatedsplitter.h" #include "widgets/animatedsplitter.h"
#include "dllmacro.h"
class QAbstractItemModel; class QAbstractItemModel;
class QListView; class QListView;
class JobStatusModel; class JobStatusModel;
class StreamConnection; class StreamConnection;
class JobStatusView : public AnimatedWidget class DLLEXPORT JobStatusView : public AnimatedWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
static JobStatusView* instance() {
return s_instance;
}
explicit JobStatusView( AnimatedSplitter* parent ); explicit JobStatusView( AnimatedSplitter* parent );
virtual ~JobStatusView() virtual ~JobStatusView()
{ {
@@ -40,14 +45,19 @@ public:
QSize sizeHint() const; QSize sizeHint() const;
void setModel( QAbstractItemModel* model ); void setModel( JobStatusModel* model );
JobStatusModel* model() { return m_model; }
private slots: private slots:
void checkCount(); void checkCount();
private: private:
QListView* m_view; QListView* m_view;
JobStatusModel* m_model;
AnimatedSplitter* m_parent; AnimatedSplitter* m_parent;
static JobStatusView* s_instance;
}; };
#endif // JOBSTATUSVIEW_H #endif // JOBSTATUSVIEW_H

View File

@@ -22,6 +22,7 @@
#include "pipeline.h" #include "pipeline.h"
#include "tomahawkapp.h" #include "tomahawkapp.h"
#include "JobStatusModel.h" #include "JobStatusModel.h"
#include "JobStatusView.h"
PipelineStatusItem::PipelineStatusItem() PipelineStatusItem::PipelineStatusItem()
: JobStatusItem() : JobStatusItem()
@@ -76,6 +77,6 @@ PipelineStatusManager::resolving( const Tomahawk::query_ptr& p )
{ {
// No current query item and we're resolving something, so show it // No current query item and we're resolving something, so show it
m_curItem = QWeakPointer< PipelineStatusItem >( new PipelineStatusItem ); m_curItem = QWeakPointer< PipelineStatusItem >( new PipelineStatusItem );
APP->mainWindow()->jobsModel()->addJob( m_curItem.data() ); JobStatusView::instance()->model()->addJob( m_curItem.data() );
} }
} }

View File

@@ -22,6 +22,9 @@
#include "utils/tomahawkutils.h" #include "utils/tomahawkutils.h"
#include "query.h" #include "query.h"
#include "sourcelist.h" #include "sourcelist.h"
#include "jobview/JobStatusView.h"
#include "jobview/JobStatusModel.h"
#include <qjson/parser.h> #include <qjson/parser.h>
#include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkAccessManager>
@@ -29,30 +32,51 @@
using namespace Tomahawk; using namespace Tomahawk;
QPixmap SpotifyParser::s_pixmap = QPixmap(); QPixmap* SpotifyParser::s_pixmap = 0;
SpotifyJobNotifier::SpotifyJobNotifier( const QString &type, const QPixmap& pixmap ) SpotifyJobNotifier::SpotifyJobNotifier( QNetworkReply* job )
: JobStatusItem() : JobStatusItem()
, m_type( type ) , m_type( "track" )
, m_icon( pixmap ) , m_job( job )
{
connect( job, SIGNAL( finished() ), this, SLOT( setFinished()) );
}
SpotifyJobNotifier::SpotifyJobNotifier()
: JobStatusItem()
, m_type( "playlist" )
, m_job( 0 )
{ {
} }
SpotifyJobNotifier::~SpotifyJobNotifier() SpotifyJobNotifier::~SpotifyJobNotifier()
{} {}
QString QString
SpotifyJobNotifier::rightColumnText() const SpotifyJobNotifier::rightColumnText() const
{ {
return QString();
} }
QPixmap
SpotifyJobNotifier::icon() const
{
return SpotifyParser::pixmap();
}
QString QString
SpotifyJobNotifier::mainText() const SpotifyJobNotifier::mainText() const
{ {
return tr( "Parsing Spotify %1" ).arg( m_type );
} }
void
SpotifyJobNotifier::setFinished()
{
emit finished();
}
SpotifyParser::SpotifyParser( const QStringList& Urls, bool createNewPlaylist, QObject* parent ) SpotifyParser::SpotifyParser( const QStringList& Urls, bool createNewPlaylist, QObject* parent )
@@ -60,6 +84,7 @@ SpotifyParser::SpotifyParser( const QStringList& Urls, bool createNewPlaylist, Q
, m_single( false ) , m_single( false )
, m_trackMode( true ) , m_trackMode( true )
, m_createNewPlaylist( createNewPlaylist ) , m_createNewPlaylist( createNewPlaylist )
, m_playlistJob( 0 )
{ {
foreach ( const QString& url, Urls ) foreach ( const QString& url, Urls )
@@ -71,16 +96,13 @@ SpotifyParser::SpotifyParser( const QString& Url, bool createNewPlaylist, QObjec
, m_single( true ) , m_single( true )
, m_trackMode( true ) , m_trackMode( true )
, m_createNewPlaylist( createNewPlaylist ) , m_createNewPlaylist( createNewPlaylist )
, m_playlistJob( 0 )
{ {
if ( s_pixmap.isNull() )
s_pixmap.load( RESPATH "images/spotify-logo.jpg" );
lookupUrl( Url ); lookupUrl( Url );
} }
SpotifyParser::~SpotifyParser() SpotifyParser::~SpotifyParser()
{ {
} }
@@ -116,6 +138,9 @@ SpotifyParser::lookupPlaylist( const QString& link )
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) ); QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
connect( reply, SIGNAL( finished() ), this, SLOT( spotifyPlaylistLookupFinished() ) ); connect( reply, SIGNAL( finished() ), this, SLOT( spotifyPlaylistLookupFinished() ) );
m_playlistJob = new SpotifyJobNotifier();
JobStatusView::instance()->model()->addJob( m_playlistJob );
m_queries.insert( reply ); m_queries.insert( reply );
} }
@@ -142,6 +167,9 @@ SpotifyParser::lookupTrack( const QString& link )
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) ); QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
connect( reply, SIGNAL( finished() ), this, SLOT( spotifyTrackLookupFinished() ) ); connect( reply, SIGNAL( finished() ), this, SLOT( spotifyTrackLookupFinished() ) );
SpotifyJobNotifier* j = new SpotifyJobNotifier( reply );
JobStatusView::instance()->model()->addJob( j );
m_queries.insert( reply ); m_queries.insert( reply );
} }
@@ -262,6 +290,8 @@ SpotifyParser::checkPlaylistFinished()
tDebug() << "Checking for spotify batch playlist job finished" << m_queries.isEmpty() << m_createNewPlaylist; tDebug() << "Checking for spotify batch playlist job finished" << m_queries.isEmpty() << m_createNewPlaylist;
if ( m_queries.isEmpty() ) // we're done if ( m_queries.isEmpty() ) // we're done
{ {
if ( m_playlistJob )
m_playlistJob->setFinished();
if( m_createNewPlaylist ) if( m_createNewPlaylist )
m_playlist = Playlist::create( SourceList::instance()->getLocal(), m_playlist = Playlist::create( SourceList::instance()->getLocal(),
uuid(), uuid(),
@@ -294,3 +324,12 @@ SpotifyParser::checkTrackFinished()
} }
} }
QPixmap
SpotifyParser::pixmap()
{
if ( !s_pixmap )
s_pixmap = new QPixmap( RESPATH "images/spotify-logo.jpg" );
return *s_pixmap;
}

View File

@@ -34,6 +34,31 @@ class QNetworkReply;
namespace Tomahawk namespace Tomahawk
{ {
class DLLEXPORT SpotifyJobNotifier : public JobStatusItem
{
Q_OBJECT
public:
// track
SpotifyJobNotifier( QNetworkReply* job );
// playlist
SpotifyJobNotifier();
virtual ~SpotifyJobNotifier();
virtual QString rightColumnText() const;
virtual QString mainText() const;
virtual QPixmap icon() const;
virtual QString type() const { return m_type; }
virtual bool collapseItem() const { return true; }
public slots:
void setFinished();
private:
QString m_type;
QNetworkReply* m_job;
};
/** /**
* Small class to parse spotify links into query_ptrs * Small class to parse spotify links into query_ptrs
* *
@@ -43,6 +68,7 @@ class DLLEXPORT SpotifyParser : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
friend class SpotifyJobNotifier;
explicit SpotifyParser( const QString& trackUrl, bool createNewPlaylist = false, QObject* parent = 0 ); explicit SpotifyParser( const QString& trackUrl, bool createNewPlaylist = false, QObject* parent = 0 );
explicit SpotifyParser( const QStringList& trackUrls, bool createNewPlaylist = false, QObject* parent = 0 ); explicit SpotifyParser( const QStringList& trackUrls, bool createNewPlaylist = false, QObject* parent = 0 );
virtual ~SpotifyParser(); virtual ~SpotifyParser();
@@ -57,6 +83,8 @@ private slots:
void spotifyPlaylistLookupFinished(); void spotifyPlaylistLookupFinished();
private: private:
static QPixmap pixmap();
void lookupUrl( const QString& url ); void lookupUrl( const QString& url );
void lookupTrack( const QString& track ); void lookupTrack( const QString& track );
void lookupPlaylist( const QString& playlist ); void lookupPlaylist( const QString& playlist );
@@ -70,29 +98,9 @@ private:
QSet< QNetworkReply* > m_queries; QSet< QNetworkReply* > m_queries;
QString m_title, m_info, m_creator; QString m_title, m_info, m_creator;
Tomahawk::playlist_ptr m_playlist; Tomahawk::playlist_ptr m_playlist;
SpotifyJobNotifier* m_playlistJob;
static QPixmap s_pixmap; static QPixmap* s_pixmap;
};
class DLLEXPORT SpotifyJobNotifier : public JobStatusItem
{
Q_OBJECT
friend class SpotifyParser;
public:
SpotifyJobNotifier( const QString& type, const QPixmap& pixmap );
virtual ~SpotifyJobNotifier();
virtual QString rightColumnText() const;
virtual QString mainText() const;
virtual QPixmap icon() const { return m_icon; }
virtual QString type() const { return m_type; }
virtual bool collapseItem() const { return true; }
private:
void set
QPixmap m_icon;
QString m_type;
}; };
} }

View File

@@ -57,7 +57,6 @@ public:
AudioControls* audioControls() { return m_audioControls; } AudioControls* audioControls() { return m_audioControls; }
SourceTreeView* sourceTreeView() const { return m_sourcetree; } SourceTreeView* sourceTreeView() const { return m_sourcetree; }
JobStatusModel* jobsModel() const { return m_jobsModel; }
void setWindowTitle( const QString& title ); void setWindowTitle( const QString& title );