mpviewplugins/mpdetailsviewplugin/src/mpquerymanager.cpp
changeset 51 560ce2306a17
parent 47 4cc1412daed0
--- a/mpviewplugins/mpdetailsviewplugin/src/mpquerymanager.cpp	Fri Aug 06 16:51:36 2010 -0500
+++ b/mpviewplugins/mpdetailsviewplugin/src/mpquerymanager.cpp	Tue Aug 24 03:36:14 2010 -0500
@@ -16,7 +16,6 @@
 */
 
 #include "mpquerymanager.h"
-#include <QDebug>
 #include <QObject>
 #include <QNetworkAccessManager>
 #include <QNetworkDiskCache>
@@ -25,58 +24,31 @@
 #include <QNetworkSession>
 #include <QDomElement>
 #include <QList>
-#include <QFile>
 #include <QUrl>
 #include <QSslError>
-#include <QDir>
-#include <QCoreApplication>
 #include <XQSysInfo>
-
-#include <thumbnailmanager_qt.h>
-#include <thumbnaildata.h>
-#include <thumbnailobjectsource.h>
+#include <QSignalMapper>
+#include <QSettings>
 
 #include "mptrace.h"
 
-const int KUndefined = -1;
 const int KRecommendationCount = 2;
 
 MpQueryManager::MpQueryManager()
     : mManager(0),
       mAlbumArtDownloader(0),
-      mThumbnailManager(0),
       mDefaultRecommendationAlbumArt("qtg_large_album_art"),
       mRequestType(NoRequest),
-      mRecommendationCount(0)
-                               
+      mRecommendationCount(0)                               
 {
     TX_ENTRY
-
-    QString privatePathQt( QCoreApplication::applicationDirPath() );
-    TX_LOG_ARGS( "Private path: " << privatePathQt );
-    QDir dir( privatePathQt );
-    QString newDir = "detailsview";
-    bool res = dir.mkdir( newDir );
-    TX_LOG_ARGS( "New dir creation result: " << res);
+    mManager = new QNetworkAccessManager( this );      
+    // A second intance is necessary to reduce complexity.
+    // Otherwise, we would have to shoot async events when we want to receive inspire me items' album art
+    // and that may not always work.
+    mAlbumArtDownloader = new QNetworkAccessManager( this ); 
 
-    // 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 );      
-    mAlbumArtDownloader = new QNetworkAccessManager( this );    // TODO: check if we can only use mManager
-    mThumbnailManager = new ThumbnailManager( this );
-    mThumbnailManager->setQualityPreference( ThumbnailManager::OptimizeForQuality );
-    mThumbnailManager->setThumbnailSize( ThumbnailManager::ThumbnailSmall );
-
+    mDownloadSignalMapper = new QSignalMapper(this);
     TX_EXIT
 }
 
@@ -90,9 +62,7 @@
     if ( mAlbumArtDownloader ) {
        mAlbumArtDownloader->deleteLater();
     }
-    if( mThumbnailManager ) {
-        mThumbnailManager->deleteLater();
-    }
+    delete mDownloadSignalMapper;
     TX_EXIT
 }
 
@@ -115,21 +85,6 @@
     TX_EXIT
 }
 
-
-void MpQueryManager::queryLocalMusicStore(QString artist,QString album,QString title)
-{
-    TX_ENTRY
-    mArtist=artist;
-    mAlbum=album;
-    mTitle=title;
-    // TODO: country information handling, MCC
-    QString queryURI("http://api.music.ovi.com/1.0/ru/?");
-    constructRequest( queryURI );
-    TX_LOG_ARGS( "queryURI : " << queryURI );
-    retrieveInformation( queryURI );
-    mRequestType = LocalStoreRequest;    
-    TX_EXIT    
-}
     
 void MpQueryManager::queryInspireMeItems(QString artist,QString album,QString title)
 {
@@ -140,7 +95,6 @@
     // start querying inspire me items
     QString queryRecommendation("http://api.music.ovi.com/1.0/" + mMusicStore + "/releases/recommend/?");
     constructRequest( 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");
@@ -161,13 +115,6 @@
     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    
 }
 
@@ -284,7 +231,6 @@
 void MpQueryManager::retrieveInformationNetworkError( QNetworkReply::NetworkError error )
 {
     TX_ENTRY_ARGS( "Network error for retrieving Information" << error);    
-    // TODO: agree on error handling
 
 	Q_UNUSED(error)
 
@@ -298,7 +244,6 @@
  */
 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();    
@@ -308,91 +253,47 @@
 /*!
  Slot to call when downloading finished
  */
-void MpQueryManager::albumArtDownloaded( QNetworkReply* reply )
+void MpQueryManager::albumArtDownloaded( int index )
 {
-    TX_ENTRY_ARGS( "mDownloadedAlbumArts = " << mDownloadedAlbumArts );
-    TX_ENTRY_ARGS( "QNetworkReply obj " << reply);
+    TX_ENTRY_ARGS( "mDownloadedAlbumArts = " << mDownloadedAlbumArts << "index = " << index);
     
+    QNetworkReply* reply = qobject_cast<QNetworkReply*> ( qobject_cast<QSignalMapper*>( sender() )->mapping( index ) );
     // 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 );
+        QPixmap albumart;
+        bool result = albumart.loadFromData( reply->readAll() );
+        if ( result ) {
+            mRecommendationAlbumArtsMap.insert( mRecommendationAlbumArtsLink.at( index ), HbIcon( QIcon( albumart ) ) );
 
-        // 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 ) {
-            // 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 {
+            mRecommendationAlbumArtsMap.insert( mRecommendationAlbumArtsLink.at( index ), mDefaultRecommendationAlbumArt );        
         }
-        else {
-            setAlbumArtUri(mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), "");
-        }
+
         ++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" );
+        mRecommendationAlbumArtsMap.insert( mRecommendationAlbumArtsLink.at( index ), mDefaultRecommendationAlbumArt );  
     }
+    mDownloadSignalMapper->removeMappings( reply );
     
     if( mDownloadedAlbumArts == mRecommendationCount) {
         // no need to be informed anymore
-        mAlbumArtDownloader->disconnect(this);
+        mDownloadSignalMapper->disconnect(this);
+        emit inspireMeItemAlbumArtReady();    
     }
     
     TX_EXIT
 }
 
