void DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi ) { TomahawkSqlQuery query = dbi->newquery(); QString whereToken( "WHERE 1" ); if ( !source().isNull() ) { whereToken += QString( " AND source %1" ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ); } if ( m_dateFrom.year() > 1900 && m_dateTo.year() > 1900 ) { whereToken += QString( " AND playtime >= %1 AND playtime <= %2" ) .arg( QDateTime( m_dateFrom ).toUTC().toTime_t() ) .arg( QDateTime( m_dateTo.addDays( 1 ) ).toUTC().toTime_t() ); } QString sql = QString( "SELECT track, playtime, secs_played, source " "FROM playback_log " "%1 " "ORDER BY playtime DESC " "%2" ).arg( whereToken ) .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() ); query.prepare( sql ); query.exec(); QList<Tomahawk::track_ptr> tl; QList<Tomahawk::PlaybackLog> logs; while ( query.next() ) { TomahawkSqlQuery query_track = dbi->newquery(); QString sql = QString( "SELECT track.name, artist.name " "FROM track, artist " "WHERE artist.id = track.artist " "AND track.id = %1" ).arg( query.value( 0 ).toUInt() ); query_track.prepare( sql ); query_track.exec(); if ( query_track.next() ) { Tomahawk::track_ptr track = Tomahawk::Track::get( query_track.value( 1 ).toString(), query_track.value( 0 ).toString(), QString() ); if ( !track ) continue; Tomahawk::PlaybackLog log; log.timestamp = query.value( 1 ).toUInt(); log.secsPlayed = query.value( 2 ).toUInt(); log.source = SourceList::instance()->get( query.value( 3 ).toUInt() ); logs << log; tl << track; } } emit tracks( tl, logs ); }
void DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi ) { TomahawkSqlQuery query_entries = dbi->newquery(); query_entries.prepare( "SELECT entries, playlist, author, timestamp, previous_revision " "FROM playlist_revision " "WHERE guid = :guid" ); query_entries.bindValue( ":guid", m_revguid ); query_entries.exec(); tLog( LOGVERBOSE ) << "trying to load playlist entries for guid:" << m_revguid; QString prevrev; bool ok; if ( query_entries.next() ) { if ( !query_entries.value( 0 ).isNull() ) { // entries should be a list of strings: QVariant v = TomahawkUtils::parseJson( query_entries.value( 0 ).toByteArray(), &ok ); Q_ASSERT( ok && v.type() == QVariant::List ); //TODO m_guids = v.toStringList(); QString inclause = QString( "('%1')" ).arg( m_guids.join( "', '" ) ); TomahawkSqlQuery query = dbi->newquery(); QString sql = QString( "SELECT guid, trackname, artistname, albumname, annotation, " "duration, addedon, addedby, result_hint " "FROM playlist_item " "WHERE guid IN %1" ).arg( inclause ); query.exec( sql ); while ( query.next() ) { plentry_ptr e( new PlaylistEntry ); e->setGuid( query.value( 0 ).toString() ); e->setAnnotation( query.value( 4 ).toString() ); e->setDuration( query.value( 5 ).toUInt() ); e->setLastmodified( 0 ); // TODO e->lastmodified = query.value( 6 ).toInt(); const QString resultHint = query.value( 8 ).toString(); e->setResultHint( resultHint ); 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( resultHint ); if ( resultHint.startsWith( "http" ) ) q->setSaveHTTPResultHint( true ); q->setProperty( "annotation", e->annotation() ); e->setQuery( q ); m_entrymap.insert( e->guid(), e ); } } prevrev = query_entries.value( 4 ).toString(); } else { // qDebug() << "Playlist has no current revision data"; } if ( prevrev.length() ) { TomahawkSqlQuery query_entries_old = dbi->newquery(); query_entries_old.prepare( "SELECT entries, " "(SELECT currentrevision = ? FROM playlist WHERE guid = ?) " "FROM playlist_revision " "WHERE guid = ?" ); query_entries_old.addBindValue( m_revguid ); query_entries_old.addBindValue( query_entries.value( 1 ).toString() ); query_entries_old.addBindValue( prevrev ); query_entries_old.exec(); if ( !query_entries_old.next() ) { return; Q_ASSERT( false ); } if ( !query_entries_old.value( 0 ).isNull() ) { QVariant v = TomahawkUtils::parseJson( query_entries_old.value( 0 ).toByteArray(), &ok ); Q_ASSERT( ok && v.type() == QVariant::List ); //TODO m_oldentries = v.toStringList(); } m_islatest = query_entries_old.value( 1 ).toBool(); } // qDebug() << Q_FUNC_INFO << "entrymap:" << m_entrymap; }
void DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi ) { TomahawkSqlQuery query = dbi->newquery(); QList<Tomahawk::query_ptr> ql; QString m_orderToken, sourceToken; switch ( m_sortOrder ) { case 0: break; case Album: m_orderToken = "album.name, file_join.albumpos"; break; case ModificationTime: m_orderToken = "file.mtime"; break; case AlbumPosition: m_orderToken = "file_join.albumpos"; break; } if ( !m_collection.isNull() ) sourceToken = QString( "AND file.source %1" ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) ); QString albumToken; if ( m_album ) { if ( m_album->id() == 0 ) { m_artist = m_album->artist().data(); albumToken = QString( "AND album.id IS NULL" ); } else albumToken = QString( "AND album.id = %1" ).arg( m_album->id() ); } QString sql = QString( "SELECT file.id, artist.name, album.name, track.name, file.size, " "file.duration, file.bitrate, file.url, file.source, file.mtime, file.mimetype, file_join.albumpos, artist.id, album.id, track.id " "FROM file, artist, track, file_join " "LEFT OUTER JOIN album " "ON file_join.album = album.id " "WHERE file.id = file_join.file " "AND file_join.artist = artist.id " "AND file_join.track = track.id " "%1 " "%2 %3 " "%4 %5 %6" ).arg( sourceToken ) .arg( !m_artist ? QString() : QString( "AND artist.id = %1" ).arg( m_artist->id() ) ) .arg( !m_album ? QString() : albumToken ) .arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( m_orderToken ) : QString() ) .arg( m_sortDescending ? "DESC" : QString() ) .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() ); query.prepare( sql ); query.exec(); while( query.next() ) { Tomahawk::result_ptr result = Tomahawk::result_ptr( new Tomahawk::Result() ); Tomahawk::source_ptr s; if( query.value( 8 ).toUInt() == 0 ) { s = SourceList::instance()->getLocal(); result->setUrl( query.value( 7 ).toString() ); } else { s = SourceList::instance()->get( query.value( 8 ).toUInt() ); if( s.isNull() ) { Q_ASSERT( false ); continue; } result->setUrl( QString( "servent://%1\t%2" ).arg( s->userName() ).arg( query.value( 7 ).toString() ) ); } QString artist, track, album; artist = query.value( 1 ).toString(); album = query.value( 2 ).toString(); track = query.value( 3 ).toString(); Tomahawk::query_ptr qry = Tomahawk::Query::get( artist, track, album ); Tomahawk::artist_ptr artistptr = Tomahawk::Artist::get( query.value( 12 ).toUInt(), artist ); Tomahawk::album_ptr albumptr = Tomahawk::Album::get( query.value( 13 ).toUInt(), album, artistptr ); result->setId( query.value( 14 ).toUInt() ); result->setArtist( artistptr ); result->setAlbum( albumptr ); result->setTrack( query.value( 3 ).toString() ); result->setSize( query.value( 4 ).toUInt() ); result->setDuration( query.value( 5 ).toUInt() ); result->setBitrate( query.value( 6 ).toUInt() ); result->setModificationTime( query.value( 9 ).toUInt() ); result->setMimetype( query.value( 10 ).toString() ); result->setAlbumPos( query.value( 11 ).toUInt() ); result->setScore( 1.0 ); result->setCollection( s->collection() ); TomahawkSqlQuery attrQuery = dbi->newquery(); QVariantMap attr; attrQuery.prepare( "SELECT k, v FROM track_attributes WHERE id = ?" ); attrQuery.bindValue( 0, result->dbid() ); attrQuery.exec(); while ( attrQuery.next() ) { attr[ attrQuery.value( 0 ).toString() ] = attrQuery.value( 1 ).toString(); } result->setAttributes( attr ); QList<Tomahawk::result_ptr> results; results << result; qry->addResults( results ); qry->setResolveFinished( true ); ql << qry; } qDebug() << Q_FUNC_INFO << ql.length(); emit tracks( ql, data() ); emit done( m_collection ); }
void DatabaseCommand_Resolve::resolve( DatabaseImpl* lib ) { QList<Tomahawk::result_ptr> res; // STEP 1 QList< QPair<int, float> > tracks = lib->search( m_query ); if ( tracks.length() == 0 ) { qDebug() << "No candidates found in first pass, aborting resolve" << m_query->artist() << m_query->track(); emit results( m_query->id(), res ); return; } // STEP 2 TomahawkSqlQuery files_query = lib->newquery(); QStringList trksl; for ( int k = 0; k < tracks.count(); k++ ) trksl.append( QString::number( tracks.at( k ).first ) ); QString trksToken = QString( "file_join.track IN (%1)" ).arg( trksl.join( "," ) ); QString sql = QString( "SELECT " "url, mtime, size, md5, mimetype, duration, bitrate, " //0 "file_join.artist, file_join.album, file_join.track, " //7 "file_join.composer, file_join.discnumber, " //10 "artist.name as artname, " //12 "album.name as albname, " //13 "track.name as trkname, " //14 "composer.name as cmpname, " //15 "file.source, " //16 "file_join.albumpos, " //17 "artist.id as artid, " //18 "album.id as albid, " //19 "composer.id as cmpid " //20 "FROM file, file_join, artist, track " "LEFT JOIN album ON album.id = file_join.album " "LEFT JOIN artist AS composer ON composer.id = file_join.composer " "WHERE " "artist.id = file_join.artist AND " "track.id = file_join.track AND " "file.id = file_join.file AND " "(%1)" ) .arg( trksToken ); files_query.prepare( sql ); files_query.exec(); while ( files_query.next() ) { source_ptr s; QString url = files_query.value( 0 ).toString(); if ( files_query.value( 16 ).toUInt() == 0 ) { s = SourceList::instance()->getLocal(); } else { s = SourceList::instance()->get( files_query.value( 16 ).toUInt() ); if ( s.isNull() ) { qDebug() << "Could not find source" << files_query.value( 16 ).toUInt(); continue; } url = QString( "servent://%1\t%2" ).arg( s->nodeId() ).arg( url ); } bool cached = Tomahawk::Result::isCached( url ); Tomahawk::result_ptr result = Tomahawk::Result::get( url ); if ( cached ) { qDebug() << "Result already cached:" << result->toString(); res << result; continue; } Tomahawk::artist_ptr artist = Tomahawk::Artist::get( files_query.value( 18 ).toUInt(), files_query.value( 12 ).toString() ); Tomahawk::album_ptr album = Tomahawk::Album::get( files_query.value( 19 ).toUInt(), files_query.value( 13 ).toString(), artist ); Tomahawk::artist_ptr composer = Tomahawk::Artist::get( files_query.value( 20 ).toUInt(), files_query.value( 15 ).toString() ); result->setModificationTime( files_query.value( 1 ).toUInt() ); result->setSize( files_query.value( 2 ).toUInt() ); result->setMimetype( files_query.value( 4 ).toString() ); result->setDuration( files_query.value( 5 ).toUInt() ); result->setBitrate( files_query.value( 6 ).toUInt() ); result->setArtist( artist ); result->setComposer( composer ); result->setAlbum( album ); result->setDiscNumber( files_query.value( 11 ).toUInt() ); result->setTrack( files_query.value( 14 ).toString() ); result->setRID( uuid() ); result->setAlbumPos( files_query.value( 17 ).toUInt() ); result->setTrackId( files_query.value( 9 ).toUInt() ); TomahawkSqlQuery attrQuery = lib->newquery(); QVariantMap attr; attrQuery.prepare( "SELECT k, v FROM track_attributes WHERE id = ?" ); attrQuery.bindValue( 0, result->trackId() ); attrQuery.exec(); while ( attrQuery.next() ) { attr[ attrQuery.value( 0 ).toString() ] = attrQuery.value( 1 ).toString(); } result->setAttributes( attr ); result->setCollection( s->dbCollection() ); res << result; } emit results( m_query->id(), res ); }
void DatabaseCommand_LoadAllSortedPlaylists::exec( DatabaseImpl* dbi ) { TomahawkSqlQuery query = dbi->newquery(); QString orderToken, sourceToken, ascDescToken; switch ( m_sortOrder ) { case 0: break; case DatabaseCommand_LoadAllPlaylists::ModificationTime: orderToken = "playlist.createdOn"; } switch ( m_sortAscDesc ) { case DatabaseCommand_LoadAllPlaylists::NoOrder: break; case DatabaseCommand_LoadAllPlaylists::Ascending: ascDescToken = "ASC"; break; case DatabaseCommand_LoadAllPlaylists::Descending: ascDescToken = "DESC"; break; } if ( !source().isNull() ) sourceToken = QString( "AND source %1 " ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ); query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, lastmodified, shared, currentrevision, createdOn, dynplaylist, source, dynamic_playlist.pltype, dynamic_playlist.plmode " "FROM playlist " "LEFT JOIN dynamic_playlist ON playlist.guid = dynamic_playlist.guid " "%1 " "%2 %3 %4" ) .arg( sourceToken ) .arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() ) .arg( ascDescToken ) .arg( m_limitAmount > 0 ? QString( "LIMIT 0, %1" ).arg( m_limitAmount ) : QString() ) ); QList<SourcePlaylistPair> plists; while ( query.next() ) { plists << QPair< int, QString >( query.value(9).toInt(), query.value(0).toString() ); // playlist_ptr p; // bool dynamic = query.value(8).toBool(); // source_ptr s = SourceList::instance()->get( query.value(9).toInt() ); // // if ( dynamic ) // { // p = dynplaylist_ptr( new DynamicPlaylist( s, // query.value(6).toString(), //current rev // query.value(1).toString(), //title // query.value(2).toString(), //info // query.value(3).toString(), //creator // query.value(7).toInt(), //createdOn // query.value(10).toString(), //type // (GeneratorMode)query.value(11).toInt(), // mode // query.value(5).toBool(), //shared // query.value(4).toInt(), //lastmod // query.value(0).toString() //GUID // ) ); // } else // { // p = playlist_ptr( new Playlist( s, //src // query.value(6).toString(), //current rev // query.value(1).toString(), //title // query.value(2).toString(), //info // query.value(3).toString(), //creator // query.value(7).toInt(), //createdOn // query.value(5).toBool(), //shared // query.value(4).toInt(), //lastmod // query.value(0).toString() //GUID // ) ); // } // plists.append( p ); } emit done( plists ); }
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent ) : QObject( (QObject*) parent ) , m_lastartid( 0 ) , m_lastalbid( 0 ) , m_lasttrkid( 0 ) { db = QSqlDatabase::addDatabase( "QSQLITE", "tomahawk" ); db.setDatabaseName( dbname ); if ( !db.open() ) { qDebug() << "FAILED TO OPEN DB"; throw "failed to open db"; // TODO } QSqlQuery qry = QSqlQuery( db ); bool schemaUpdated = false; qry.exec( "SELECT v FROM settings WHERE k='schema_version'" ); if ( qry.next() ) { int v = qry.value( 0 ).toInt(); qDebug() << "Current schema is" << v << this->thread(); if ( v != CURRENT_SCHEMA_VERSION ) { QString newname = QString("%1.v%2").arg(dbname).arg(v); qDebug() << endl << "****************************" << endl; qDebug() << "Schema version too old: " << v << ". Current version is:" << CURRENT_SCHEMA_VERSION; qDebug() << "Moving" << dbname << newname; qDebug() << endl << "****************************" << endl; qry.clear(); qry.finish(); db.close(); db.removeDatabase( "tomahawk" ); if( QFile::rename( dbname, newname ) ) { db = QSqlDatabase::addDatabase( "QSQLITE", "tomahawk" ); db.setDatabaseName( dbname ); if( !db.open() ) throw "db moving failed"; TomahawkSqlQuery query = newquery(); query.exec( "PRAGMA auto_vacuum = FULL" ); schemaUpdated = updateSchema( v ); } else { Q_ASSERT( false ); QTimer::singleShot( 0, qApp, SLOT( quit() ) ); return; } } } else { schemaUpdated = updateSchema( 0 ); } TomahawkSqlQuery query = newquery(); query.exec( "SELECT v FROM settings WHERE k='dbid'" ); if( query.next() ) { m_dbid = query.value( 0 ).toString(); } else { m_dbid = uuid(); query.exec( QString( "INSERT INTO settings(k,v) VALUES('dbid','%1')" ).arg( m_dbid ) ); } qDebug() << "Database ID:" << m_dbid; // make sqlite behave how we want: query.exec( "PRAGMA synchronous = ON" ); query.exec( "PRAGMA foreign_keys = ON" ); //query.exec( "PRAGMA temp_store = MEMORY" ); // in case of unclean shutdown last time: query.exec( "UPDATE source SET isonline = 'false'" ); m_fuzzyIndex = new FuzzyIndex( *this, schemaUpdated ); }
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent ) : QObject( (QObject*) parent ) , m_lastartid( 0 ) , m_lastalbid( 0 ) , m_lasttrkid( 0 ) { bool schemaUpdated = false; int version = getDatabaseVersion( dbname ); if ( version > 0 && version != CURRENT_SCHEMA_VERSION ) { QString newname = QString( "%1.v%2" ).arg( dbname ).arg( version ); tLog() << endl << "****************************" << endl; tLog() << "Schema version too old: " << version << ". Current version is:" << CURRENT_SCHEMA_VERSION; tLog() << "Moving" << dbname << newname; tLog() << "If the migration fails, you can recover your DB by copying" << newname << "back to" << dbname; tLog() << endl << "****************************" << endl; QFile::copy( dbname, newname ); { db = QSqlDatabase::addDatabase( "QSQLITE", "tomahawk" ); db.setDatabaseName( dbname ); if( !db.open() ) throw "db moving failed"; TomahawkSqlQuery query = newquery(); query.exec( "PRAGMA auto_vacuum = FULL" ); schemaUpdated = updateSchema( version ); if ( !schemaUpdated ) { Q_ASSERT( false ); QTimer::singleShot( 0, qApp, SLOT( quit() ) ); } } } else { db = QSqlDatabase::addDatabase( "QSQLITE", "tomahawk" ); db.setDatabaseName( dbname ); if ( !db.open() ) { tLog() << "Failed to open database" << dbname; throw "failed to open db"; // TODO } if ( version < 0 ) schemaUpdated = updateSchema( 0 ); } TomahawkSqlQuery query = newquery(); query.exec( "SELECT v FROM settings WHERE k='dbid'" ); if( query.next() ) { m_dbid = query.value( 0 ).toString(); } else { m_dbid = uuid(); query.exec( QString( "INSERT INTO settings(k,v) VALUES('dbid','%1')" ).arg( m_dbid ) ); } tLog() << "Database ID:" << m_dbid; // make sqlite behave how we want: query.exec( "PRAGMA synchronous = ON" ); query.exec( "PRAGMA foreign_keys = ON" ); //query.exec( "PRAGMA temp_store = MEMORY" ); // in case of unclean shutdown last time: query.exec( "UPDATE source SET isonline = 'false'" ); m_fuzzyIndex = new FuzzyIndex( *this, schemaUpdated ); }
void Tomahawk::DatabaseCommand_LoadDynamicPlaylist::exec( DatabaseImpl* dbi ) { TomahawkSqlQuery query = dbi->newquery(); query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, createdOn, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode " "FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid AND playlist.guid = '%2'" ) .arg( source()->isLocal() ? "IS NULL" : QString( "=%1" ).arg( source()->id() ) ).arg( m_plid ) ); QList<dynplaylist_ptr> plists; if( query.next() ) { dynplaylist_ptr p( new DynamicPlaylist( source(), query.value(7).toString(), //current rev query.value(1).toString(), //title query.value(2).toString(), //info query.value(3).toString(), //creator query.value(4).toUInt(), //createdOn query.value(8).toString(), // dynamic type static_cast<GeneratorMode>(query.value(9).toInt()), // dynamic mode query.value(6).toBool(), //shared query.value(5).toInt(), //lastmod query.value(0).toString() ) ); //GUID tLog() << "Loaded individual dynamic playlist:" << query.value(7).toString() //current rev << query.value(1).toString() //title << query.value(2).toString() //info << query.value(3).toString() //creator << query.value(4).toString() //createdOn << query.value(8).toString() // dynamic type << static_cast<GeneratorMode>(query.value(9).toInt()) // dynamic mode << query.value(6).toBool() //shared << query.value(5).toInt() //lastmod << query.value(0).toString(); //GUID emit dynamicPlaylistLoaded( p ); } emit done(); }
void DatabaseCommand_LoadAllPlaylists::exec( DatabaseImpl* dbi ) { Q_D( DatabaseCommand_LoadAllPlaylists ); TomahawkSqlQuery query = dbi->newquery(); QString orderToken, sourceToken; switch ( d->sortOrder ) { case 0: break; case ModificationTime: orderToken = "ORDER BY playlist.createdOn"; } if ( !source().isNull() ) sourceToken = QString( "AND source %1 " ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ); QString trackIdJoin; QString trackIdFields; if ( d->returnPlEntryIds ) { trackIdFields = ", pr.entries"; trackIdJoin = "JOIN playlist_revision pr ON pr.playlist = p.guid AND pr.guid = p.currentrevision"; } query.exec( QString( " SELECT p.guid, p.title, p.info, p.creator, p.lastmodified, p.shared, p.currentrevision, p.createdOn %6 " " FROM playlist p " " %5 " " WHERE ( ( dynplaylist = 'false' ) OR ( dynplaylist = 0 ) ) " " %1 " " %2 %3 %4 " ) .arg( sourceToken ) .arg( orderToken ) .arg( d->sortDescending ? "DESC" : QString() ) .arg( d->limitAmount > 0 ? QString( "LIMIT 0, %1" ).arg( d->limitAmount ) : QString() ) .arg( trackIdJoin ) .arg( trackIdFields ) ); QList<playlist_ptr> plists; QHash<playlist_ptr, QStringList> phash; while ( query.next() ) { playlist_ptr p( new Playlist( source(), //src query.value(6).toString(), //current rev query.value(1).toString(), //title query.value(2).toString(), //info query.value(3).toString(), //creator query.value(7).toInt(), //lastmod / createdOn query.value(5).toBool(), //shared query.value(4).toInt(), //lastmod query.value(0).toString() //GUID ), &QObject::deleteLater ); p->setWeakSelf( p.toWeakRef() ); plists.append( p ); if ( d->returnPlEntryIds ) { QStringList trackIds = TomahawkUtils::parseJson( query.value( 8 ).toByteArray() ).toStringList(); phash.insert( p, trackIds ); } } emit done( plists ); if ( d->returnPlEntryIds ) { emit done( phash ); } }
void DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi ) { TomahawkSqlQuery query = dbi->newquery(); QList<Tomahawk::query_ptr> ql; QString m_orderToken, sourceToken; switch ( m_sortOrder ) { case 0: break; case Album: m_orderToken = "album.name, file_join.discnumber, file_join.albumpos"; break; case ModificationTime: m_orderToken = "file.mtime"; break; case AlbumPosition: m_orderToken = "file_join.discnumber, file_join.albumpos"; break; } if ( !m_collection.isNull() ) sourceToken = QString( "AND file.source %1" ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) ); QString albumToken; if ( m_album ) { if ( m_album->id() == 0 ) { m_artist = m_album->artist(); albumToken = QString( "AND album.id IS NULL" ); } else albumToken = QString( "AND album.id = %1" ).arg( m_album->id() ); } QString sql = QString( "SELECT file.id, artist.name, album.name, track.name, composer.name, file.size, " //0 "file.duration, file.bitrate, file.url, file.source, file.mtime, " //6 "file.mimetype, file_join.discnumber, file_join.albumpos, artist.id, " //11 "album.id, track.id, composer.id " //15 "FROM file, artist, track, file_join " "LEFT OUTER JOIN album " "ON file_join.album = album.id " "LEFT OUTER JOIN artist AS composer " "ON file_join.composer = composer.id " "WHERE file.id = file_join.file " "AND file_join.artist = artist.id " "AND file_join.track = track.id " "%1 " "%2 %3 " "%4 %5 %6" ).arg( sourceToken ) .arg( !m_artist ? QString() : QString( "AND artist.id = %1" ).arg( m_artist->id() ) ) .arg( !m_album ? QString() : albumToken ) .arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( m_orderToken ) : QString() ) .arg( m_sortDescending ? "DESC" : QString() ) .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() ); query.prepare( sql ); query.exec(); while( query.next() ) { QString url = query.value( 8 ).toString(); Tomahawk::source_ptr s = SourceList::instance()->get( query.value( 9 ).toUInt() ); if ( !s ) { Q_ASSERT( false ); continue; } if ( !s->isLocal() ) url = QString( "servent://%1\t%2" ).arg( s->nodeId() ).arg( url ); QString artist, track, album, composer; artist = query.value( 1 ).toString(); album = query.value( 2 ).toString(); track = query.value( 3 ).toString(); composer = query.value( 4 ).toString(); Tomahawk::result_ptr result = Tomahawk::Result::get( url ); Tomahawk::query_ptr qry = Tomahawk::Query::get( artist, track, album ); Tomahawk::track_ptr t = Tomahawk::Track::get( query.value( 16 ).toUInt(), artist, track, album, query.value( 6 ).toUInt(), composer, query.value( 13 ).toUInt(), query.value( 12 ).toUInt() ); t->loadAttributes(); result->setTrack( t ); result->setSize( query.value( 5 ).toUInt() ); result->setBitrate( query.value( 7 ).toUInt() ); result->setModificationTime( query.value( 10 ).toUInt() ); result->setMimetype( query.value( 11 ).toString() ); result->setScore( 1.0 ); result->setCollection( s->dbCollection() ); QList<Tomahawk::result_ptr> results; results << result; qry->addResults( results ); qry->setResolveFinished( true ); ql << qry; } emit tracks( ql, data() ); emit tracks( ql ); emit done( m_collection ); }