mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-01 11:50:37 +02:00
Remove some features, fix up whitespace and a few misc other things
Some fixups, parse spotify tracks in result
This commit is contained in:
@@ -36,7 +36,7 @@ ContextMenu::ContextMenu( QWidget* parent )
|
|||||||
m_sigmap = new QSignalMapper( this );
|
m_sigmap = new QSignalMapper( this );
|
||||||
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) );
|
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) );
|
||||||
|
|
||||||
m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink | ActionAddToPlaylist;
|
m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextMenu::~ContextMenu()
|
ContextMenu::~ContextMenu()
|
||||||
@@ -77,25 +77,6 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
|||||||
if ( m_supportedActions & ActionQueue )
|
if ( m_supportedActions & ActionQueue )
|
||||||
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
|
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ( m_supportedActions & ActionAddToPlaylist ){
|
|
||||||
|
|
||||||
QList<playlist_ptr> p = SourceList::instance()->getLocal()->collection()->playlists();
|
|
||||||
QMenu *addTo = new QMenu("Add to");
|
|
||||||
for(int i = 0; i< p.count(); i++){
|
|
||||||
m_sigmap->setMapping( addTo->addAction( p[i]->title() ), p[i]->guid() );
|
|
||||||
m_sigmap->setMapping( addMenu( addTo ), ActionAddToPlaylist );
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ( QAction* action, addTo->actions() )
|
|
||||||
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
|
|
||||||
|
|
||||||
connect(m_sigmap, SIGNAL(mapped(QString)),
|
|
||||||
this, SLOT(onAction(QString)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
addSeparator();
|
addSeparator();
|
||||||
|
|
||||||
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||||
@@ -204,22 +185,6 @@ ContextMenu::setArtist( const Tomahawk::artist_ptr& artist )
|
|||||||
setArtists( artists );
|
setArtists( artists );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ContextMenu::onClicked( int action )
|
|
||||||
{
|
|
||||||
qDebug() << Q_FUNC_INFO << "Action:" << action;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ContextMenu::onAction( const QString& what )
|
|
||||||
{
|
|
||||||
playlist_ptr p = SourceList::instance()->getLocal()->collection()->playlist( what );
|
|
||||||
p->addEntries( m_queries, p->currentrevision());
|
|
||||||
qDebug() << Q_FUNC_INFO << "Adding track to guid" << what << "With title" << p->title();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ContextMenu::onTriggered( int action )
|
ContextMenu::onTriggered( int action )
|
||||||
{
|
{
|
||||||
@@ -262,7 +227,6 @@ void ContextMenu::addToQueue()
|
|||||||
void
|
void
|
||||||
ContextMenu::copyLink()
|
ContextMenu::copyLink()
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
if ( m_queries.count() )
|
if ( m_queries.count() )
|
||||||
{
|
{
|
||||||
GlobalActionManager::instance()->copyToClipboard( m_queries.first() );
|
GlobalActionManager::instance()->copyToClipboard( m_queries.first() );
|
||||||
|
@@ -38,8 +38,7 @@ public:
|
|||||||
ActionPlay = 1,
|
ActionPlay = 1,
|
||||||
ActionQueue = 2,
|
ActionQueue = 2,
|
||||||
ActionDelete = 4,
|
ActionDelete = 4,
|
||||||
ActionCopyLink = 8,
|
ActionCopyLink = 8
|
||||||
ActionAddToPlaylist = 9
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,21 +63,18 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void triggered( int action );
|
void triggered( int action );
|
||||||
void clicked( int action );
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onTriggered( int action );
|
void onTriggered( int action );
|
||||||
void onClicked( int action );
|
|
||||||
void copyLink();
|
void copyLink();
|
||||||
void addToQueue();
|
void addToQueue();
|
||||||
void onAction(const QString& what);
|
|
||||||
private:
|
private:
|
||||||
QSignalMapper* m_sigmap;
|
QSignalMapper* m_sigmap;
|
||||||
int m_supportedActions;
|
int m_supportedActions;
|
||||||
|
|
||||||
QList<Tomahawk::query_ptr> m_queries;
|
QList<Tomahawk::query_ptr> m_queries;
|
||||||
QList<Tomahawk::artist_ptr> m_artists;
|
QList<Tomahawk::artist_ptr> m_artists;
|
||||||
playlist_ptr m_playlist;
|
|
||||||
QList<Tomahawk::album_ptr> m_albums;
|
QList<Tomahawk::album_ptr> m_albums;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -33,6 +33,8 @@
|
|||||||
#include "utils/xspfloader.h"
|
#include "utils/xspfloader.h"
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
bool DropJob::s_canParseSpotifyPlaylists = false;
|
||||||
|
|
||||||
DropJob::DropJob( QObject *parent )
|
DropJob::DropJob( QObject *parent )
|
||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
, m_queryCount( 0 )
|
, m_queryCount( 0 )
|
||||||
@@ -62,39 +64,8 @@ DropJob::mimeTypes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DropJob::DropAction()
|
DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType, DropJob::DropAction acceptedAction )
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( dropAction() == DropJob::Create )
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType, DropJob::DropActions acceptedAction)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
if (acceptedType.testFlag(DropJob::None))
|
|
||||||
qDebug() << Q_FUNC_INFO << "AcceptedType is None";
|
|
||||||
|
|
||||||
if (acceptedType.testFlag(DropJob::All))
|
|
||||||
qDebug() << Q_FUNC_INFO << "AcceptedType is All";
|
|
||||||
|
|
||||||
if (acceptedType.testFlag(DropJob::Playlist))
|
|
||||||
qDebug() << Q_FUNC_INFO << "AcceptedType is Playlist";
|
|
||||||
|
|
||||||
if (acceptedType.testFlag(DropJob::Track))
|
|
||||||
qDebug() << Q_FUNC_INFO << "AcceptedType is Track";
|
|
||||||
|
|
||||||
if (acceptedAction.testFlag(DropJob::Append))
|
|
||||||
qDebug() << Q_FUNC_INFO << "AcceptedAction is Append";
|
|
||||||
|
|
||||||
if (acceptedAction.testFlag(DropJob::Create))
|
|
||||||
qDebug() << Q_FUNC_INFO << "AcceptedAction is Create";
|
|
||||||
|
|
||||||
if ( data->hasFormat( "application/tomahawk.query.list" )
|
if ( data->hasFormat( "application/tomahawk.query.list" )
|
||||||
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
||||||
|| data->hasFormat( "application/tomahawk.result.list" )
|
|| data->hasFormat( "application/tomahawk.result.list" )
|
||||||
@@ -106,59 +77,49 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( data->hasFormat( "text/plain" )
|
// check plain text url types
|
||||||
&& data->data( "text/plain" ).contains( "xspf" )
|
if ( !data->hasFormat( "text/plain" ) )
|
||||||
&& ( acceptedType.testFlag(DropJob::Playlist) || acceptedType.testFlag(DropJob::All) )
|
return false;
|
||||||
&& acceptedAction.testFlag(DropJob::Create)
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// crude check for spotify playlists
|
const QString url = data->data( "text/plain" );
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" )
|
|
||||||
&& data->data( "text/plain" ).contains( "playlist" )
|
|
||||||
&& ( acceptedType.testFlag(DropJob::Playlist) || acceptedType.testFlag(DropJob::All) )
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// crude check for itunes tracks
|
if ( acceptedType.testFlag( Playlist ) )
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "itunes" )
|
{
|
||||||
&& data->data( "text/plain" ).contains( "album" )
|
if( url.contains( "xspf" ) )
|
||||||
&& ( acceptedType.testFlag(DropJob::Track)
|
return true;
|
||||||
|| acceptedType.testFlag(DropJob::Album)
|
|
||||||
|| acceptedType.testFlag(DropJob::All)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// crude check for itunes artist
|
// Not the most elegant
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "itunes" )
|
if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists )
|
||||||
&& data->data( "text/plain" ).contains( "artist" )
|
return true;
|
||||||
&& ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) )
|
}
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// crude check for spotify tracks
|
if ( acceptedType.testFlag( Track ) )
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" )
|
{
|
||||||
&& data->data( "text/plain" ).contains( "track" )
|
if ( url.contains( "itunes" ) && url.contains( "album" ) ) // YES itunes is fucked up and song links have album/ in the url.
|
||||||
&& ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) )
|
return true;
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// crude check for rdio tracks
|
if ( url.contains( "spotify" ) && url.contains( "track" ) )
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" )
|
return true;
|
||||||
&& data->data( "text/plain" ).contains( "track" )
|
|
||||||
&& ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) )
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
if ( url.contains( "rdio.com" ) && url.contains( "track" ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( acceptedType.testFlag( Album ) )
|
||||||
|
{
|
||||||
|
if ( url.contains( "itunes" ) && url.contains( "album" ) ) // YES itunes is fucked up and song links have album/ in the url.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( acceptedType.testFlag( Artist ) )
|
||||||
|
{
|
||||||
|
if ( url.contains( "itunes" ) && url.contains( "artist" ) ) // YES itunes is fucked up and song links have album/ in the url.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
||||||
// so we do an extra level of lookup
|
// so we do an extra level of lookup
|
||||||
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
|
if ( url.contains( "bit.ly" ) || url.contains( "j.mp" ) || url.contains( "t.co" ) || url.contains( "rd.io" ) )
|
||||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
|
|
||||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
|
|
||||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) )
|
|
||||||
&& ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) ) )
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -202,26 +163,6 @@ DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates, bool o
|
|||||||
void
|
void
|
||||||
DropJob::parseMimeData( const QMimeData *data )
|
DropJob::parseMimeData( const QMimeData *data )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << data->hasText();
|
|
||||||
|
|
||||||
if(dropTypes() & DropJob::Playlist)
|
|
||||||
qDebug() << Q_FUNC_INFO << "DropType is Playlist";
|
|
||||||
if(dropTypes() & DropJob::All)
|
|
||||||
qDebug() << Q_FUNC_INFO << "DropType is All";
|
|
||||||
if(dropTypes() & DropJob::Track)
|
|
||||||
qDebug() << Q_FUNC_INFO << "DropType is Track";
|
|
||||||
if(dropTypes() & DropJob::Artist)
|
|
||||||
qDebug() << Q_FUNC_INFO << "DropType is Artist";
|
|
||||||
if(DropTypes() & DropJob::None)
|
|
||||||
qDebug() << Q_FUNC_INFO << "DropType is None";
|
|
||||||
else qDebug() << "DropType is I DONT KNOW!";
|
|
||||||
|
|
||||||
if(dropAction() == DropJob::Append)
|
|
||||||
qDebug() << Q_FUNC_INFO << "DropAction is Append";
|
|
||||||
if(dropAction() == DropJob::Create)
|
|
||||||
qDebug() << Q_FUNC_INFO << "DropAction is Create";
|
|
||||||
|
|
||||||
|
|
||||||
QList< query_ptr > results;
|
QList< query_ptr > results;
|
||||||
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
||||||
results = tracksFromQueryList( data );
|
results = tracksFromQueryList( data );
|
||||||
@@ -235,13 +176,12 @@ DropJob::parseMimeData( const QMimeData *data )
|
|||||||
tracksFromMixedData( data );
|
tracksFromMixedData( data );
|
||||||
else if ( data->hasFormat( "text/plain" ) )
|
else if ( data->hasFormat( "text/plain" ) )
|
||||||
{
|
{
|
||||||
QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() );
|
const QString plainData = QString::fromUtf8( data->data( "text/plain" ) );
|
||||||
qDebug() << Q_FUNC_INFO << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData.trimmed();
|
|
||||||
|
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "xspf" ) )
|
if ( plainData.contains( "xspf" ) )
|
||||||
handleXspf( data->data( "text/plain" ).trimmed(), DropAction() );
|
handleXspf( data->data( "text/plain" ).trimmed() );
|
||||||
else if ( plainData.contains( "spotify" ) && plainData.contains( "playlist" ) )
|
else if ( plainData.contains( "spotify" ) && plainData.contains( "playlist" ) && s_canParseSpotifyPlaylists )
|
||||||
handleSpPlaylist( plainData, DropAction() );
|
handleSpPlaylist( plainData );
|
||||||
else
|
else
|
||||||
handleTrackUrls ( plainData );
|
handleTrackUrls ( plainData );
|
||||||
}
|
}
|
||||||
@@ -426,87 +366,77 @@ DropJob::tracksFromMixedData( const QMimeData *data )
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DropJob::handleXspf( const QString& fileUrl, bool createNewPlaylist )
|
DropJob::handleXspf( const QString& fileUrl )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << "Got xspf playlist!!" << fileUrl;
|
tDebug() << Q_FUNC_INFO << "Got xspf playlist!!" << fileUrl;
|
||||||
|
|
||||||
// Doing like so on *nix, dont know really how files are
|
// Doing like so on *nix, dont know really how files are
|
||||||
// passed on others.
|
// passed on others.
|
||||||
qDebug() << "Got xspf playlist!!";
|
// TODO look in to!
|
||||||
QString newFile = fileUrl;
|
// QString newFile = fileUrl;
|
||||||
newFile.replace("file://", "");
|
// newFile.replace("file://", "");
|
||||||
QFile xspfFile(newFile);
|
// QFile xspfFile(newFile);
|
||||||
XSPFLoader* l = new XSPFLoader( createNewPlaylist, this );
|
// XSPFLoader* l = new XSPFLoader( createNewPlaylist, this );
|
||||||
tDebug( LOGINFO ) << "Loading local xspf:" << newFile;
|
// tDebug( LOGINFO ) << "Loading local xspf:" << newFile;
|
||||||
l->load( xspfFile );
|
// l->load( xspfFile );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DropJob::handleSpPlaylist( const QString& url, bool createNewPlaylist)
|
DropJob::handleSpPlaylist( const QString& url )
|
||||||
{
|
{
|
||||||
|
|
||||||
qDebug() << "Got spotify playlist!!" << url;
|
qDebug() << "Got spotify playlist!!" << url;
|
||||||
|
|
||||||
if ( url.contains( "open.spotify.com/user") ||
|
QString playlistUri = url;
|
||||||
url.contains( "spotify:user" ) )
|
if ( url.contains( "open.spotify.com/user" ) ) // convert to a URI
|
||||||
{
|
{
|
||||||
// Lets create a valid playlist uri
|
playlistUri.replace("http://open.spotify.com/", "");
|
||||||
QString playlistUri = url;
|
playlistUri.replace( "/", ":" );
|
||||||
QString validUri;
|
playlistUri = "spotify:" + playlistUri;
|
||||||
|
}
|
||||||
|
|
||||||
if(url.contains( "open.spotify.com/user")){
|
tDebug() << "Got a spotify playlist uri in dropjob!" << playlistUri;
|
||||||
playlistUri.replace("http://open.spotify.com/", "");
|
SpotifyParser* spot = new SpotifyParser( playlistUri, dropAction() == Create, this );
|
||||||
QStringList playlist = playlistUri.split( "/" );
|
|
||||||
validUri = "spotify:" + playlist.join(":");
|
|
||||||
}else validUri = playlistUri;
|
|
||||||
|
|
||||||
tDebug() << "Got a spotify playlist in dropjob!" << validUri;
|
//This currently supports draging and dropping a spotify playlist
|
||||||
SpotifyParser* spot = new SpotifyParser( validUri, this, createNewPlaylist);
|
if ( dropAction() == Append )
|
||||||
|
{
|
||||||
//This currently supports draging and dropping a spotify playlist
|
tDebug() << Q_FUNC_INFO << "Asking for spotify playlist contents from" << playlistUri;
|
||||||
if(createNewPlaylist){
|
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||||
qDebug() << Q_FUNC_INFO << "Got spotify playlist!! Create new" << url;
|
}
|
||||||
}else{
|
|
||||||
qDebug() << Q_FUNC_INFO << "Got spotify playlist!!" << url;
|
|
||||||
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_queryCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
m_queryCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DropJob::handleTrackUrls( const QString& urls )
|
DropJob::handleTrackUrls( const QString& urls )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << urls;
|
// TODO REMOVE HACK
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ( urls.contains( "open.spotify.com/user") ||
|
if ( urls.contains( "open.spotify.com/user") ||
|
||||||
urls.contains( "spotify:user" ) )
|
urls.contains( "spotify:user" ) )
|
||||||
handleSpPlaylist( urls, dropAction() );
|
{
|
||||||
|
Q_ASSERT( false );
|
||||||
|
// handleSpPlaylist( urls, dropAction() );
|
||||||
|
}
|
||||||
else if ( urls.contains( "itunes.apple.com") )
|
else if ( urls.contains( "itunes.apple.com") )
|
||||||
{
|
{
|
||||||
QStringList tracks = urls.split(QRegExp("\\s+"), QString::SkipEmptyParts);
|
QStringList tracks = urls.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
|
||||||
|
|
||||||
tDebug() << "Got a list of itunes urls!" << tracks;
|
tDebug() << "Got a list of itunes urls!" << tracks;
|
||||||
ItunesParser* itunes = new ItunesParser( tracks, this );
|
ItunesParser* itunes = new ItunesParser( tracks, this );
|
||||||
connect( itunes, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
connect( itunes, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||||
m_queryCount++;
|
m_queryCount++;
|
||||||
}
|
}
|
||||||
else if ( urls.contains( "open.spotify.com/track") ||
|
else if ( urls.contains( "open.spotify.com/track") || urls.contains( "spotify:track" ) )
|
||||||
urls.contains( "spotify:track" ) )
|
|
||||||
{
|
{
|
||||||
QStringList tracks = urls.split(QRegExp("\\s+"), QString::SkipEmptyParts);
|
QStringList tracks = urls.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
|
||||||
|
|
||||||
tDebug() << "Got a list of spotify urls!" << tracks;
|
tDebug() << "Got a list of spotify urls!" << tracks;
|
||||||
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
||||||
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||||
m_queryCount++;
|
m_queryCount++;
|
||||||
} else if ( urls.contains( "rdio.com" ) )
|
}
|
||||||
|
else if ( urls.contains( "rdio.com" ) )
|
||||||
{
|
{
|
||||||
QStringList tracks = urls.split( "\n" );
|
QStringList tracks = urls.split( "\n" );
|
||||||
|
|
||||||
|
@@ -45,40 +45,53 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
enum DropType {
|
enum DropType {
|
||||||
|
None = 0x00,
|
||||||
|
Playlist = 0x01,
|
||||||
|
Track = 0x02,
|
||||||
|
Album = 0x04,
|
||||||
|
Artist = 0x08,
|
||||||
|
|
||||||
None = 0x00,
|
All = 0xFF
|
||||||
Playlist = 0x01,
|
};
|
||||||
Track = 0x02,
|
Q_DECLARE_FLAGS(DropTypes, DropType)
|
||||||
Album = 0x04,
|
|
||||||
Artist = 0x08,
|
|
||||||
All = 0x10
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_FLAGS(DropTypes, DropType)
|
enum DropAction {
|
||||||
|
Append = 0,
|
||||||
|
Create
|
||||||
|
};
|
||||||
|
|
||||||
enum DropAction {
|
/**
|
||||||
|
* Returns if the caller should accept this mimetype.
|
||||||
|
*
|
||||||
|
* \param data The mimetype object to check
|
||||||
|
* \param type The type of drop content to accept
|
||||||
|
* \param action What action is requested from the content, if not all data types support all actions
|
||||||
|
*/
|
||||||
|
static bool acceptsMimeData( const QMimeData* data, DropJob::DropTypes type = All, DropAction action = Append );
|
||||||
|
|
||||||
Append = 0x00,
|
|
||||||
Create = 0x01
|
|
||||||
|
|
||||||
};
|
|
||||||
Q_DECLARE_FLAGS(DropActions, DropAction)
|
|
||||||
|
|
||||||
|
|
||||||
static bool acceptsMimeData( const QMimeData* data, DropJob::DropTypes type = All, DropJob::DropActions action = Append );
|
|
||||||
static QStringList mimeTypes();
|
static QStringList mimeTypes();
|
||||||
|
|
||||||
virtual void setDropTypes( DropTypes types ) { m_dropTypes = types; }
|
/// Set the drop types that should be extracted from this drop
|
||||||
virtual void setDropAction( DropAction action ) { m_dropAction = action; }
|
void setDropTypes( DropTypes types ) { m_dropTypes = types; }
|
||||||
virtual DropTypes dropTypes() const { return m_dropTypes; }
|
|
||||||
virtual DropAction dropAction() const { return m_dropAction; }
|
/// Set the action that the drop should do. For example, if dropping a playlist, Create will create a new playlist but Append will generate the raw tracks
|
||||||
|
void setDropAction( DropAction action ) { m_dropAction = action; }
|
||||||
|
|
||||||
|
DropTypes dropTypes() const { return m_dropTypes; }
|
||||||
|
DropAction dropAction() const { return m_dropAction; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin the parsing of the mime data. The resulting tracks are exposed in the various signals
|
||||||
|
*/
|
||||||
void parseMimeData( const QMimeData* data );
|
void parseMimeData( const QMimeData* data );
|
||||||
|
|
||||||
void setGetWholeArtists( bool getWholeArtists );
|
void setGetWholeArtists( bool getWholeArtists );
|
||||||
void setGetWholeAlbums( bool getWholeAlbums );
|
void setGetWholeAlbums( bool getWholeAlbums );
|
||||||
void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false, bool onlyLocal = false, bool top10 = false );
|
void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false, bool onlyLocal = false, bool top10 = false );
|
||||||
void handleXspf( const QString& file, bool createNewPlaylist = false );
|
void handleXspf( const QString& file );
|
||||||
void handleSpPlaylist( const QString& url, bool createNewPlaylist = false );
|
void handleSpPlaylist( const QString& url );
|
||||||
|
|
||||||
|
static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; }
|
||||||
signals:
|
signals:
|
||||||
/// QMimeData parsing results
|
/// QMimeData parsing results
|
||||||
void tracks( const QList< Tomahawk::query_ptr >& tracks );
|
void tracks( const QList< Tomahawk::query_ptr >& tracks );
|
||||||
@@ -115,9 +128,11 @@ private:
|
|||||||
bool m_top10;
|
bool m_top10;
|
||||||
DropTypes m_dropTypes;
|
DropTypes m_dropTypes;
|
||||||
DropAction m_dropAction;
|
DropAction m_dropAction;
|
||||||
bool DropAction();
|
|
||||||
|
|
||||||
QList< Tomahawk::query_ptr > m_resultList;
|
QList< Tomahawk::query_ptr > m_resultList;
|
||||||
|
|
||||||
|
static bool s_canParseSpotifyPlaylists;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(DropJob::DropTypes)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(DropJob::DropTypes)
|
||||||
#endif // DROPJOB_H
|
#endif // DROPJOB_H
|
||||||
|
@@ -23,7 +23,6 @@
|
|||||||
#include "playlist/playlistmodel.h"
|
#include "playlist/playlistmodel.h"
|
||||||
#include "trackview.h"
|
#include "trackview.h"
|
||||||
#include "viewpage.h"
|
#include "viewpage.h"
|
||||||
#include "dropjob.h"
|
|
||||||
#include "dllmacro.h"
|
#include "dllmacro.h"
|
||||||
|
|
||||||
class DLLEXPORT PlaylistView : public TrackView, public Tomahawk::ViewPage
|
class DLLEXPORT PlaylistView : public TrackView, public Tomahawk::ViewPage
|
||||||
@@ -68,9 +67,6 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
PlaylistModel* m_model;
|
PlaylistModel* m_model;
|
||||||
bool m_resizing;
|
|
||||||
bool m_dragging;
|
|
||||||
QRect m_dropRect;
|
|
||||||
QString m_customTitle;
|
QString m_customTitle;
|
||||||
QString m_customDescripton;
|
QString m_customDescripton;
|
||||||
|
|
||||||
|
@@ -89,7 +89,7 @@ TrackView::TrackView( QWidget* parent )
|
|||||||
|
|
||||||
TrackView::~TrackView()
|
TrackView::~TrackView()
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
delete m_header;
|
delete m_header;
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ void
|
|||||||
TrackView::setModel( QAbstractItemModel* model )
|
TrackView::setModel( QAbstractItemModel* model )
|
||||||
{
|
{
|
||||||
Q_UNUSED( model );
|
Q_UNUSED( model );
|
||||||
qDebug() << "Explicitly use setTrackModel instead";
|
tDebug() << "Explicitly use setTrackModel instead";
|
||||||
Q_ASSERT( false );
|
Q_ASSERT( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ TrackView::onItemActivated( const QModelIndex& index )
|
|||||||
TrackModelItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( index ) );
|
TrackModelItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( index ) );
|
||||||
if ( item && !item->query().isNull() && item->query()->numResults() )
|
if ( item && !item->query().isNull() && item->query()->numResults() )
|
||||||
{
|
{
|
||||||
qDebug() << "Result activated:" << item->query()->toString() << item->query()->results().first()->url();
|
tDebug() << "Result activated:" << item->query()->toString() << item->query()->results().first()->url();
|
||||||
m_proxyModel->setCurrentIndex( index );
|
m_proxyModel->setCurrentIndex( index );
|
||||||
AudioEngine::instance()->playItem( m_proxyModel, item->query()->results().first() );
|
AudioEngine::instance()->playItem( m_proxyModel, item->query()->results().first() );
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ TrackView::keyPressEvent( QKeyEvent* event )
|
|||||||
void
|
void
|
||||||
TrackView::onItemResized( const QModelIndex& index )
|
TrackView::onItemResized( const QModelIndex& index )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
tDebug() << Q_FUNC_INFO;
|
||||||
m_delegate->updateRowSize( index );
|
m_delegate->updateRowSize( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ TrackView::resizeEvent( QResizeEvent* event )
|
|||||||
void
|
void
|
||||||
TrackView::dragEnterEvent( QDragEnterEvent* event )
|
TrackView::dragEnterEvent( QDragEnterEvent* event )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
tDebug() << Q_FUNC_INFO;
|
||||||
QTreeView::dragEnterEvent( event );
|
QTreeView::dragEnterEvent( event );
|
||||||
|
|
||||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||||
@@ -251,7 +251,6 @@ TrackView::dragEnterEvent( QDragEnterEvent* event )
|
|||||||
m_dragging = true;
|
m_dragging = true;
|
||||||
m_dropRect = QRect();
|
m_dropRect = QRect();
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Accepting Drag Event";
|
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,7 +305,7 @@ TrackView::dropEvent( QDropEvent* event )
|
|||||||
|
|
||||||
if ( event->isAccepted() )
|
if ( event->isAccepted() )
|
||||||
{
|
{
|
||||||
qDebug() << "Ignoring accepted event!";
|
tDebug() << "Ignoring accepted event!";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -315,7 +314,7 @@ TrackView::dropEvent( QDropEvent* event )
|
|||||||
const QPoint pos = event->pos();
|
const QPoint pos = event->pos();
|
||||||
const QModelIndex index = indexAt( pos );
|
const QModelIndex index = indexAt( pos );
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Drop Event accepted at row:" << index.row();
|
tDebug() << Q_FUNC_INFO << "Drop Event accepted at row:" << index.row();
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
|
|
||||||
if ( !model()->isReadOnly() )
|
if ( !model()->isReadOnly() )
|
||||||
@@ -395,7 +394,7 @@ TrackView::startDrag( Qt::DropActions supportedActions )
|
|||||||
if ( indexes.count() == 0 )
|
if ( indexes.count() == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "Dragging" << indexes.count() << "indexes";
|
tDebug() << "Dragging" << indexes.count() << "indexes";
|
||||||
QMimeData* data = m_proxyModel->mimeData( indexes );
|
QMimeData* data = m_proxyModel->mimeData( indexes );
|
||||||
if ( !data )
|
if ( !data )
|
||||||
return;
|
return;
|
||||||
|
@@ -31,23 +31,22 @@
|
|||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
ItunesParser::ItunesParser( const QStringList& Urls, QObject* parent, bool createNewPlaylist)
|
ItunesParser::ItunesParser( const QStringList& urls, QObject* parent )
|
||||||
: QObject ( parent )
|
: QObject ( parent )
|
||||||
, m_single( false )
|
, m_single( false )
|
||||||
|
|
||||||
{
|
{
|
||||||
m_createNewPlaylist = createNewPlaylist;
|
foreach ( const QString& url, urls )
|
||||||
foreach ( const QString& url, Urls ){
|
{
|
||||||
|
|
||||||
lookupItunesUri( url );
|
lookupItunesUri( url );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ItunesParser::ItunesParser( const QString& Url, QObject* parent, bool createNewPlaylist )
|
ItunesParser::ItunesParser( const QString& Url, QObject* parent )
|
||||||
: QObject ( parent )
|
: QObject ( parent )
|
||||||
, m_single( true )
|
, m_single( true )
|
||||||
{
|
{
|
||||||
m_createNewPlaylist = createNewPlaylist;
|
|
||||||
lookupItunesUri( Url );
|
lookupItunesUri( Url );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,17 +68,21 @@ ItunesParser::lookupItunesUri( const QString& link )
|
|||||||
|
|
||||||
// Doing a parse on regex in 2 stages,
|
// Doing a parse on regex in 2 stages,
|
||||||
// first, look if we have both album and track id
|
// first, look if we have both album and track id
|
||||||
int pos = rxAlbumTrack.indexIn(link);
|
int pos = rxAlbumTrack.indexIn( link );
|
||||||
if (pos > -1) {
|
if ( pos > -1 ) {
|
||||||
id = rxAlbumTrack.cap(1);
|
id = rxAlbumTrack.cap( 1 );
|
||||||
trackId = rxAlbumTrack.cap(2);
|
trackId = rxAlbumTrack.cap( 2 );
|
||||||
}else{
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Second, if we dont have trackId, check for just Id
|
// Second, if we dont have trackId, check for just Id
|
||||||
int pos = rxId.indexIn(link);
|
int pos = rxId.indexIn( link );
|
||||||
if (pos > -1) {
|
if ( pos > -1 )
|
||||||
id = rxId.cap(1);
|
{
|
||||||
}else return;
|
id = rxId.cap( 1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +92,8 @@ ItunesParser::lookupItunesUri( const QString& link )
|
|||||||
QUrl url;
|
QUrl url;
|
||||||
if( link.contains( "artist" ) )
|
if( link.contains( "artist" ) )
|
||||||
url = QUrl( QString( "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/wsLookup?id=%1&entity=song&limit=30" ).arg( id ) );
|
url = QUrl( QString( "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/wsLookup?id=%1&entity=song&limit=30" ).arg( id ) );
|
||||||
else url = QUrl( QString( "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/wsLookup?id=%1&entity=song" ).arg( ( trackId.isEmpty() ? id : trackId ) ) );
|
else
|
||||||
|
url = QUrl( QString( "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/wsLookup?id=%1&entity=song" ).arg( ( trackId.isEmpty() ? id : trackId ) ) );
|
||||||
|
|
||||||
qDebug() << "Looking up..." << url.toString();
|
qDebug() << "Looking up..." << url.toString();
|
||||||
|
|
||||||
@@ -125,11 +129,13 @@ ItunesParser::itunesResponseLookupFinished()
|
|||||||
}
|
}
|
||||||
QVariantList itunesResponse = res.value( "results" ).toList();
|
QVariantList itunesResponse = res.value( "results" ).toList();
|
||||||
|
|
||||||
foreach(QVariant itune, itunesResponse){
|
foreach ( QVariant itune, itunesResponse )
|
||||||
|
{
|
||||||
QString title, artist, album;
|
QString title, artist, album;
|
||||||
QVariantMap ituneMap = itune.toMap();
|
QVariantMap ituneMap = itune.toMap();
|
||||||
|
|
||||||
if( ituneMap.value( "wrapperType" ).toString().contains( "track" ) ){
|
if ( ituneMap.value( "wrapperType" ).toString().contains( "track" ) )
|
||||||
|
{
|
||||||
|
|
||||||
title = ituneMap.value( "trackName" ).toString();
|
title = ituneMap.value( "trackName" ).toString();
|
||||||
artist = ituneMap.value( "artistName" ).toString();
|
artist = ituneMap.value( "artistName" ).toString();
|
||||||
@@ -146,7 +152,6 @@ ItunesParser::itunesResponseLookupFinished()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
tLog() << "Error in network request to Itunes for track decoding:" << r->errorString();
|
tLog() << "Error in network request to Itunes for track decoding:" << r->errorString();
|
||||||
@@ -156,7 +161,6 @@ ItunesParser::itunesResponseLookupFinished()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ItunesParser::checkTrackFinished()
|
ItunesParser::checkTrackFinished()
|
||||||
{
|
{
|
||||||
|
@@ -29,11 +29,12 @@
|
|||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
class TrackModel;
|
class TrackModel;
|
||||||
|
|
||||||
namespace Tomahawk
|
namespace Tomahawk
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Small class to parse spotify links into query_ptrs
|
* Small class to parse itunes links into query_ptrs
|
||||||
*
|
*
|
||||||
* Connect to the signals to get the results
|
* Connect to the signals to get the results
|
||||||
*/
|
*/
|
||||||
@@ -41,16 +42,13 @@ class DLLEXPORT ItunesParser : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ItunesParser( const QString& trackUrl, QObject* parent = 0, bool createNewPl = false );
|
explicit ItunesParser( const QString& trackUrl, QObject* parent = 0 );
|
||||||
explicit ItunesParser( const QStringList& trackUrls, QObject* parent = 0, bool createNewPl = false);
|
explicit ItunesParser( const QStringList& trackUrls, QObject* parent = 0 );
|
||||||
virtual ~ItunesParser();
|
virtual ~ItunesParser();
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void track( const Tomahawk::query_ptr& track );
|
void track( const Tomahawk::query_ptr& track );
|
||||||
void tracks( const QList< Tomahawk::query_ptr > tracks );
|
void tracks( const QList< Tomahawk::query_ptr > tracks );
|
||||||
void playlist( const Tomahawk::query_ptr& playlist );
|
|
||||||
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void itunesResponseLookupFinished();
|
void itunesResponseLookupFinished();
|
||||||
@@ -60,7 +58,6 @@ private:
|
|||||||
void checkTrackFinished();
|
void checkTrackFinished();
|
||||||
|
|
||||||
bool m_single;
|
bool m_single;
|
||||||
bool m_createNewPlaylist;
|
|
||||||
QList< query_ptr > m_tracks;
|
QList< query_ptr > m_tracks;
|
||||||
QSet< QNetworkReply* > m_queries;
|
QSet< QNetworkReply* > m_queries;
|
||||||
QString m_title, m_info, m_creator;
|
QString m_title, m_info, m_creator;
|
||||||
|
@@ -29,21 +29,23 @@
|
|||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
SpotifyParser::SpotifyParser( const QStringList& Urls, QObject* parent, bool createNewPlaylist)
|
SpotifyParser::SpotifyParser( const QStringList& Urls, bool createNewPlaylist, QObject* parent )
|
||||||
: QObject ( parent )
|
: QObject ( parent )
|
||||||
, m_single( false )
|
, m_single( false )
|
||||||
|
, m_trackMode( true )
|
||||||
|
, m_createNewPlaylist( createNewPlaylist )
|
||||||
|
|
||||||
{
|
{
|
||||||
m_createNewPlaylist = createNewPlaylist;
|
|
||||||
foreach ( const QString& url, Urls )
|
foreach ( const QString& url, Urls )
|
||||||
lookupUrl( url );
|
lookupUrl( url );
|
||||||
}
|
}
|
||||||
|
|
||||||
SpotifyParser::SpotifyParser( const QString& Url, QObject* parent, bool createNewPlaylist )
|
SpotifyParser::SpotifyParser( const QString& Url, bool createNewPlaylist, QObject* parent )
|
||||||
: QObject ( parent )
|
: QObject ( parent )
|
||||||
, m_single( true )
|
, m_single( true )
|
||||||
|
, m_trackMode( true )
|
||||||
|
, m_createNewPlaylist( createNewPlaylist )
|
||||||
{
|
{
|
||||||
m_createNewPlaylist = createNewPlaylist;
|
|
||||||
lookupUrl( Url );
|
lookupUrl( Url );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,12 +58,18 @@ SpotifyParser::~SpotifyParser()
|
|||||||
void
|
void
|
||||||
SpotifyParser::lookupUrl( const QString& link )
|
SpotifyParser::lookupUrl( const QString& link )
|
||||||
{
|
{
|
||||||
|
|
||||||
if( link.contains( "track" ) )
|
if( link.contains( "track" ) )
|
||||||
lookupTrack(link);
|
{
|
||||||
|
m_trackMode = true;
|
||||||
|
lookupTrack( link );
|
||||||
|
}
|
||||||
else if( link.contains( "playlist" ) )
|
else if( link.contains( "playlist" ) )
|
||||||
|
{
|
||||||
|
m_trackMode = false;
|
||||||
lookupPlaylist( link );
|
lookupPlaylist( link );
|
||||||
else return; // We only support tracks and playlists
|
}
|
||||||
|
else
|
||||||
|
return; // We only support tracks and playlists
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +80,8 @@ SpotifyParser::lookupPlaylist( const QString& link )
|
|||||||
if ( !link.contains( "spotify:user:" ) ) // we only support playlist here
|
if ( !link.contains( "spotify:user:" ) ) // we only support playlist here
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString uri = link;
|
tLog() << "Parsing Spotify Playlist URI:" << link;
|
||||||
tLog() << "Parsing Spotify Playlist URI:" << uri;
|
QUrl url = QUrl( QString( SPOTIFY_PLAYLIST_API_URL "/playlist/%1" ).arg( link ) );
|
||||||
QUrl url = QUrl( QString( "http://www.trushuffle.com:5512/playlist/%1" ).arg( uri ) );
|
|
||||||
tDebug() << "Looking up URL..." << url.toString();
|
tDebug() << "Looking up URL..." << url.toString();
|
||||||
|
|
||||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||||
@@ -100,10 +107,8 @@ SpotifyParser::lookupTrack( const QString& link )
|
|||||||
uri = QString( "spotify:track:%1" ).arg( hash );
|
uri = QString( "spotify:track:%1" ).arg( hash );
|
||||||
}
|
}
|
||||||
|
|
||||||
tLog() << "Parsing Spotify Track URI:" << uri;
|
|
||||||
|
|
||||||
QUrl url = QUrl( QString( "http://ws.spotify.com/lookup/1/.json?uri=%1" ).arg( uri ) );
|
QUrl url = QUrl( QString( "http://ws.spotify.com/lookup/1/.json?uri=%1" ).arg( uri ) );
|
||||||
tDebug() << "Looking up..." << url.toString();
|
tLog() << "Looking up spotify track information..." << url.toString();
|
||||||
|
|
||||||
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() ) );
|
||||||
@@ -118,6 +123,7 @@ SpotifyParser::spotifyPlaylistLookupFinished()
|
|||||||
{
|
{
|
||||||
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
|
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
|
||||||
Q_ASSERT( r );
|
Q_ASSERT( r );
|
||||||
|
|
||||||
m_queries.remove( r );
|
m_queries.remove( r );
|
||||||
r->deleteLater();
|
r->deleteLater();
|
||||||
|
|
||||||
@@ -132,28 +138,25 @@ SpotifyParser::spotifyPlaylistLookupFinished()
|
|||||||
tLog() << "Failed to parse json from Spotify playlist lookup:" << p.errorString() << "On line" << p.errorLine();
|
tLog() << "Failed to parse json from Spotify playlist lookup:" << p.errorString() << "On line" << p.errorLine();
|
||||||
checkTrackFinished();
|
checkTrackFinished();
|
||||||
return;
|
return;
|
||||||
} else if ( !res.contains( "tracks" ) )
|
}
|
||||||
|
else if ( !res.contains( "tracks" ) )
|
||||||
{
|
{
|
||||||
tLog() << "No 'tracks' item in the spotify playlist lookup result... not doing anything";
|
tLog() << "No tracks' item in the spotify playlist lookup result... not doing anything";
|
||||||
checkTrackFinished();
|
checkTrackFinished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantList trackResponse = res.value( "tracks" ).toList();
|
QVariantList trackResponse = res.value( "tracks" ).toList();
|
||||||
if(!trackResponse.isEmpty()){
|
if ( !trackResponse.isEmpty() )
|
||||||
|
{
|
||||||
m_title = res.value( "title" ).toString();
|
m_title = res.value( "title" ).toString();
|
||||||
m_creator = res.value( "creator" ).toString();
|
m_creator = res.value( "creator" ).toString();
|
||||||
qDebug() << "playlist owner: " << m_creator;
|
qDebug() << "playlist owner: " << m_creator;
|
||||||
}
|
}
|
||||||
foreach(QVariant track, trackResponse){
|
|
||||||
|
|
||||||
QString title, artist, album;
|
|
||||||
title = track.toMap().value( "title" ).toString();
|
|
||||||
artist = track.toMap().value( "artists" ).toList().first().toString();
|
|
||||||
album = track.toMap().value( "album" ).toString();
|
|
||||||
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), true );
|
|
||||||
m_tracks << q;
|
|
||||||
|
|
||||||
|
foreach( QVariant track, trackResponse )
|
||||||
|
{
|
||||||
|
lookupTrack( track.toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
@@ -218,7 +221,10 @@ SpotifyParser::spotifyTrackLookupFinished()
|
|||||||
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
|
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkTrackFinished();
|
if ( m_trackMode )
|
||||||
|
checkTrackFinished();
|
||||||
|
else
|
||||||
|
checkPlaylistFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -226,7 +232,7 @@ SpotifyParser::checkPlaylistFinished()
|
|||||||
{
|
{
|
||||||
if ( m_queries.isEmpty() ) // we're done
|
if ( m_queries.isEmpty() ) // we're done
|
||||||
{
|
{
|
||||||
if(m_createNewPlaylist)
|
if( m_createNewPlaylist )
|
||||||
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
|
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
|
||||||
uuid(),
|
uuid(),
|
||||||
m_title,
|
m_title,
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QtCore/QStringList>
|
#include <QtCore/QStringList>
|
||||||
|
|
||||||
|
#define SPOTIFY_PLAYLIST_API_URL "http://spotikea.tomahawk-player.org:10380"
|
||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
namespace Tomahawk
|
namespace Tomahawk
|
||||||
{
|
{
|
||||||
@@ -40,8 +42,8 @@ class DLLEXPORT SpotifyParser : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit SpotifyParser( const QString& trackUrl, QObject* parent = 0, bool createNewPl = false );
|
explicit SpotifyParser( const QString& trackUrl, bool createNewPlaylist = false, QObject* parent = 0 );
|
||||||
explicit SpotifyParser( const QStringList& trackUrls, QObject* parent = 0, bool createNewPl = false);
|
explicit SpotifyParser( const QStringList& trackUrls, bool createNewPlaylist = false, QObject* parent = 0 );
|
||||||
virtual ~SpotifyParser();
|
virtual ~SpotifyParser();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -59,7 +61,9 @@ private:
|
|||||||
void lookupPlaylist( const QString& playlist );
|
void lookupPlaylist( const QString& playlist );
|
||||||
void checkTrackFinished();
|
void checkTrackFinished();
|
||||||
void checkPlaylistFinished();
|
void checkPlaylistFinished();
|
||||||
|
|
||||||
bool m_single;
|
bool m_single;
|
||||||
|
bool m_trackMode;
|
||||||
bool m_createNewPlaylist;
|
bool m_createNewPlaylist;
|
||||||
QList< query_ptr > m_tracks;
|
QList< query_ptr > m_tracks;
|
||||||
QSet< QNetworkReply* > m_queries;
|
QSet< QNetworkReply* > m_queries;
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include "libtomahawk/pipeline.h"
|
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
#include "viewmanager.h"
|
#include "viewmanager.h"
|
||||||
#include "sourcesproxymodel.h"
|
#include "sourcesproxymodel.h"
|
||||||
@@ -40,7 +40,6 @@
|
|||||||
#include "tomahawksettings.h"
|
#include "tomahawksettings.h"
|
||||||
#include "globalactionmanager.h"
|
#include "globalactionmanager.h"
|
||||||
#include "dropjob.h"
|
#include "dropjob.h"
|
||||||
#include "resolversmodel.h"
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "items/genericpageitems.h"
|
#include "items/genericpageitems.h"
|
||||||
#include "items/temporarypageitem.h"
|
#include "items/temporarypageitem.h"
|
||||||
@@ -160,16 +159,6 @@ SourceTreeView::setupMenus()
|
|||||||
m_copyPlaylistAction = m_playlistMenu.addAction( tr( "&Copy Link" ) );
|
m_copyPlaylistAction = m_playlistMenu.addAction( tr( "&Copy Link" ) );
|
||||||
m_deletePlaylistAction = m_playlistMenu.addAction( tr( "&Delete %1" ).arg( SourcesModel::rowTypeToString( type ) ) );
|
m_deletePlaylistAction = m_playlistMenu.addAction( tr( "&Delete %1" ).arg( SourcesModel::rowTypeToString( type ) ) );
|
||||||
|
|
||||||
// Add a menu for spotify export
|
|
||||||
TomahawkSettings* settings = TomahawkSettings::instance();
|
|
||||||
foreach(QString resolver, settings->enabledScriptResolvers() ){
|
|
||||||
if( resolver.contains( "spotify" ) ){
|
|
||||||
QAction *m_addToSpotify = m_playlistMenu.addAction( tr( "Add to &Spotify" ) );
|
|
||||||
connect( m_addToSpotify, SIGNAL( triggered() ), SLOT( addToSpotify() ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString addToText = QString( "Add to my %1" );
|
QString addToText = QString( "Add to my %1" );
|
||||||
if ( type == SourcesModel::StaticPlaylist )
|
if ( type == SourcesModel::StaticPlaylist )
|
||||||
addToText = addToText.arg( "Playlists" );
|
addToText = addToText.arg( "Playlists" );
|
||||||
@@ -252,36 +241,6 @@ SourceTreeView::loadPlaylist()
|
|||||||
onItemActivated( m_contextMenuIndex );
|
onItemActivated( m_contextMenuIndex );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
SourceTreeView::addToSpotify( )
|
|
||||||
{
|
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
|
|
||||||
QModelIndex idx = m_contextMenuIndex;
|
|
||||||
if ( !idx.isValid() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( idx, SourcesModel::SourceTreeItemTypeRole ).toInt();
|
|
||||||
if ( type == SourcesModel::StaticPlaylist )
|
|
||||||
{
|
|
||||||
PlaylistItem* item = itemFromIndex< PlaylistItem >( idx );
|
|
||||||
playlist_ptr playlist = item->playlist();
|
|
||||||
qDebug() << Q_FUNC_INFO << "Static playlist" << playlist->title();
|
|
||||||
// Do something with playlist -> spotify()
|
|
||||||
|
|
||||||
} else if( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station )
|
|
||||||
{
|
|
||||||
DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( idx );
|
|
||||||
dynplaylist_ptr playlist = item->dynPlaylist();
|
|
||||||
qDebug() << Q_FUNC_INFO << "Dynamic playlist" << playlist->title();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SourceTreeView::deletePlaylist( const QModelIndex& idxIn )
|
SourceTreeView::deletePlaylist( const QModelIndex& idxIn )
|
||||||
{
|
{
|
||||||
@@ -533,20 +492,18 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
|
|||||||
event->setDropAction( Qt::CopyAction );
|
event->setDropAction( Qt::CopyAction );
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Ignoring";
|
|
||||||
event->ignore();
|
|
||||||
}
|
|
||||||
}else if ( DropJob::acceptsMimeData( event->mimeData(), DropJob::Playlist, DropJob::Create ) )
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Should maybe ignore, but we are just dropping
|
qDebug() << Q_FUNC_INFO << "Ignoring";
|
||||||
// a playlist in the container, not on a specific playlist
|
event->ignore();
|
||||||
event->setDropAction( Qt::CopyAction );
|
|
||||||
event->accept();
|
|
||||||
}
|
}
|
||||||
setDirtyRegion( m_dropRect );
|
}
|
||||||
|
else if ( DropJob::acceptsMimeData( event->mimeData(), DropJob::Playlist, DropJob::Create ) )
|
||||||
|
{
|
||||||
|
event->setDropAction( Qt::CopyAction );
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
setDirtyRegion( m_dropRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -569,7 +526,6 @@ SourceTreeView::dropEvent( QDropEvent* event )
|
|||||||
// Need to fake the dropevent because the treeview would reject it if it is outside the item (on the tree)
|
// Need to fake the dropevent because the treeview would reject it if it is outside the item (on the tree)
|
||||||
if ( pos.x() < 100 )
|
if ( pos.x() < 100 )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << "New Event";
|
|
||||||
QDropEvent* newEvent = new QDropEvent( pos + QPoint( 100, 0 ), event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers(), event->type() );
|
QDropEvent* newEvent = new QDropEvent( pos + QPoint( 100, 0 ), event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers(), event->type() );
|
||||||
QTreeView::dropEvent( newEvent );
|
QTreeView::dropEvent( newEvent );
|
||||||
delete newEvent;
|
delete newEvent;
|
||||||
@@ -582,6 +538,7 @@ SourceTreeView::dropEvent( QDropEvent* event )
|
|||||||
dropThis->setDropTypes( DropJob::Playlist );
|
dropThis->setDropTypes( DropJob::Playlist );
|
||||||
dropThis->setDropAction( DropJob::Create );
|
dropThis->setDropAction( DropJob::Create );
|
||||||
dropThis->parseMimeData( event->mimeData() );
|
dropThis->parseMimeData( event->mimeData() );
|
||||||
|
|
||||||
QTreeView::dropEvent( event );
|
QTreeView::dropEvent( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -27,7 +27,6 @@ class PlaylistModel;
|
|||||||
class SourcesModel;
|
class SourcesModel;
|
||||||
class SourcesProxyModel;
|
class SourcesProxyModel;
|
||||||
class SourceDelegate;
|
class SourceDelegate;
|
||||||
class ResolversModel;
|
|
||||||
|
|
||||||
class SourceTreeView : public QTreeView
|
class SourceTreeView : public QTreeView
|
||||||
{
|
{
|
||||||
@@ -35,7 +34,7 @@ Q_OBJECT
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SourceTreeView( QWidget* parent = 0 );
|
explicit SourceTreeView( QWidget* parent = 0 );
|
||||||
//static bool acceptsMimeData( const QMimeData* data, bool playlistOnly = true );
|
|
||||||
public slots:
|
public slots:
|
||||||
void showOfflineSources( bool offlineSourcesShown );
|
void showOfflineSources( bool offlineSourcesShown );
|
||||||
|
|
||||||
@@ -54,7 +53,6 @@ private slots:
|
|||||||
void expandRequest( const QPersistentModelIndex& idx );
|
void expandRequest( const QPersistentModelIndex& idx );
|
||||||
|
|
||||||
void loadPlaylist();
|
void loadPlaylist();
|
||||||
void addToSpotify();
|
|
||||||
void deletePlaylist( const QModelIndex& = QModelIndex() );
|
void deletePlaylist( const QModelIndex& = QModelIndex() );
|
||||||
void copyPlaylistLink();
|
void copyPlaylistLink();
|
||||||
void addToLocal();
|
void addToLocal();
|
||||||
@@ -65,7 +63,6 @@ private slots:
|
|||||||
void onCustomContextMenu( const QPoint& pos );
|
void onCustomContextMenu( const QPoint& pos );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// void drawBranches( QPainter* painter, const QRect& rect, const QModelIndex& index ) const {}
|
|
||||||
void drawRow( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
void drawRow( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||||
|
|
||||||
virtual void paintEvent( QPaintEvent* event );
|
virtual void paintEvent( QPaintEvent* event );
|
||||||
@@ -81,7 +78,7 @@ private:
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
T* itemFromIndex( const QModelIndex& index ) const;
|
T* itemFromIndex( const QModelIndex& index ) const;
|
||||||
//void parseMimeData( const QMimeData* data );
|
|
||||||
SourcesModel* m_model;
|
SourcesModel* m_model;
|
||||||
SourcesProxyModel* m_proxyModel;
|
SourcesProxyModel* m_proxyModel;
|
||||||
QModelIndex m_contextMenuIndex;
|
QModelIndex m_contextMenuIndex;
|
||||||
@@ -100,7 +97,6 @@ private:
|
|||||||
|
|
||||||
bool m_dragging;
|
bool m_dragging;
|
||||||
QRect m_dropRect;
|
QRect m_dropRect;
|
||||||
ResolversModel* m_resolversModel;
|
|
||||||
QPersistentModelIndex m_dropIndex;
|
QPersistentModelIndex m_dropIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -54,6 +54,8 @@
|
|||||||
#include "musicscanner.h"
|
#include "musicscanner.h"
|
||||||
#include "AtticaManager.h"
|
#include "AtticaManager.h"
|
||||||
#include "pipeline.h"
|
#include "pipeline.h"
|
||||||
|
#include "utils/spotifyparser.h"
|
||||||
|
#include "dropjob.h"
|
||||||
|
|
||||||
#include "audio/audioengine.h"
|
#include "audio/audioengine.h"
|
||||||
#include "utils/xspfloader.h"
|
#include "utils/xspfloader.h"
|
||||||
@@ -80,6 +82,7 @@
|
|||||||
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
#include <thirdparty/jreen/bot/bot.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -261,6 +264,10 @@ TomahawkApp::init()
|
|||||||
|
|
||||||
// Make sure to init GAM in the gui thread
|
// Make sure to init GAM in the gui thread
|
||||||
GlobalActionManager::instance();
|
GlobalActionManager::instance();
|
||||||
|
|
||||||
|
// check if our spotify playlist api server is up and running, and enable spotify playlist drops if so
|
||||||
|
QNetworkReply* r = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( SPOTIFY_PLAYLIST_API_URL "/playlist/test" ) ) );
|
||||||
|
connect( r, SIGNAL( finished() ), this, SLOT( spotifyApiCheckFinished() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -501,6 +508,18 @@ TomahawkApp::initSIP()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TomahawkApp::spotifyApiCheckFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
|
||||||
|
Q_ASSERT( reply );
|
||||||
|
|
||||||
|
if ( reply->error() == QNetworkReply::ContentNotFoundError )
|
||||||
|
DropJob::setCanParseSpotifyPlaylists( true );
|
||||||
|
else
|
||||||
|
DropJob::setCanParseSpotifyPlaylists( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TomahawkApp::activate()
|
TomahawkApp::activate()
|
||||||
|
@@ -97,6 +97,7 @@ private slots:
|
|||||||
void initServent();
|
void initServent();
|
||||||
void initSIP();
|
void initSIP();
|
||||||
|
|
||||||
|
void spotifyApiCheckFinished();
|
||||||
private:
|
private:
|
||||||
void registerMetaTypes();
|
void registerMetaTypes();
|
||||||
|
|
||||||
@@ -109,8 +110,6 @@ private:
|
|||||||
|
|
||||||
void initHTTP();
|
void initHTTP();
|
||||||
|
|
||||||
void loadPlugins();
|
|
||||||
|
|
||||||
QList<Tomahawk::collection_ptr> m_collections;
|
QList<Tomahawk::collection_ptr> m_collections;
|
||||||
|
|
||||||
QWeakPointer<Database> m_database;
|
QWeakPointer<Database> m_database;
|
||||||
|
Reference in New Issue
Block a user