-/*!
- Write the image data to a file with the given filename.
- If writing operation fails for any reason (e.g. OOD),
- returns false, otherwise true.
- */
-bool MpQueryManager::writeImageToFile(const QByteArray &aImageData, const QString &aImageFileName )
-{
-    bool ret( false );
-    TX_ENTRY_ARGS( "imagefile: " << aImageFileName );
-    if ( aImageFileName.isEmpty() ) {
-        TX_LOG_ARGS( "Only store two album arts" );
-    }
-    else {
-        QFile file( aImageFileName );
-        if ( !file.open( QIODevice::ReadWrite ) ) {
-            TX_LOG_ARGS( "Unable to open file" );
-        }
-        else {
-            qint64 writtenBytes = file.write( aImageData );
-            // Verify file write status
-            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 {
-                // 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
@@ -428,7 +329,6 @@
                 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;
                     }
@@ -457,12 +357,15 @@
             if ( mRecommendationAlbumArtsLink.at( i ).contains( "http", Qt::CaseInsensitive ) ) {
                 reply = mAlbumArtDownloader->get( QNetworkRequest( QUrl( mRecommendationAlbumArtsLink.at(i) ) ) );
                 mReplys.append( reply );
+                connect( reply, SIGNAL( finished() ), mDownloadSignalMapper, SLOT( map() ) );
+                mDownloadSignalMapper->setMapping( reply, i );
+
                 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );
                 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) );
             }
         }
        // 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 * ) ) );
+        connect( mDownloadSignalMapper, SIGNAL( mapped( int ) ), this, SLOT( albumArtDownloaded( int ) ) );
 
     }
     else if ( rootElement.attribute( "type" ) == "storeList" ) {
@@ -470,10 +373,15 @@
         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);
+        if( !mMusicStore.isEmpty() ) {
+            bool musicStoreUpdated = ( previousMusicStore != mMusicStore );
+            TX_LOG_ARGS("Music Store" << mMusicStore );
+            emit localMusicStoreRetrieved( musicStoreUpdated );
+            if( musicStoreUpdated ) {
+                QSettings settings;
+                TX_LOG_ARGS( "Storing music store value: " << mMusicStore );
+                settings.setValue( "LocalMusicStore", QVariant( mMusicStore ) );
+            }    
         }
         else {
             emit localMusicStoreRetrievalError();   
@@ -485,28 +393,14 @@
     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
 }
@@ -521,8 +415,8 @@
     QStringList keys;
     keys << "artist" << "albumtitle" << "tracktitle" << "orderby";
     
-    // TODO: need to clarify which crition to use for sort, currently hard code to "relevancy"
-    // order can be relevancy, alltimedownloads, streetreleasedate, sortname, recentdownloads
+    // "relevancy" is the selected sort order
+    // sort order types can be relevancy, alltimedownloads, streetreleasedate, sortname, recentdownloads
     QStringList values;
     values << mArtist << mAlbum << mTitle << QString("relevancy");
     TX_LOG_ARGS( "Artist: " << mArtist ); 
@@ -558,71 +452,14 @@
     return str.left( str.length() - 1 );
 }
 
-/*!
- Sets recommendation album art
-*/
-void MpQueryManager::setAlbumArtUri( const QString &albumArtUri, const QString &albumArtName )
+bool MpQueryManager::isLocalMusicStore()
 {
-    // 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
-            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.
-        mRecommendationAlbumArtsMap.insert( albumArtUri, mDefaultRecommendationAlbumArt );
+    if( mMusicStore.isEmpty() ) {
+        QSettings settings;
+        QVariant settingsvariant = settings.value( "LocalMusicStore", "" );
+        mMusicStore = settingsvariant.toString(); 
+        TX_LOG_ARGS( "Got local music store from settings:" << mMusicStore );
     }
-    TX_EXIT
-}
-
-/*!
- Slot to handle the recommendation album art 
-*/
-void MpQueryManager::thumbnailReady(
-        const QPixmap pixmap,
-        void *data,
-        int id,
-        int error  )
-{
-    TX_ENTRY
-
-    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 );
-        mRecommendationAlbumArtsMap.insert( uri, HbIcon(QIcon(pixmap)) );
-    }
-    else {
-        mRecommendationAlbumArtsMap.insert( uri, mDefaultRecommendationAlbumArt );        
-    }
-
-    emit inspireMeItemAlbumArtReady();    
-    TX_EXIT
-}
-
-bool MpQueryManager::isLocalMusicStore() const
-{
     TX_LOG_ARGS( "isLocalMusicStore = " << !mMusicStore.isEmpty() )
     return !mMusicStore.isEmpty();
 }