mpviewplugins/mpdetailsviewplugin/src/mpquerymanager.cpp
changeset 47 4cc1412daed0
parent 45 612c4815aebe
child 51 560ce2306a17
--- a/mpviewplugins/mpdetailsviewplugin/src/mpquerymanager.cpp	Fri Jul 23 17:31:12 2010 -0500
+++ b/mpviewplugins/mpdetailsviewplugin/src/mpquerymanager.cpp	Fri Aug 06 16:51:36 2010 -0500
@@ -22,7 +22,7 @@
 #include <QNetworkDiskCache>
 #include <QNetworkProxyFactory>
 #include <qmobilityglobal.h>
-#include <qnetworksession.h>
+#include <QNetworkSession>
 #include <QDomElement>
 #include <QList>
 #include <QFile>
@@ -30,12 +30,12 @@
 #include <QSslError>
 #include <QDir>
 #include <QCoreApplication>
+#include <XQSysInfo>
 
 #include <thumbnailmanager_qt.h>
 #include <thumbnaildata.h>
 #include <thumbnailobjectsource.h>
 
-#include "mpdetailssharedialog.h"
 #include "mptrace.h"
 
 const int KUndefined = -1;
@@ -43,8 +43,11 @@
 
 MpQueryManager::MpQueryManager()
     : mManager(0),
-      mDownloadManager(0),
-      mThumbnailManager(0)        
+      mAlbumArtDownloader(0),
+      mThumbnailManager(0),
+      mDefaultRecommendationAlbumArt("qtg_large_album_art"),
+      mRequestType(NoRequest),
+      mRecommendationCount(0)
                                
 {
     TX_ENTRY
@@ -56,56 +59,57 @@
     bool res = dir.mkdir( newDir );
     TX_LOG_ARGS( "New dir creation result: " << res);
 
-    // We're not handling a negative result for directory creation here,
-    // instead it will be escalated in DownloadFinished() method.
+    // TODO: Instead of writing the album art to a file, 
+	// then using Thumbnail Manager to convert it, etc. 
+	// have you considered just loading it directly into QPixmap? 
+	// QPixmap provides a loadFromData() that can load from QByteArray. 
+	// This would not only make the availability of the album art immediate, 
+	// but also save a lot of cleanup in file system, thumbnail manager, etc.    
     privatePathQt = privatePathQt + "/detailsview";
     QString albumArt1( privatePathQt + "/albumOne.png" );
     QString albumArt2( privatePathQt + "/albumTwo.png" );
     mRecommendationAlbumArtsName << albumArt1 << albumArt2;
     TX_LOG_ARGS( "recommendation album art names: " << mRecommendationAlbumArtsName );
 
-    mManager = new QNetworkAccessManager( this );
-      
-    mDownloadManager = new QNetworkAccessManager( this );
-    connect( mDownloadManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( DownloadFinished( QNetworkReply * ) ) );
-    
+    mManager = new QNetworkAccessManager( this );      
+    mAlbumArtDownloader = new QNetworkAccessManager( this );    // TODO: check if we can only use mManager
     mThumbnailManager = new ThumbnailManager( this );
     mThumbnailManager->setQualityPreference( ThumbnailManager::OptimizeForQuality );
     mThumbnailManager->setThumbnailSize( ThumbnailManager::ThumbnailSmall );
-    QObject::connect( mThumbnailManager, SIGNAL( thumbnailReady( QPixmap , void * , int , int ) ),
-            this, SLOT( thumbnailReady( QPixmap , void * , int , int  ) ) );
-    // TODO: Use the album art in provided by 10.1 wk16 platform. Current one is in the binary        
-    mDefaultRecommendationAlbumArt = QPixmap( ":/mpdetailsviewicons/qtg_large_music_album.svg" );    
-     
+
     TX_EXIT
 }
 
 MpQueryManager::~MpQueryManager()
 {
     TX_ENTRY
+    reset();
     if ( mManager ) {
        mManager->deleteLater();
-     }
-    if ( mDownloadManager ) {
-       mDownloadManager->deleteLater();
+    }
+    if ( mAlbumArtDownloader ) {
+       mAlbumArtDownloader->deleteLater();
     }
-    delete mThumbnailManager;
+    if( mThumbnailManager ) {
+        mThumbnailManager->deleteLater();
+    }
     TX_EXIT
 }
 
 
 void MpQueryManager::clearNetworkReplies()
 {
+    mRequestType = NoRequest; 
     disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );     
     TX_ENTRY_ARGS( "Reply count = " << mReplys.count() );    
