1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-20 15:59:42 +01:00

* Be prepared for empty query_ptrs being returned from Query::get().

This commit is contained in:
Christian Muehlhaeuser 2012-06-30 23:21:52 +02:00
parent 4d188af33e
commit becb263635
15 changed files with 168 additions and 105 deletions

View File

@ -617,16 +617,15 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
{
if ( parts.size() && parts[ 0 ] == "track" )
{
if ( queueSpotify( parts, queryItems ) )
return true;
else if ( queueRdio( parts, queryItems ) )
return true;
QPair< QString, QString > pair;
QString title, artist, album, urlStr;
foreach ( pair, queryItems ) {
foreach ( pair, queryItems )
{
pair.second = pair.second.replace( "+", " " ); // QUrl::queryItems doesn't decode + to a space :(
if ( pair.first == "title" )
title = pair.second;
@ -642,9 +641,12 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
{
// an individual; query to add to queue
query_ptr q = Query::get( artist, title, album, uuid(), false );
if ( q.isNull() )
return false;
if ( !urlStr.isEmpty() )
q->setResultHint( urlStr );
Pipeline::instance()->resolve( q, true );
Pipeline::instance()->resolve( q );
handleOpenTrack( q );
return true;
@ -666,9 +668,11 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
{ // give it a web result hint
QFileInfo info( track.path() );
query_ptr q = Query::get( QString(), info.baseName(), QString(), uuid(), false );
q->setResultHint( track.toString() );
if ( q.isNull() )
continue;
Pipeline::instance()->resolve( q, true );
q->setResultHint( track.toString() );
Pipeline::instance()->resolve( q );
ViewManager::instance()->queue()->model()->appendQuery( q );
ViewManager::instance()->showQueue();
@ -1067,6 +1071,9 @@ GlobalActionManager::handlePlayCommand( const QUrl& url )
}
query_ptr q = Query::get( artist, title, album );
if ( q.isNull() )
return false;
if ( !urlStr.isEmpty() )
q->setResultHint( urlStr );
@ -1155,18 +1162,25 @@ bool GlobalActionManager::handleBookmarkCommand(const QUrl& url)
urlStr = pair.second;
}
query_ptr q = Query::get( artist, title, album );
if ( q.isNull() )
return false;
if ( !urlStr.isEmpty() )
q->setResultHint( urlStr );
Pipeline::instance()->resolve( q, true );
Pipeline::instance()->resolve( q );
// now we add it to the special "bookmarks" playlist, creating it if it doesn't exist. if nothing is playing, start playing the track
QSharedPointer< LocalCollection > col = SourceList::instance()->getLocal()->collection().dynamicCast< LocalCollection >();
playlist_ptr bookmarkpl = col->bookmarksPlaylist();
if ( bookmarkpl.isNull() ) { // create it and do the deed then
if ( bookmarkpl.isNull() )
{
// create it and do the deed then
m_waitingToBookmark = q;
col->createBookmarksPlaylist();
connect( col.data(), SIGNAL( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), this, SLOT( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), Qt::UniqueConnection );
} else {
}
else
{
doBookmark( bookmarkpl, q );
}

View File

@ -132,7 +132,7 @@ LastFmConfig::onHistoryLoaded()
uint total = 0;
bool finished = false;
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
try
{
lastfm::XmlQuery lfm;
@ -142,22 +142,25 @@ LastFmConfig::onHistoryLoaded()
{
// tDebug() << "Found:" << e["artist"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt();
Tomahawk::query_ptr query = Query::get( e["artist"].text(), e["name"].text(), QString(), QString(), false );
if ( query.isNull() )
continue;
m_lastTimeStamp = e["date"].attribute( "uts" ).toUInt();
DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( query, DatabaseCommand_LogPlayback::Finished, m_lastTimeStamp );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
}
if ( !lfm.children( "recenttracks" ).isEmpty() )
{
lastfm::XmlQuery stats = lfm.children( "recenttracks" ).first();
uint page = stats.attribute( "page" ).toUInt();
total = stats.attribute( "totalPages" ).toUInt();
m_ui->progressBar->setMaximum( total );
m_ui->progressBar->setValue( page );
if ( page < total )
{
m_page = page + 1;
@ -174,7 +177,7 @@ LastFmConfig::onHistoryLoaded()
tDebug() << "XmlQuery error:" << e.message();
finished = true;
}
if ( finished )
{
if ( m_page != total )

View File

@ -674,6 +674,9 @@ SpotifyPlaylistUpdater::variantToQueries( const QVariantList& list )
{
QVariantMap trackMap = blob.toMap();
const query_ptr q = Query::get( trackMap.value( "artist" ).toString(), trackMap.value( "track" ).toString(), trackMap.value( "album" ).toString(), uuid(), false );
if ( q.isNull() )
continue;
if ( trackMap.contains( "id" ) )
q->setProperty( "annotation", trackMap.value( "id" ) );

View File

@ -91,6 +91,8 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
artist = query.value( 1 ).toString();
qry = Tomahawk::Query::get( artist, track, QString() );
if ( qry.isNull() )
continue;
}
else if ( m_queryType == Artist )
{

View File

@ -77,6 +77,9 @@ DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
e->setResultHint( query.value( 8 ).toString() );
Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() );
if ( q.isNull() )
continue;
q->setResultHint( query.value( 8 ).toString() );
q->setProperty( "annotation", e->annotation() );
e->setQuery( q );

View File

@ -199,7 +199,8 @@ GroovesharkParser::trackPageFetchFinished()
tDebug() << "Got track info from grooveshark, enough to create a query:" << title.toPlainText() << artist.toPlainText() << album.toPlainText();
Tomahawk::query_ptr q = Tomahawk::Query::get( artist.toPlainText(), title.toPlainText(), album.toPlainText(), uuid(), true );
m_tracks << q;
if ( !q.isNull() )
m_tracks << q;
}
checkTrackFinished();

View File

@ -37,18 +37,18 @@ using namespace Tomahawk;
QPixmap* ItunesParser::s_pixmap = 0;
ItunesParser::ItunesParser( const QStringList& urls, QObject* parent )
: QObject ( parent )
, m_single( false )
{
foreach ( const QString& url, urls )
{
lookupItunesUri( url );
}
}
ItunesParser::ItunesParser( const QString& Url, QObject* parent )
: QObject ( parent )
, m_single( true )
@ -56,11 +56,12 @@ ItunesParser::ItunesParser( const QString& Url, QObject* parent )
lookupItunesUri( Url );
}
ItunesParser::~ItunesParser()
{
}
void
ItunesParser::lookupItunesUri( const QString& link )
{
@ -89,17 +90,17 @@ ItunesParser::lookupItunesUri( const QString& link )
}
else
return;
}
tLog() << "Parsing itunes track:" << link;
QUrl url;
DropJob::DropType type;
if( link.contains( "artist" ) )
if ( link.contains( "artist" ) )
{
type = DropJob::Artist;
url = QUrl( QString( "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/wsLookup?id=%1&entity=song&limit=30" ).arg( id ) );
}else
}
else
{
type = ( trackId.isEmpty() ? DropJob::Album : DropJob::Track );
url = QUrl( QString( "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/wsLookup?id=%1&entity=song" ).arg( ( trackId.isEmpty() ? id : trackId ) ) );
@ -113,8 +114,9 @@ ItunesParser::lookupItunesUri( const QString& link )
JobStatusView::instance()->model()->addJob( j );
m_queries.insert( reply );
}
void
ItunesParser::itunesResponseLookupFinished()
{
@ -134,7 +136,8 @@ ItunesParser::itunesResponseLookupFinished()
tLog() << "Failed to parse json from Spotify track lookup:" << p.errorString() << "On line" << p.errorLine();
checkTrackFinished();
return;
} else if ( !res.contains( "results" ) )
}
else if ( !res.contains( "results" ) )
{
tLog() << "No 'results' item in the itunes track lookup result... not doing anything";
checkTrackFinished();
@ -149,23 +152,25 @@ ItunesParser::itunesResponseLookupFinished()
if ( ituneMap.value( "wrapperType" ).toString().contains( "track" ) )
{
title = ituneMap.value( "trackName" ).toString();
artist = ituneMap.value( "artistName" ).toString();
album = ituneMap.value( "collectionName" ).toString();
if ( title.isEmpty() && artist.isEmpty() ) // don't have enough...
{
tLog() << "Didn't get an artist and track name from itunes, not enough to build a query on. Aborting" << title << artist << album;
}else{
}
else
{
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), true );
if ( q.isNull() )
continue;
m_tracks << q;
}
}
}
} else
}
else
{
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Error fetching iTunes information from the network!" ) ) );
tLog() << "Error in network request to Itunes for track decoding:" << r->errorString();
@ -187,9 +192,9 @@ ItunesParser::checkTrackFinished()
deleteLater();
}
}
QPixmap
ItunesParser::pixmap() const
{

View File

@ -34,16 +34,20 @@
using namespace Tomahawk;
JSPFLoader::JSPFLoader( bool autoCreate, QObject *parent )
JSPFLoader::JSPFLoader( bool autoCreate, QObject* parent )
: QObject( parent )
, m_autoCreate( autoCreate )
, m_autoDelete( true )
{}
{
}
JSPFLoader::~JSPFLoader()
{
}
QList< Tomahawk::query_ptr >
JSPFLoader::entries() const
{
@ -159,9 +163,9 @@ JSPFLoader::gotBody()
if ( tM.value( "location" ).toList().size() > 0 )
url = tM.value( "location" ).toList().first().toString();
if( artist.isEmpty() || track.isEmpty() )
if ( artist.isEmpty() || track.isEmpty() )
{
if( !shownError )
if ( !shownError )
{
QMessageBox::warning( 0, tr( "Failed to save tracks" ), tr( "Some tracks in the playlist do not contain an artist and a title. They will be ignored." ), QMessageBox::Ok );
shownError = true;
@ -170,6 +174,9 @@ JSPFLoader::gotBody()
}
query_ptr q = Tomahawk::Query::get( artist, track, album, uuid() );
if ( q.isNull() )
continue;
q->setDuration( duration.toInt() / 1000 );
if( !url.isEmpty() )
q->setResultHint( url );
@ -201,7 +208,6 @@ JSPFLoader::gotBody()
m_creator,
false,
m_entries );
}
emit ok( m_playlist );

View File

@ -91,7 +91,8 @@ M3uLoader::getTags( const QFileInfo& info )
{
qDebug() << Q_FUNC_INFO << artist << track << album;
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, track, album, uuid(), !m_createNewPlaylist );
m_tracks << q;
if ( !q.isNull() )
m_tracks << q;
}
}

