File indexing completed on 2024-05-19 04:50:11

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org>                                *
0003  * Copyright (c) 2007 Adam Pigg <adam@piggz.co.uk>                                      *
0004  * Copyright (c) 2007 Casey Link <unnamedrambler@gmail.com>                             *
0005  *           (c) 2013 Ralf Engels <ralf-engels@gmx.de>                                  *
0006  *                                                                                      *
0007  * This program is free software; you can redistribute it and/or modify it under        *
0008  * the terms of the GNU General Public License as published by the Free Software        *
0009  * Foundation; either version 2 of the License, or (at your option) any later           *
0010  * version.                                                                             *
0011  *                                                                                      *
0012  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0013  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0014  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0015  *                                                                                      *
0016  * You should have received a copy of the GNU General Public License along with         *
0017  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0018  ****************************************************************************************/
0019 
0020 #define DEBUG_PREFIX "AmpacheServiceQueryMaker"
0021 
0022 #include "AmpacheServiceQueryMaker.h"
0023 
0024 #include "AmpacheMeta.h"
0025 #include "core/meta/Statistics.h"
0026 #include "core/support/Amarok.h"
0027 #include "core/support/Debug.h"
0028 #include "core/meta/support/MetaConstants.h"
0029 #include "core-impl/collections/support/MemoryMatcher.h"
0030 
0031 #include <QAtomicInt>
0032 #include <QDomDocument>
0033 #include <QSet>
0034 #include <QUrlQuery>
0035 
0036 using namespace Collections;
0037 
0038 struct AmpacheServiceQueryMaker::Private
0039 {
0040     AmpacheServiceCollection* collection;
0041 
0042     QueryMaker::QueryType type;
0043     int maxsize;
0044 
0045     QAtomicInt expectedReplies;
0046 
0047     QUrl server;
0048     QString sessionId;
0049     QList<int> parentTrackIds;
0050     QList<int> parentAlbumIds;
0051     QList<int> parentArtistIds;
0052     uint dateFilter;
0053     QString artistFilter;
0054     QString albumFilter;
0055 
0056     /** We are collecting the results of the queries and submit them
0057         in one block to ensure that we don't report albums twice
0058         and because the CollectionTreeItemModelBase does not handle
0059         multiple results correctly (which it should).
0060     */
0061     Meta::AlbumList albumResults;
0062     Meta::ArtistList artistResults;
0063     Meta::TrackList trackResults;
0064 };
0065 
0066 AmpacheServiceQueryMaker::AmpacheServiceQueryMaker( AmpacheServiceCollection * collection, const QUrl &server, const QString &sessionId  )
0067     : DynamicServiceQueryMaker()
0068     , d( new Private )
0069 {
0070     d->collection = collection;
0071     d->type = QueryMaker::None;
0072     d->maxsize = 0;
0073     d->server = server;
0074     d->sessionId = sessionId;
0075     d->dateFilter = 0;
0076 }
0077 
0078 AmpacheServiceQueryMaker::~AmpacheServiceQueryMaker()
0079 {
0080     delete d;
0081 }
0082 
0083 void
0084 AmpacheServiceQueryMaker::run()
0085 {
0086     DEBUG_BLOCK
0087 
0088     if( d->expectedReplies ) // still running an old query
0089         return;
0090 
0091     //naive implementation, fix this
0092     //note: we are not handling filtering yet
0093 
0094     d->collection->acquireReadLock();
0095 
0096     if (  d->type == QueryMaker::Artist )
0097         fetchArtists();
0098     else if( d->type == QueryMaker::Album )
0099         fetchAlbums();
0100     else if( d->type == QueryMaker::Track )
0101         fetchTracks();
0102     else
0103         warning() << "Requested unhandled query type"; //TODO error handling
0104 
0105      d->collection->releaseLock();
0106 }
0107 
0108 void
0109 AmpacheServiceQueryMaker::abortQuery()
0110 {
0111 }
0112 
0113 QueryMaker *
0114 AmpacheServiceQueryMaker::setQueryType( QueryType type )
0115 {
0116     d->type = type;
0117 
0118     return this;
0119 }
0120 
0121 QueryMaker*
0122 AmpacheServiceQueryMaker::addMatch( const Meta::TrackPtr &track )
0123 {
0124     DEBUG_BLOCK
0125 
0126     const Meta::AmpacheTrack* serviceTrack = dynamic_cast< const Meta::AmpacheTrack * >( track.data() );
0127     if( serviceTrack )
0128     {
0129         d->parentTrackIds << serviceTrack->id();
0130         debug() << "parent id set to: " << d->parentTrackIds;
0131     }
0132     else
0133     {
0134         // searching for something from another collection
0135         //hmm, not sure what to do now
0136     }
0137 
0138     return this;
0139 }
0140 
0141 QueryMaker*
0142 AmpacheServiceQueryMaker::addMatch( const Meta::ArtistPtr &artist, ArtistMatchBehaviour behaviour )
0143 {
0144     Q_UNUSED( behaviour ) // TODO
0145     DEBUG_BLOCK
0146 
0147     if( d->parentAlbumIds.isEmpty() )
0148     {
0149         const Meta::AmpacheArtist* serviceArtist = dynamic_cast< const Meta::AmpacheArtist * >( artist.data() );
0150         if( serviceArtist )
0151         {
0152             d->parentArtistIds << serviceArtist->id();
0153         }
0154         else
0155         {
0156             // searching for something from another collection
0157             if( d->collection->artistMap().contains( artist->name() ) )
0158             {
0159                 serviceArtist = static_cast< const Meta::AmpacheArtist* >( d->collection->artistMap().value( artist->name() ).data() );
0160                 d->parentArtistIds << serviceArtist->id();
0161             }
0162             else
0163             {
0164                 //hmm, not sure what to do now
0165             }
0166         }
0167     }
0168     return this;
0169 }
0170 
0171 QueryMaker *
0172 AmpacheServiceQueryMaker::addMatch( const Meta::AlbumPtr & album )
0173 {
0174     DEBUG_BLOCK
0175     const Meta::AmpacheAlbum* serviceAlbum = dynamic_cast< const Meta::AmpacheAlbum * >( album.data() );
0176     if( serviceAlbum )
0177     {
0178         d->parentAlbumIds << serviceAlbum->ids();
0179         debug() << "parent id set to: " << d->parentAlbumIds;
0180         d->parentArtistIds.clear();
0181     }
0182     else
0183     {
0184         // searching for something from another collection
0185         if( d->collection->albumMap().contains( album ) )  // compares albums by value
0186         {
0187             serviceAlbum = static_cast< const Meta::AmpacheAlbum* >( d->collection->albumMap().value( album ).data() );
0188             d->parentAlbumIds << serviceAlbum->ids();
0189             d->parentArtistIds.clear();
0190         }
0191         else
0192         {
0193             //hmm, not sure what to do now
0194         }
0195     }
0196 
0197     return this;
0198 }
0199 
0200 void
0201 AmpacheServiceQueryMaker::fetchArtists()
0202 {
0203     DEBUG_BLOCK
0204 
0205     Meta::ArtistList artists;
0206 
0207     // first try the cache
0208     if( !d->parentArtistIds.isEmpty() )
0209     {
0210         for( int artistId : qAsConst(d->parentArtistIds) )
0211             artists << d->collection->artistById( artistId );
0212     }
0213 
0214     if( !artists.isEmpty() )
0215     {
0216         debug() << "got" << artists.count() << "artists from the memory collection";
0217         Q_EMIT newArtistsReady( artists );
0218         Q_EMIT queryDone();
0219         return;
0220     }
0221 
0222     QUrl request = getRequestUrl( "artists" );
0223     QUrlQuery query( request );
0224 
0225     if ( !d->artistFilter.isEmpty() )
0226     {
0227         query.addQueryItem( "filter", d->artistFilter );
0228         request.setQuery( query );
0229     }
0230 
0231     d->expectedReplies.ref();
0232     The::networkAccessManager()->getData( request, this, &AmpacheServiceQueryMaker::artistDownloadComplete );
0233 }
0234 
0235 void
0236 AmpacheServiceQueryMaker::fetchAlbums()
0237 {
0238     DEBUG_BLOCK
0239 
0240     Meta::AlbumList albums;
0241 
0242     // first try the cache
0243     if( !d->parentArtistIds.isEmpty() )
0244     {
0245         foreach( int artistId, d->parentArtistIds )
0246             albums << matchAlbums( d->collection, d->collection->artistById( artistId ) );
0247     }
0248     if( !albums.isEmpty() )
0249     {
0250         debug() << "got" << albums.count() << "albums from the memory collection";
0251         Q_EMIT newAlbumsReady( albums );
0252         Q_EMIT queryDone();
0253         return;
0254     }
0255 
0256     if( !d->parentArtistIds.isEmpty() )
0257     {
0258         foreach( int id, d->parentArtistIds )
0259         {
0260             QUrl request = getRequestUrl( "artist_albums" );
0261             QUrlQuery query( request );
0262             query.addQueryItem( "filter", QString::number( id ) );
0263             request.setQuery( query );
0264 
0265             d->expectedReplies.ref();
0266             The::networkAccessManager()->getData( request, this, &AmpacheServiceQueryMaker::albumDownloadComplete );
0267         }
0268     }
0269     else
0270     {
0271         QUrl request = getRequestUrl( "albums" );
0272         QUrlQuery query( request );
0273 
0274         if ( !d->albumFilter.isEmpty() )
0275         {
0276             query.addQueryItem( "filter", d->albumFilter );
0277             request.setQuery( query );
0278         }
0279 
0280         d->expectedReplies.ref();
0281         The::networkAccessManager()->getData( request, this, &AmpacheServiceQueryMaker::albumDownloadComplete );
0282     }
0283 }
0284 
0285 void
0286 AmpacheServiceQueryMaker::fetchTracks()
0287 {
0288     DEBUG_BLOCK
0289 
0290     Meta::TrackList tracks;
0291 
0292     //debug() << "parent album id: " << d->parentAlbumId;
0293 
0294     // first try the cache
0295     // TODO: this is fishy as we cannot be sure that the cache contains
0296     //       everything
0297     //       we should cache database query results instead
0298     if( !d->parentTrackIds.isEmpty() )
0299     {
0300         foreach( int trackId, d->parentTrackIds )
0301         {
0302             tracks << d->collection->trackById( trackId );
0303         }
0304     }
0305     else if( !d->parentAlbumIds.isEmpty() )
0306     {
0307         foreach( int albumId, d->parentAlbumIds )
0308         {
0309             AlbumMatcher albumMatcher( d->collection->albumById( albumId ) );
0310             tracks << albumMatcher.match( d->collection->trackMap().values() );
0311         }
0312     }
0313     else if( d->parentArtistIds.isEmpty() )
0314     {
0315         foreach( int artistId, d->parentArtistIds )
0316         {
0317             ArtistMatcher artistMatcher( d->collection->artistById( artistId ) );
0318             tracks << artistMatcher.match( d->collection->trackMap().values() );
0319         }
0320     }
0321 
0322     if( !tracks.isEmpty() )
0323     {
0324         debug() << "got" << tracks.count() << "tracks from the memory collection";
0325         Q_EMIT newTracksReady( tracks );
0326         Q_EMIT queryDone();
0327         return;
0328     }
0329 
0330     QUrl request = getRequestUrl();
0331 
0332 
0333     if( !d->parentAlbumIds.isEmpty() )
0334     {
0335         foreach( int id, d->parentAlbumIds )
0336         {
0337             QUrl request = getRequestUrl( "album_songs" );
0338             QUrlQuery query( request );
0339             query.addQueryItem( "filter", QString::number( id ) );
0340             request.setQuery( query );
0341 
0342             d->expectedReplies.ref();
0343             The::networkAccessManager()->getData( request, this, &AmpacheServiceQueryMaker::trackDownloadComplete );
0344         }
0345     }
0346     else if( !d->parentArtistIds.isEmpty() )
0347     {
0348         foreach( int id, d->parentArtistIds )
0349         {
0350             QUrl request = getRequestUrl( "artist_songs" );
0351             QUrlQuery query( request );
0352             query.addQueryItem( "filter", QString::number( id ) );
0353             request.setQuery( query );
0354 
0355             d->expectedReplies.ref();
0356             The::networkAccessManager()->getData( request, this, &AmpacheServiceQueryMaker::trackDownloadComplete );
0357         }
0358     }
0359     else
0360     {
0361         QUrl request = getRequestUrl( "songs" );
0362 
0363         d->expectedReplies.ref();
0364         The::networkAccessManager()->getData( request, this, &AmpacheServiceQueryMaker::trackDownloadComplete );
0365     }
0366 }
0367 
0368 void
0369 AmpacheServiceQueryMaker::artistDownloadComplete( const QUrl &url, const QByteArray &data, const NetworkAccessManagerProxy::Error &e )
0370 {
0371     Q_UNUSED( url );
0372 
0373     if( e.code != QNetworkReply::NoError )
0374     {
0375         warning() << "Artist download error:" << e.description;
0376         if( !d->expectedReplies.deref() )
0377             Q_EMIT queryDone();
0378         return;
0379     }
0380 
0381     // DEBUG_BLOCK
0382 
0383     // so lets figure out what we got here:
0384     QDomDocument doc( "reply" );
0385     doc.setContent( data );
0386     QDomElement root = doc.firstChildElement( "root" );
0387 
0388     // Is this an error, if so we need to 'un-ready' the service and re-authenticate before continuing
0389     QDomElement domError = root.firstChildElement( "error" );
0390 
0391     if ( !domError.isNull() )
0392     {
0393         warning() << "Error getting Artist List" << domError.text() << "Code:" << domError.attribute("code");
0394         AmpacheService *parentService = dynamic_cast< AmpacheService * >( d->collection->service() );
0395         if( !parentService )
0396             return;
0397         else
0398             parentService->reauthenticate();
0399     }
0400 
0401     for( QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling() )
0402     {
0403         QDomElement e = n.toElement(); // try to convert the node to an element.
0404 
0405         QDomElement element = n.firstChildElement( "name" );
0406         int artistId = e.attribute( "id", "0").toInt();
0407 
0408         // check if we have the artist already
0409         Meta::ArtistPtr artistPtr = d->collection->artistById( artistId );
0410 
0411         if( !artistPtr )
0412         {
0413             // new artist
0414             Meta::ServiceArtist* artist = new Meta::AmpacheArtist( element.text(), d->collection->service() );
0415             artist->setId( artistId );
0416 
0417             // debug() << "Adding artist: " << element.text() << " with id: " << artistId;
0418 
0419             artistPtr = artist;
0420 
0421             d->collection->acquireWriteLock();
0422             d->collection->addArtist( artistPtr );
0423             d->collection->releaseLock();
0424         }
0425 
0426         if( !d->artistResults.contains( artistPtr ) )
0427             d->artistResults.push_back( artistPtr );
0428     }
0429 
0430     if( !d->expectedReplies.deref() )
0431     {
0432         Q_EMIT newArtistsReady( d->artistResults );
0433         Q_EMIT queryDone();
0434         d->artistResults.clear();
0435     }
0436 }
0437 
0438 void
0439 AmpacheServiceQueryMaker::albumDownloadComplete( const QUrl &url, const QByteArray &data, const NetworkAccessManagerProxy::Error &e )
0440 {
0441     Q_UNUSED( url );
0442 
0443     if( e.code != QNetworkReply::NoError )
0444     {
0445         warning() << "Album download error:" << e.description;
0446         if( !d->expectedReplies.deref() )
0447             Q_EMIT queryDone();
0448         return;
0449     }
0450 
0451     // DEBUG_BLOCK
0452 
0453      //so lets figure out what we got here:
0454     QDomDocument doc( "reply" );
0455     doc.setContent( data );
0456     QDomElement root = doc.firstChildElement( "root" );
0457 
0458     // Is this an error, if so we need to 'un-ready' the service and re-authenticate before continuing
0459     QDomElement domError = root.firstChildElement( "error" );
0460 
0461     if( !domError.isNull() )
0462     {
0463         warning() << "Error getting Album List" << domError.text() << "Code:" << domError.attribute("code");
0464         AmpacheService *parentService = dynamic_cast< AmpacheService * >(d->collection->service());
0465         if( parentService == nullptr )
0466             return;
0467         else
0468             parentService->reauthenticate();
0469     }
0470 
0471     for( QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling() )
0472     {
0473         QDomElement e = n.toElement(); // try to convert the node to an element.
0474 
0475         // --- the album artist
0476         Meta::ArtistPtr artistPtr;
0477         QDomElement artistElement = n.firstChildElement( "artist" );
0478         if( !artistElement.isNull() )
0479         {
0480             int artistId = artistElement.attribute( "id", "0").toInt();
0481             // check if we already know the artist
0482             artistPtr = d->collection->artistById( artistId );
0483             if( !artistPtr.data() )
0484             {
0485                 // new artist.
0486                 Meta::ServiceArtist* artist = new Meta::AmpacheArtist( artistElement.text(), d->collection->service() );
0487                 artistPtr = artist;
0488 
0489                 artist->setId( artistId );
0490                 // debug() << "Adding artist: " << artistElement.text() << " with id: " << artistId;
0491 
0492                 d->collection->acquireWriteLock();
0493                 d->collection->addArtist( artistPtr );
0494                 d->collection->releaseLock();
0495             }
0496         }
0497 
0498         QDomElement element = n.firstChildElement( "name" );
0499         QString title = element.text();
0500 
0501         Meta::AmpacheAlbum::AmpacheAlbumInfo info;
0502         info.id = e.attribute( "id", "0" ).toInt();
0503 
0504         element = n.firstChildElement( "disk" );
0505         info.discNumber = element.text().toInt();
0506 
0507         element = n.firstChildElement( "year" );
0508         info.year = element.text().toInt();
0509 
0510         // check if we have the album already
0511         Meta::AlbumPtr albumPtr = d->collection->albumById( info.id );
0512 
0513         if( !albumPtr )
0514         {
0515             // check if we at least have an album with the same title and artist
0516             Meta::AmpacheAlbum* album = static_cast<Meta::AmpacheAlbum*>(
0517             const_cast<Meta::Album*>( d->collection->albumMap().value( title, artistPtr ? artistPtr->name() : QString() ).data() ) );
0518 
0519             if( !album )
0520             {
0521                 // new album
0522                 album = new Meta::AmpacheAlbum( title );
0523                 album->setAlbumArtist( artistPtr );
0524 
0525                 // -- cover
0526                 element = n.firstChildElement( "art" );
0527 
0528                 QString coverUrl = element.text();
0529                 album->setCoverUrl( coverUrl );
0530             }
0531             album->addInfo( info );
0532 
0533             // debug() << "Adding album" << title << "with id:" << info.id;
0534 
0535             albumPtr = album;
0536 
0537             // register a new id with the ServiceCollection
0538             album->setId( info.id );
0539             d->collection->acquireWriteLock();
0540             d->collection->addAlbum( albumPtr );
0541             d->collection->releaseLock();
0542         }
0543 
0544         if( !d->albumResults.contains( albumPtr ) )
0545             d->albumResults.push_back( albumPtr );
0546     }
0547 
0548     if( !d->expectedReplies.deref() )
0549     {
0550         Q_EMIT newAlbumsReady( d->albumResults );
0551         Q_EMIT queryDone();
0552         d->albumResults.clear();
0553     }
0554 }
0555 
0556 void
0557 AmpacheServiceQueryMaker::trackDownloadComplete( const QUrl &url, const QByteArray &data, const NetworkAccessManagerProxy::Error &e )
0558 {
0559     Q_UNUSED( url );
0560 
0561     if( e.code != QNetworkReply::NoError )
0562     {
0563         warning() << "Track download error:" << e.description;
0564         if( !d->expectedReplies.deref() )
0565             Q_EMIT queryDone();
0566         return;
0567     }
0568 
0569     // DEBUG_BLOCK
0570 
0571      //so lets figure out what we got here:
0572     QDomDocument doc( "reply" );
0573     doc.setContent( data );
0574     QDomElement root = doc.firstChildElement( "root" );
0575 
0576     // Is this an error, if so we need to 'un-ready' the service and re-authenticate before continuing
0577     QDomElement domError = root.firstChildElement( "error" );
0578 
0579     if( !domError.isNull() )
0580     {
0581         warning() << "Error getting Track Download " << domError.text() << "Code:" << domError.attribute("code");
0582         AmpacheService *parentService = dynamic_cast< AmpacheService * >( d->collection->service() );
0583         if( parentService == nullptr )
0584             return;
0585         else
0586             parentService->reauthenticate();
0587     }
0588 
0589     for( QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling() )
0590     {
0591         QDomElement e = n.toElement(); // try to convert the node to an element.
0592 
0593         int trackId = e.attribute( "id", "0" ).toInt();
0594         Meta::TrackPtr trackPtr = d->collection->trackById( trackId );
0595 
0596         if( !trackPtr )
0597         {
0598             // new track
0599 
0600             QDomElement element = n.firstChildElement( "title" );
0601             QString title = element.text();
0602             Meta::AmpacheTrack * track = new Meta::AmpacheTrack( title, d->collection->service() );
0603             trackPtr = track;
0604 
0605             track->setId( trackId );
0606 
0607             element = n.firstChildElement( "url" );
0608             track->setUidUrl( element.text() );
0609 
0610             element = n.firstChildElement( "time" );
0611             track->setLength( element.text().toInt() * 1000 );
0612 
0613             element = n.firstChildElement( "track" );
0614             track->setTrackNumber( element.text().toInt() );
0615 
0616             element = n.firstChildElement( "rating" );
0617             track->statistics()->setRating( element.text().toDouble() * 2.0 );
0618 
0619             QDomElement albumElement = n.firstChildElement( "album" );
0620             int albumId = albumElement.attribute( "id", "0").toInt();
0621 
0622             QDomElement artistElement = n.firstChildElement( "artist" );
0623             int artistId = artistElement.attribute( "id", "0").toInt();
0624 
0625             Meta::ArtistPtr artistPtr = d->collection->artistById( artistId );
0626             // TODO: this assumes that we query all artist before tracks
0627             if( artistPtr )
0628             {
0629                 // debug() << "Found parent artist " << artistPtr->name();
0630                 Meta::ServiceArtist *artist = dynamic_cast< Meta::ServiceArtist * > ( artistPtr.data() );
0631                 track->setArtist( artistPtr );
0632                 artist->addTrack( trackPtr );
0633             }
0634 
0635             Meta::AlbumPtr albumPtr = d->collection->albumById( albumId );
0636             // TODO: this assumes that we query all albums before tracks
0637             if( albumPtr )
0638             {
0639                 // debug() << "Found parent album " << albumPtr->name() << albumId;
0640                 Meta::AmpacheAlbum *album = dynamic_cast< Meta::AmpacheAlbum * > ( albumPtr.data() );
0641                 track->setDiscNumber( album->getInfo( albumId ).discNumber );
0642                 track->setYear( album->getInfo( albumId ).year );
0643                 track->setAlbumPtr( albumPtr );
0644                 // debug() << " parent album with"<<track->discNumber()<<track->year();
0645                 album->addTrack( trackPtr );
0646             }
0647 
0648             // debug() << "Adding track: " <<  title << " with id: " << trackId;
0649 
0650             d->collection->acquireWriteLock();
0651             d->collection->addTrack( trackPtr );
0652             d->collection->releaseLock();
0653         }
0654 
0655         if( !d->trackResults.contains( trackPtr ) )
0656             d->trackResults.push_back( trackPtr );
0657     }
0658 
0659     if( !d->expectedReplies.deref() )
0660     {
0661         Q_EMIT newTracksReady( d->trackResults );
0662         Q_EMIT queryDone();
0663         d->trackResults.clear();
0664     }
0665 }
0666 
0667 QueryMaker *
0668 AmpacheServiceQueryMaker::addFilter( qint64 value, const QString & filter, bool matchBegin, bool matchEnd )
0669 {
0670     Q_UNUSED( matchBegin )
0671     Q_UNUSED( matchEnd )
0672 
0673     //for now, only accept artist filters
0674     // TODO: What about albumArtist?
0675     if( value == Meta::valArtist )
0676     {
0677         d->artistFilter = filter;
0678     }
0679     else if( value == Meta::valAlbum )
0680     {
0681         d->albumFilter = filter;
0682     }
0683     else
0684     {
0685         warning() << "unsupported filter" << Meta::nameForField( value );
0686     }
0687     return this;
0688 }
0689 
0690 QueryMaker*
0691 AmpacheServiceQueryMaker::addNumberFilter( qint64 value, qint64 filter, QueryMaker::NumberComparison compare )
0692 {
0693     if( value == Meta::valCreateDate && compare == QueryMaker::GreaterThan )
0694     {
0695         debug() << "asking to filter based on added date";
0696         d->dateFilter = filter;
0697         debug() << "setting dateFilter to:" << d->dateFilter;
0698     }
0699     else
0700     {
0701         warning() << "unsupported filter" << Meta::nameForField( value );
0702     }
0703     return this;
0704 }
0705 
0706 int
0707 AmpacheServiceQueryMaker::validFilterMask()
0708 {
0709     //we only support artist and album filters for now...
0710     return ArtistFilter | AlbumFilter;
0711 }
0712 
0713 QueryMaker *
0714 AmpacheServiceQueryMaker::limitMaxResultSize( int size )
0715 {
0716     d->maxsize = size;
0717     return this;
0718 }
0719 
0720 QUrl
0721 AmpacheServiceQueryMaker::getRequestUrl( const QString &action ) const
0722 {
0723     QUrl url = d->server;
0724     QString scheme = url.scheme();
0725 
0726     if( scheme != "http" && scheme != "https" )
0727         url.setScheme( "http" );
0728 
0729     QUrlQuery query( url );
0730 
0731     url = url.adjusted( QUrl::StripTrailingSlash );
0732     url.setPath( url.path() + "/server/xml.server.php" );
0733 
0734     query.addQueryItem( "auth", d->sessionId );
0735 
0736     if( !action.isEmpty() )
0737         query.addQueryItem( "action", action );
0738 
0739     if( d->dateFilter > 0 )
0740     {
0741         QDateTime from;
0742         from.setSecsSinceEpoch( d->dateFilter );
0743         query.addQueryItem( "add", from.toString( Qt::ISODate ) );
0744     }
0745     query.addQueryItem( "limit", QString::number( d->maxsize ) );
0746     url.setQuery( query );
0747 
0748     return url;
0749 }
0750 
0751