-    for ( int i = 0; i < mReplys.count(); i++ ) {
+    for ( int i = 0; i < mReplys.count(); ++i ) {
         QNetworkReply *reply = mReplys.at( i );
         disconnect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );        
         if ( reply != NULL ) {
             reply->close();
             reply->deleteLater();
             reply = NULL;
-        }   
+        }
     }
     mReplys.clear();
     TX_EXIT
@@ -123,6 +127,7 @@
     constructRequest( queryURI );
     TX_LOG_ARGS( "queryURI : " << queryURI );
     retrieveInformation( queryURI );
+    mRequestType = LocalStoreRequest;    
     TX_EXIT    
 }
     
@@ -133,82 +138,89 @@
     mAlbum=album;
     mTitle=title;
     // start querying inspire me items
-    QString queryRecommendation("http://api.music.ovi.com/1.0/gb/releases/recommend/?");
+    QString queryRecommendation("http://api.music.ovi.com/1.0/" + mMusicStore + "/releases/recommend/?");
     constructRequest( queryRecommendation );
-    TX_LOG_ARGS( "queryRecommendation : " << queryRecommendation );
+	// TODO: Store the token to a cenrep key	
+    // TODO: Tokens change per new ovi api release. 
+	//       Need to figure out a way to get them updated on the fly
+    queryRecommendation.append("&Token=03574704-e3d1-4466-9691-e0b34c7abfff");
+
+    TX_LOG_ARGS( queryRecommendation );
     retrieveInformation( queryRecommendation );