View File

@ -48,6 +48,7 @@ QPixmap* RdioParser::s_pixmap = 0;
QCA::Initializer RdioParser::m_qcaInit = QCA::Initializer();
#endif
RdioParser::RdioParser( QObject* parent )
: QObject( parent )
, m_count( 0 )
@ -56,10 +57,12 @@ RdioParser::RdioParser( QObject* parent )
{
}
RdioParser::~RdioParser()
{
}
void
RdioParser::parse( const QString& url )
{
@ -68,6 +71,7 @@ RdioParser::parse( const QString& url )
parseUrl( url );
}
void
RdioParser::parse( const QStringList& urls )
{
@ -109,9 +113,9 @@ RdioParser::parseUrl( const QString& url )
// artist, album, or playlist link requre fetching
fetchObjectsFromUrl( url, type );
}
}
void
RdioParser::fetchObjectsFromUrl( const QString& url, DropJob::DropType type )
{
@ -134,10 +138,10 @@ RdioParser::fetchObjectsFromUrl( const QString& url, DropJob::DropType type )
m_reqQueries.insert( reply );
}
void
RdioParser::rdioReturned()
{
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r );
m_reqQueries.remove( r );
@ -185,21 +189,22 @@ RdioParser::rdioReturned()
}
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), !m_createPlaylist );
if ( q.isNull() )
continue;
m_tracks << q;
}
} else
}
else
{
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Error fetching Rdio information from the network!" ) ) );
tLog() << "Error in network request to Rdio for track decoding:" << r->errorString();
}
checkFinished();
}
void
RdioParser::parseTrack( const QString& origUrl )
{
@ -313,6 +318,7 @@ RdioParser::hmacSha1(QByteArray key, QByteArray baseString)
#endif
}
void
RdioParser::checkFinished()
{
@ -325,7 +331,7 @@ RdioParser::checkFinished()
if ( m_tracks.isEmpty() )
return;
if( m_createPlaylist )
if ( m_createPlaylist )
{
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
uuid(),
@ -353,6 +359,7 @@ RdioParser::checkFinished()
}
}
void
RdioParser::playlistCreated( Tomahawk::PlaylistRevision )
{
@ -370,6 +377,7 @@ RdioParser::expandedLinks( const QStringList& urls )
}
}
QPixmap
RdioParser::pixmap() const
{
@ -378,4 +386,3 @@ RdioParser::pixmap() const
return *s_pixmap;
}