+    mRequestType = InspireMeItemsMetadataRequest;
     TX_EXIT
 }
 
 void MpQueryManager::clearRecommendations()
 {
-    TX_ENTRY    
+    TX_ENTRY
+    mRecommendationCount = 0;
     mDownloadedAlbumArts = 0;
     mAlbumArtsReadyCount = 0;
-    for ( int i = 0; i < KRecommendationCount; i++ ) {
-       mRecommendationSongs.clear();
-       mRecommendationArtists.clear();
-       mRecommendationAlbumArtsLink.clear();
-       mRecommendationAlbumArtsMap.clear();      
-       QFile file( mRecommendationAlbumArtsName.at( i ) );        
-       if ( file.exists() ) {
-           if ( file.remove() ) {
-               TX_LOG_ARGS( "File removed - " << file.fileName() );
-           }
-           else {
-               TX_LOG_ARGS( "Cannot remove file - " << file.fileName() );
-           }
-       } else {
-           TX_LOG_ARGS( "File doesn't exist - " << file.fileName() );
+    mRecommendationSongs.clear();
+    mRecommendationArtists.clear();
+    mRecommendationAlbumArtsLink.clear();
+    mRecommendationAlbumArtsMap.clear();
+    for ( int i = 0; i < mRecommendationAlbumArtsName.count(); ++i ) {
+       QFile file( mRecommendationAlbumArtsName.at( i ) );
+       TX_LOG_ARGS( "File " << file.fileName() << " exists: " << file.exists() );
+       if ( file.exists() && file.remove() ) {
+            TX_LOG_ARGS( "File " << file.fileName() << " removed");
        }
     }
     TX_EXIT    
 }
 
+
+
 /*!
- Return recommendation songs
+ Returns the Local Music Store(if available) to be used while querying "Inspire Me" Items
  */
-QStringList MpQueryManager::recommendationSongs()
+void MpQueryManager::queryLocalMusicStore()
 {
-    TX_LOG  
-    return mRecommendationSongs;
+    TX_ENTRY
+    QString imsi,mcc;
+
+    XQSysInfo sysInfo( this );
+    imsi = sysInfo.imsi();
+    mcc= imsi.left(3);
+    TX_LOG_ARGS( "mcc : " << mcc );
+    
+    QString queryLocalMusicStore("http://api.music.cq1.brislabs.com/1.0/?mcc=" + mcc + "&token=06543e34-0261-40a4-a03a-9e09fe110c1f");
+    TX_LOG_ARGS( "queryLocalMusicStore : " << queryLocalMusicStore );
+    retrieveInformation( queryLocalMusicStore );
+    mRequestType = LocalStoreRequest;
+    TX_EXIT
+}
+
+
+int MpQueryManager::recommendationsCount() const
+{
+    TX_LOG_ARGS ("count: " << mRecommendationSongs.count());
+    return mRecommendationSongs.count();
+}
+
+QString MpQueryManager::recommendedSong(int index) const
+{
+    QString result;
+    if( (0 <= index) && (index < mRecommendationSongs.count())) {
+        result = mRecommendationSongs.at(index);
+    }
+    TX_LOG_ARGS ("recommendedSong: " << result);    
+    return result; 
 }
 
 /*!
  Return recommendation artists
  */
-QStringList MpQueryManager::recommendationArtists()
-{
-    TX_LOG  
-    return mRecommendationArtists;
-}
-
-/*!
- Return recommendation album arts links
- */
-QStringList MpQueryManager::recommendationAlbumArtsLink()
+QString MpQueryManager::recommendedArtist(int index) const
 {
-    TX_LOG  
-    return mRecommendationAlbumArtsLink;
-}
-
-/*!
- Return map of name and pixmap
- */
-QMap<QString, QPixmap>  MpQueryManager::recommendationAlbumArtsMap()
-{
-    TX_LOG  
-    return mRecommendationAlbumArtsMap;
-}
-
-/*!
- Insert one uri & pixmap item into map
- */
-void MpQueryManager::insertMapItem( const QString &uri, const QPixmap &pixmap )
-{
-    TX_ENTRY_ARGS( "Map Item URI: " << uri );
-    mRecommendationAlbumArtsMap.insert( uri, pixmap );
-    TX_EXIT
+    QString result;
+    if( (0 <= index) && (index < mRecommendationArtists.count())) {
+        result = mRecommendationArtists.at(index);
+    }
+    TX_LOG_ARGS ("recommendedArtist: " << result);    
+    return result;
 }
 
 /*!
@@ -221,24 +233,49 @@
     int errorLine;
     int errorColumn;
     bool parsingSuccess;
+        
+    if ( reply->error() != QNetworkReply::NoError ) {
+		TX_LOG_ARGS("reply->error(): " << reply->error());
+        signalError();
+        return;
+    }
+        
+    parsingSuccess = mDomDocument.setContent( reply, true, &errorStr, &errorLine, &errorColumn );
+    if ( !parsingSuccess ) {
+		TX_LOG_ARGS("Parsing Received Content Failed");
+        signalError();
+        return;
+    }
+
+    handleParsedXML();  //CodeScanner throws a warning mis-interpreting the trailing 'L' to be a leaving function.
     
-    if ( reply->error() == QNetworkReply::NoError )
-    {
-        parsingSuccess = mDomDocument.setContent( reply, true, &errorStr, &errorLine, &errorColumn );
-        if ( parsingSuccess ) {
-            handleParsedXML();  //CodeScanner throws a warning mis-interpreting the trailing 'L' to be a leaving function.
-        } else {
-            // TODO: agree on error handling            
-            TX_LOG_ARGS( "XML parsing error" );
-        }
+    mReplys.removeAll(reply); // remove it so that we wont process it again
+    reply->deleteLater(); // make sure reply is deleted, as we longer care about it
+    
+    TX_EXIT
+}
+
+void MpQueryManager::signalError()
+{
+    TX_ENTRY; 
+    switch(mRequestType) {
+        case InspireMeItemsMetadataRequest:
+            TX_LOG_ARGS("emit inspireMeItemsRetrievalError");
+            emit inspireMeItemsRetrievalError();
+            break;
+        case InspireMeItemsAlbumArtRequest:
+            TX_LOG_ARGS("Warning: InspireMeItemsAlbumArtRequestError, will keep using the default AA icon");            
+            break;    
+        case LocalStoreRequest:
+            TX_LOG_ARGS("emit localMusicStoreRetrievalError");            
+            emit localMusicStoreRetrievalError();
+            break;
+        case NoRequest:   
+        default:
+            TX_LOG_ARGS("Warning!! Possible uninitialized mRequestType");            
+            break;                                 
     }
-    else
-    {
-        // TODO: agree on error handling
-        TX_LOG_ARGS( "Network error in retrieving Information" );
-        emit networkError();
-    }
-    TX_EXIT
+    TX_EXIT    
 }
 
 /*!
@@ -246,9 +283,13 @@
  */
 void MpQueryManager::retrieveInformationNetworkError( QNetworkReply::NetworkError error )
 {
+    TX_ENTRY_ARGS( "Network error for retrieving Information" << error);    
     // TODO: agree on error handling
+
 	Q_UNUSED(error)
-    TX_ENTRY_ARGS( "Network error for retrieving Information" << error);
+
+    disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );     
+    signalError();
     TX_EXIT
 }
 
@@ -256,43 +297,59 @@
  Slot to call when there is ssl error
  */
 void MpQueryManager::retrieveInformationSslErrors( const QList<QSslError> &/*error*/ )
-{   
+{
     // TODO: agree on error handling
     TX_ENTRY_ARGS( "SSL error for retrieving Information" );
+    disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );     
+    signalError();    
     TX_EXIT
 }
 
 /*!
  Slot to call when downloading finished
  */
-void MpQueryManager::DownloadFinished( QNetworkReply* reply )
+void MpQueryManager::albumArtDownloaded( QNetworkReply* reply )
 {
     TX_ENTRY_ARGS( "mDownloadedAlbumArts = " << mDownloadedAlbumArts );
-    if ( reply->error() == QNetworkReply::NoError )
-        {
+    TX_ENTRY_ARGS( "QNetworkReply obj " << reply);
+    
+    // It seems we get several finished signals for the same reply obj
+    // do nothing if we get a second signal
+    if( mReplys.indexOf(reply) == -1 ) {
+        TX_LOG_ARGS("Warning: QNetworkReply AA request may have been processed in previous call: " << reply );
+        return;
+    }
+        
+    if ( reply->error() == QNetworkReply::NoError ) {
+        
         QString fileName = mRecommendationAlbumArtsName.at( mDownloadedAlbumArts );
         QByteArray imageData = reply->readAll();
         bool ret = writeImageToFile( imageData, fileName );
 
         // If file writing went OK, emit a signal with the real filename
         // If it failed, use empty filename (since file was removed in any case)
-        if ( ret )
-            {
+        if ( ret ) {
+            // TODO: If album album arts come in different order than they have been asked,
+            // then inspire me items will use swapped album arts. Correct
             setAlbumArtUri( mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), 
                             mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) );
-            }
-        else
-            {
+        }
+        else {
             setAlbumArtUri(mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), "");
-            }
         }
-    else
-    {
-        TX_LOG_ARGS( "Downloading album art failed!" );
-        emit networkError();
+        ++mDownloadedAlbumArts;
+        mReplys.removeAll(reply); // remove it so that we wont process it again
+        reply->deleteLater(); // make sure reply is deleted, as we longer care about it
+    }
+    else {
+        TX_LOG_ARGS( "Error: Downloading album art failed! Will keep using the default AA" );
     }
     
-    mDownloadedAlbumArts++;
+    if( mDownloadedAlbumArts == mRecommendationCount) {
+        // no need to be informed anymore
+        mAlbumArtDownloader->disconnect(this);
+    }
+    
     TX_EXIT
 }
 