View File

@ -39,6 +39,7 @@ using namespace Tomahawk;
QPixmap* SpotifyParser::s_pixmap = 0;
SpotifyParser::SpotifyParser( const QStringList& Urls, bool createNewPlaylist, QObject* parent )
: QObject ( parent )
, m_limit ( 40 )
@ -52,6 +53,7 @@ SpotifyParser::SpotifyParser( const QStringList& Urls, bool createNewPlaylist, Q
lookupUrl( url );
}
SpotifyParser::SpotifyParser( const QString& Url, bool createNewPlaylist, QObject* parent )
: QObject ( parent )
, m_limit ( 40 )
@ -63,6 +65,7 @@ SpotifyParser::SpotifyParser( const QString& Url, bool createNewPlaylist, QObjec
lookupUrl( Url );
}
SpotifyParser::~SpotifyParser()
{
}
@ -71,12 +74,12 @@ SpotifyParser::~SpotifyParser()
void
SpotifyParser::lookupUrl( const QString& link )
{
if( link.contains( "track" ) )
if ( link.contains( "track" ) )
{
m_trackMode = true;
lookupTrack( link );
}
else if( link.contains( "playlist" ) || link.contains( "album" ) || link.contains( "artist" ) )
else if ( link.contains( "playlist" ) || link.contains( "album" ) || link.contains( "artist" ) )
{
if( !m_createNewPlaylist )
m_trackMode = true;
@ -87,7 +90,6 @@ SpotifyParser::lookupUrl( const QString& link )
}
else
return; // Not valid spotify item
}
@ -103,7 +105,6 @@ SpotifyParser::lookupSpotifyBrowse( const QString& linkRaw )
browseUri = "spotify:" + browseUri;
}
DropJob::DropType type;
if ( browseUri.contains( "spotify:user" ) )
@ -133,6 +134,7 @@ SpotifyParser::lookupSpotifyBrowse( const QString& linkRaw )
m_queries.insert( reply );
}
void
SpotifyParser::lookupTrack( const QString& link )
{
@ -159,7 +161,6 @@ SpotifyParser::lookupTrack( const QString& link )
JobStatusView::instance()->model()->addJob( j );
m_queries.insert( reply );
}
@ -186,8 +187,6 @@ SpotifyParser::spotifyBrowseFinished()
}
QVariantMap resultResponse = res.value( res.value( "type" ).toString() ).toMap();
if ( !resultResponse.isEmpty() )
{
m_title = resultResponse.value( "name" ).toString();
@ -214,12 +213,14 @@ SpotifyParser::spotifyBrowseFinished()
}
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), m_trackMode );
if ( q.isNull() )
continue;
m_tracks << q;
}
}
} else
}
else
{
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Error fetching Spotify information from the network!" ) ) );
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
@ -232,7 +233,6 @@ SpotifyParser::spotifyBrowseFinished()
}
void
SpotifyParser::spotifyTrackLookupFinished()
{
@ -252,7 +252,8 @@ SpotifyParser::spotifyTrackLookupFinished()
tLog() << "Failed to parse json from Spotify track lookup:" << p.errorString() << "On line" << p.errorLine();
checkTrackFinished();
return;
} else if ( !res.contains( "track" ) )
}
else if ( !res.contains( "track" ) )
{
tLog() << "No 'track' item in the spotify track lookup result... not doing anything";
checkTrackFinished();
@ -261,7 +262,6 @@ SpotifyParser::spotifyTrackLookupFinished()
// lets parse this baby
QVariantMap t = res.value( "track" ).toMap();
QString title, artist, album;
title = t.value( "name", QString() ).toString();
@ -278,8 +278,10 @@ SpotifyParser::spotifyTrackLookupFinished()
}
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), m_trackMode );
m_tracks << q;
} else
if ( !q.isNull() )
m_tracks << q;
}
else
{
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
}
@ -288,9 +290,9 @@ SpotifyParser::spotifyTrackLookupFinished()
checkTrackFinished();
else
checkBrowseFinished();
}
void
SpotifyParser::checkBrowseFinished()
{
@ -300,7 +302,7 @@ SpotifyParser::checkBrowseFinished()
if ( m_browseJob )
m_browseJob->setFinished();
if( m_createNewPlaylist && !m_tracks.isEmpty() )
if ( m_createNewPlaylist && !m_tracks.isEmpty() )
{
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
uuid(),
@ -322,6 +324,7 @@ SpotifyParser::checkBrowseFinished()
}
}
void
SpotifyParser::checkTrackFinished()
{
@ -338,13 +341,12 @@ SpotifyParser::checkTrackFinished()
deleteLater();
}
}
void
SpotifyParser::playlistCreated()
{
ViewManager::instance()->show( m_playlist );
deleteLater();

View File

@ -40,6 +40,7 @@
using namespace Tomahawk;
QString
XSPFLoader::errorToString( XSPFErrorCode error )
{
@ -56,7 +57,8 @@ XSPFLoader::errorToString( XSPFErrorCode error )
}
}
XSPFLoader::XSPFLoader( bool autoCreate, bool autoUpdate, QObject *parent )
XSPFLoader::XSPFLoader( bool autoCreate, bool autoUpdate, QObject* parent )
: QObject( parent )
, m_autoCreate( autoCreate )
, m_autoUpdate( autoUpdate )
@ -69,7 +71,8 @@ XSPFLoader::XSPFLoader( bool autoCreate, bool autoUpdate, QObject *parent )
XSPFLoader::~XSPFLoader()
{}
{
}
void
@ -235,6 +238,9 @@ XSPFLoader::gotBody()
}
query_ptr q = Tomahawk::Query::get( artist, track, album, uuid(), false );
if ( q.isNull() )
continue;
q->setDuration( duration.toInt() / 1000 );
if ( !url.isEmpty() )
q->setResultHint( url );
@ -279,5 +285,4 @@ XSPFLoader::gotBody()
if ( m_autoDelete )
deleteLater();
}

View File

@ -27,47 +27,52 @@ ChartDataLoader::ChartDataLoader()
{
}
void
ChartDataLoader::go()
{
switch ( m_type )
{
case Track:
{
QList< query_ptr > track_ptrs;
foreach ( const Tomahawk::InfoSystem::InfoStringHash& track, m_data )
case Track:
{
track_ptrs << Query::get( track[ "artist" ], track[ "track" ], QString(), uuid(), false );
QList< query_ptr > track_ptrs;
foreach ( const Tomahawk::InfoSystem::InfoStringHash& track, m_data )
{
query_ptr q = Query::get( track[ "artist" ], track[ "track" ], QString(), uuid(), false );
if ( q.isNull() )
continue;
track_ptrs << q;
}
emit tracks( this, track_ptrs );
break;
}
emit tracks( this, track_ptrs );
break;
}
case Artist:
{
QList< artist_ptr > artist_ptrs;
foreach ( const QString& artistname, m_artists )
case Artist:
{
artist_ptrs << Artist::get( artistname, false );
QList< artist_ptr > artist_ptrs;
foreach ( const QString& artistname, m_artists )
{
artist_ptrs << Artist::get( artistname, false );
}
emit artists( this, artist_ptrs );
break;
}
emit artists( this, artist_ptrs );
break;
}
case Album:
{
QList< album_ptr > album_ptrs;
foreach ( const Tomahawk::InfoSystem::InfoStringHash& album, m_data )
case Album:
{
artist_ptr artistPtr = Artist::get( album[ "artist" ], false );
album_ptr albumPtr = Album::get( artistPtr, album[ "album" ], false );
album_ptrs << albumPtr;
}
QList< album_ptr > album_ptrs;
emit albums( this, album_ptrs );
break;
}
foreach ( const Tomahawk::InfoSystem::InfoStringHash& album, m_data )
{
artist_ptr artistPtr = Artist::get( album[ "artist" ], false );
album_ptr albumPtr = Album::get( artistPtr, album[ "album" ], false );
album_ptrs << albumPtr;
}
emit albums( this, album_ptrs );
break;
}
}
}