@@ -302,48 +359,40 @@
  returns false, otherwise true.
  */
 bool MpQueryManager::writeImageToFile(const QByteArray &aImageData, const QString &aImageFileName )
-    {
+{
     bool ret( false );
     TX_ENTRY_ARGS( "imagefile: " << aImageFileName );
-    if ( aImageFileName.isEmpty() )
-        {
+    if ( aImageFileName.isEmpty() ) {
         TX_LOG_ARGS( "Only store two album arts" );
-        }
-    else
-        {
+    }
+    else {
         QFile file( aImageFileName );
-
-        if ( !file.open( QIODevice::ReadWrite ) )
-            {
+        if ( !file.open( QIODevice::ReadWrite ) ) {
             TX_LOG_ARGS( "Unable to open file" );
-            }
-        else
-            {
+        }
+        else {
             qint64 writtenBytes = file.write( aImageData );
-
             // Verify file write status
-            if ( writtenBytes < aImageData.size() )
-                {
+            if ( writtenBytes < aImageData.size() ) {
                 // If write succeeded only partially, or completely failed,
                 // remove the file from filesystem to remove risk of corruption
                 TX_LOG_ARGS( "Wrote only " << writtenBytes << " bytes, aborting operation!" );
                 file.close();
                 QFile::remove( mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) );
-                }
-            else
-                {
+            }
+            else {
                 // If write fully succeeded, flush contents
                 TX_LOG_ARGS( "Wrote all the bytes (" << writtenBytes << "), flushing and closing!");
                 file.flush();
                 file.close();
                 ret = true;
-                }
             }
         }
+    }
     TX_LOG_ARGS( "Returning with value: " << ret );
     TX_EXIT
     return ret;
-    }
+}
 
 /*!
  Get Atom response from Ovi server based on query
@@ -351,7 +400,7 @@
 void MpQueryManager::retrieveInformation( const QString &urlEncoded )
 {
     TX_ENTRY_ARGS( "urlEconded = " << urlEncoded)
-    connect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );    
+    connect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ), Qt::UniqueConnection );
     QNetworkReply *reply = mManager->get( QNetworkRequest( QUrl( urlEncoded ) ) );
     mReplys.append( reply );
     
@@ -369,71 +418,99 @@
     TX_ENTRY
     QDomElement rootElement = mDomDocument.documentElement();
     
-    if ( rootElement.attribute( "type" ) == "search" ) {
-        TX_LOG_ARGS( "URI response" )
-        QString result;
+    if ( rootElement.attribute( "type" ) == "recommendedTracks" ) {
+        TX_LOG_ARGS( "Recommendation response" )
         QDomElement entry = rootElement.firstChildElement( "entry" );
-        while ( !entry.isNull() )
-        {
+        mRecommendationCount = 0;
+        while ( !entry.isNull() && mRecommendationCount < KRecommendationCount ) {
             if ( entry.attribute( "type" ) == "musictrack" ) {
                 QDomElement link = entry.firstChildElement( "link" );
-                while ( !link.isNull() )
-                {
-                    if ( link.attribute( "rel" ) == "alternate"
-                        && link.attribute( "type" ) == "text/html" ) {
-                        result = link.attribute( "href" );
-                    }
-                    link = link.nextSiblingElement( "link" );
-                }
-            }
-            entry = entry.nextSiblingElement( "entry" );
-        }
-		// Signal that the url was received. Might be empty string.
-		emit searchUrlRetrieved( result );
-    } else if ( rootElement.attribute( "type" ) == "recommendedTracks" ) {
-        TX_LOG_ARGS( "Recommendation response" )
-        QDomElement entry = rootElement.firstChildElement( "entry" );
-        QNetworkReply *reply;
-        int count = 0;
-        while ( !entry.isNull() && count < KRecommendationCount )
-        {
-            if ( entry.attribute( "type" ) == "musictrack" ) {
-                QDomElement link = entry.firstChildElement( "link" );
-                while ( !link.isNull() )
-                {
+                while ( !link.isNull() ) {
                     if ( link.attribute( "title" ) == "albumart100" ) {
                         mRecommendationAlbumArtsLink.append( link.attribute( "href" ) );
+                        // TODO: This may get called twice for one inspire me item. Investigate why
+                        mRecommendationAlbumArtsMap.insert( link.attribute( "href" ), mDefaultRecommendationAlbumArt );                      
                         break;
-                    } else {
+                    }
+                    else {
                         link = link.nextSiblingElement( "link" );
-                    }                    
+                    }
                 }
                 QDomElement metadata = entry.firstChildElement( "metadata" );
                 mRecommendationSongs.append( metadata.firstChildElement( "name" ).text() );
                 mRecommendationArtists.append( metadata.firstChildElement( "primaryartist" ).text() );
-                count++;
+                ++mRecommendationCount;
             }
             entry = entry.nextSiblingElement( "entry" );
-        }          
-        
-        for (int i = 0; i < KRecommendationCount; i++ ) {
+        }
+ 
+        emit inspireMeItemsMetadataRetrieved();
+
+        QNetworkReply *reply = 0;
+        // we need to channel the retrieved album arts to albumArtDownloaded slot only
+        disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );        
+        for (int i = 0; i < mRecommendationCount; i++ ) {
             TX_LOG_ARGS( "song name: " << mRecommendationSongs.at(i) );
             TX_LOG_ARGS( "Artist name: " << mRecommendationArtists.at(i) );
             TX_LOG_ARGS( "Album art link: " << mRecommendationAlbumArtsLink.at(i) );
-            
+            mRequestType = InspireMeItemsAlbumArtRequest;
             if ( mRecommendationAlbumArtsLink.at( i ).contains( "http", Qt::CaseInsensitive ) ) {
-                reply = mDownloadManager->get( QNetworkRequest( QUrl( mRecommendationAlbumArtsLink.at(i) ) ) );
+                reply = mAlbumArtDownloader->get( QNetworkRequest( QUrl( mRecommendationAlbumArtsLink.at(i) ) ) );
                 mReplys.append( reply );
                 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );
                 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) );
-            }             
+            }
         }
-    } else {
+       // we have queried for album arts for inspire me items. Now, time to wait for a response        
+       connect( mAlbumArtDownloader, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( albumArtDownloaded( QNetworkReply * ) ) );
+
+    }
+    else if ( rootElement.attribute( "type" ) == "storeList" ) {
+		TX_LOG_ARGS( "Music Store List" )
+        QDomElement entry = rootElement.firstChildElement( "workspace" );
+        QString previousMusicStore = mMusicStore;
+        mMusicStore = entry.attribute( "countryCode" );
+        if(!mMusicStore.isEmpty()) {
+            bool musicStoreUpdated = (previousMusicStore != mMusicStore);
+        	TX_LOG_ARGS("Music Store" << mMusicStore );
+            emit localMusicStoreRetrieved(musicStoreUpdated);
+        }
+        else {
+            emit localMusicStoreRetrievalError();   
+        }		
+    }
+    else {
         TX_LOG_ARGS( "Not supported response" )
     }
     TX_EXIT
 }
 
+void MpQueryManager::clearThumbnails()
+{
+    TX_ENTRY
+    for(int i = 0; i < mThumbnailRequests.count(); ++i ) {
+        mThumbnailManager->cancelRequest(mThumbnailRequests.at(i));
+    }
+    mThumbnailRequests.clear();    
+    for(int i = 0; i < mRecommendationAlbumArtsName.count(); ++i) {
+        mThumbnailManager->deleteThumbnails(mRecommendationAlbumArtsName.at(i)); // async, returns immidiately
+    }
+    TX_EXIT        
+}
+
+void MpQueryManager::reset()
+{
+    TX_ENTRY
+    mManager->disconnect(this);
+    mAlbumArtDownloader->disconnect(this);
+    mThumbnailManager->disconnect(this);
+    clearNetworkReplies();
+    clearRecommendations();
+    clearThumbnails();
+    mRecommendationAlbumArtsMap.clear();
+    TX_EXIT
+}
+    
 /*!
  Construct the query for fetching URI & recommendations
  */
@@ -468,11 +545,11 @@
     QString str;
     if ( keys.length() != values.length() ) {
         TX_LOG_ARGS( "Error: keys length is not equal to values length" ); 
-    } else {
+    }
+    else {
         for ( int i = 0; i < keys.length(); i++ ) {
             QString tValue = values.at( i );
-            if ( 0 != tValue.length() )
-            {
+            if ( 0 != tValue.length() ) {
                 str += keys.at( i ) + "=" + values.at( i ) + "&";
             }
         }
@@ -486,18 +563,28 @@
 */
 void MpQueryManager::setAlbumArtUri( const QString &albumArtUri, const QString &albumArtName )
 {
+    // TODO: rename this function. Doing too many things
     TX_ENTRY_ARGS( "albumArtUri = " << albumArtUri )
     TX_LOG_ARGS( "albumArtName = " << albumArtName )
     if ( !albumArtUri.isEmpty() && !albumArtName.isEmpty() ) {
+        // TODO: this is no good to pass the address of the albumArtUri. It is an item in the list, which can cleaned
         int id = mThumbnailManager->getThumbnail( albumArtName, reinterpret_cast<void *>( const_cast<QString *>( &albumArtUri ) ) );
         if ( id == KUndefined ) {
-            // Request failed. Set default album art.
-            insertMapItem( albumArtUri, mDefaultRecommendationAlbumArt );
+            // Request failed. Set default album art
+            mRecommendationAlbumArtsMap.insert( albumArtUri, mDefaultRecommendationAlbumArt );
+        }
+        else {
+            // Async request went throu
+            TX_LOG_ARGS("Request to thumbnail manager made. Id: " << id)
+            mThumbnailRequests.append(id);
+            mThumbnailManager->disconnect( this ); // to prevent multiple same connections with thumbnailmanager
+            QObject::connect( mThumbnailManager, SIGNAL( thumbnailReady( QPixmap , void * , int , int ) ),
+            this, SLOT( thumbnailReady( QPixmap , void * , int , int  ) ) );
         }
     }
     else {
         // No album art uri. Set default album art.
-        insertMapItem( albumArtUri, mDefaultRecommendationAlbumArt );
+        mRecommendationAlbumArtsMap.insert( albumArtUri, mDefaultRecommendationAlbumArt );
     }
     TX_EXIT
 }
@@ -506,24 +593,42 @@
  Slot to handle the recommendation album art 
 */
 void MpQueryManager::thumbnailReady(
-        const QPixmap& pixmap,
+        const QPixmap pixmap,
         void *data,
-        int /*id*/,
+        int id,
         int error  )
 {
     TX_ENTRY
-    // TODO: Hkn: use qobject_cast
+
+    if( mThumbnailRequests.indexOf(id) == -1 ) {
+        TX_LOG_ARGS("Warning: some old thumbnail request from previous song. Ignoring")
+        return;
+    }
+    
+    // TODO: Using data from array, which can be reset. There must be a safer way    
     QString uri = *( reinterpret_cast<QString *>( data ) );
     TX_LOG_ARGS( "Uri: " << uri );
     
     if ( error == 0 ) {
         TX_LOG_ARGS( "album art link: " << uri );
-        insertMapItem( uri, pixmap );
-    } else {
-        insertMapItem( uri, mDefaultRecommendationAlbumArt );
+        mRecommendationAlbumArtsMap.insert( uri, HbIcon(QIcon(pixmap)) );
     }
-    if(++mAlbumArtsReadyCount == KRecommendationCount) {
-        emit recommendationAlbumArtsReady();
-    }    
+    else {
+        mRecommendationAlbumArtsMap.insert( uri, mDefaultRecommendationAlbumArt );        
+    }
+
+    emit inspireMeItemAlbumArtReady();    
     TX_EXIT
 }
+
+bool MpQueryManager::isLocalMusicStore() const
+{
+    TX_LOG_ARGS( "isLocalMusicStore = " << !mMusicStore.isEmpty() )
+    return !mMusicStore.isEmpty();
+}
+
+HbIcon MpQueryManager::recommendedAlbumArt(int index) const
+{
+    TX_LOG_ARGS( "index = " << index )
+    return mRecommendationAlbumArtsMap.value( mRecommendationAlbumArtsLink.at( index ) );
+}