View File

@ -253,8 +253,7 @@ Api_v1::resolve( QxtWebRequestEvent* event )
!event->url.hasQueryItem( "track" ) )
{
qDebug() << "Malformed HTTP resolve request";
send404( event );
return;
return send404( event );
}
const QString artist = QUrl::fromPercentEncoding( event->url.queryItemValue( "artist" ).toUtf8() );
@ -265,8 +264,7 @@ Api_v1::resolve( QxtWebRequestEvent* event )
track.trimmed().isEmpty() )
{
qDebug() << "Malformed HTTP resolve request";
send404( event );
return;
return send404( event );
}
QString qid;
@ -276,6 +274,11 @@ Api_v1::resolve( QxtWebRequestEvent* event )
qid = uuid();
query_ptr qry = Query::get( artist, track, album, qid, false );
if ( qry.isNull() )
{
return send404( event );
}
Pipeline::instance()->resolve( qry, true, true );
QVariantMap r;

View File

@ -150,7 +150,7 @@ void XMPPBot::handleSubscription(const gloox::Subscription& subscription)
void XMPPBot::handleMessage(const Message& msg, MessageSession* session)
{
//TODO: implement "properly" with MessageSessions, if the bot is to be multi-user
if (msg.subtype() != Message::Chat || msg.from().full().empty() || msg.to().full().empty())
if ( msg.subtype() != Message::Chat || msg.from().full().empty() || msg.to().full().empty() )
return;
QString body = QString::fromStdString( msg.body() ).toLower().trimmed();
@ -163,6 +163,9 @@ void XMPPBot::handleMessage(const Message& msg, MessageSession* session)
AudioEngine::instance()->play();
Tomahawk::query_ptr q = Tomahawk::Query::get( tokens.first().trimmed(), tokens.last().trimmed(), QString() );
if ( q.isNull() )
return;
connect( q.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ),
SLOT( onResultsAdded( QList<Tomahawk::result_ptr> ) ) );