mpviewplugins/mpdetailsviewplugin/src/mpquerymanager.cpp
changeset 47 4cc1412daed0
parent 45 612c4815aebe
child 51 560ce2306a17
equal deleted inserted replaced
45:612c4815aebe 47:4cc1412daed0
    20 #include <QObject>
    20 #include <QObject>
    21 #include <QNetworkAccessManager>
    21 #include <QNetworkAccessManager>
    22 #include <QNetworkDiskCache>
    22 #include <QNetworkDiskCache>
    23 #include <QNetworkProxyFactory>
    23 #include <QNetworkProxyFactory>
    24 #include <qmobilityglobal.h>
    24 #include <qmobilityglobal.h>
    25 #include <qnetworksession.h>
    25 #include <QNetworkSession>
    26 #include <QDomElement>
    26 #include <QDomElement>
    27 #include <QList>
    27 #include <QList>
    28 #include <QFile>
    28 #include <QFile>
    29 #include <QUrl>
    29 #include <QUrl>
    30 #include <QSslError>
    30 #include <QSslError>
    31 #include <QDir>
    31 #include <QDir>
    32 #include <QCoreApplication>
    32 #include <QCoreApplication>
       
    33 #include <XQSysInfo>
    33 
    34 
    34 #include <thumbnailmanager_qt.h>
    35 #include <thumbnailmanager_qt.h>
    35 #include <thumbnaildata.h>
    36 #include <thumbnaildata.h>
    36 #include <thumbnailobjectsource.h>
    37 #include <thumbnailobjectsource.h>
    37 
    38 
    38 #include "mpdetailssharedialog.h"
       
    39 #include "mptrace.h"
    39 #include "mptrace.h"
    40 
    40 
    41 const int KUndefined = -1;
    41 const int KUndefined = -1;
    42 const int KRecommendationCount = 2;
    42 const int KRecommendationCount = 2;
    43 
    43 
    44 MpQueryManager::MpQueryManager()
    44 MpQueryManager::MpQueryManager()
    45     : mManager(0),
    45     : mManager(0),
    46       mDownloadManager(0),
    46       mAlbumArtDownloader(0),
    47       mThumbnailManager(0)        
    47       mThumbnailManager(0),
       
    48       mDefaultRecommendationAlbumArt("qtg_large_album_art"),
       
    49       mRequestType(NoRequest),
       
    50       mRecommendationCount(0)
    48                                
    51                                
    49 {
    52 {
    50     TX_ENTRY
    53     TX_ENTRY
    51 
    54 
    52     QString privatePathQt( QCoreApplication::applicationDirPath() );
    55     QString privatePathQt( QCoreApplication::applicationDirPath() );
    54     QDir dir( privatePathQt );
    57     QDir dir( privatePathQt );
    55     QString newDir = "detailsview";
    58     QString newDir = "detailsview";
    56     bool res = dir.mkdir( newDir );
    59     bool res = dir.mkdir( newDir );
    57     TX_LOG_ARGS( "New dir creation result: " << res);
    60     TX_LOG_ARGS( "New dir creation result: " << res);
    58 
    61 
    59     // We're not handling a negative result for directory creation here,
    62     // TODO: Instead of writing the album art to a file, 
    60     // instead it will be escalated in DownloadFinished() method.
    63 	// then using Thumbnail Manager to convert it, etc. 
       
    64 	// have you considered just loading it directly into QPixmap? 
       
    65 	// QPixmap provides a loadFromData() that can load from QByteArray. 
       
    66 	// This would not only make the availability of the album art immediate, 
       
    67 	// but also save a lot of cleanup in file system, thumbnail manager, etc.    
    61     privatePathQt = privatePathQt + "/detailsview";
    68     privatePathQt = privatePathQt + "/detailsview";
    62     QString albumArt1( privatePathQt + "/albumOne.png" );
    69     QString albumArt1( privatePathQt + "/albumOne.png" );
    63     QString albumArt2( privatePathQt + "/albumTwo.png" );
    70     QString albumArt2( privatePathQt + "/albumTwo.png" );
    64     mRecommendationAlbumArtsName << albumArt1 << albumArt2;
    71     mRecommendationAlbumArtsName << albumArt1 << albumArt2;
    65     TX_LOG_ARGS( "recommendation album art names: " << mRecommendationAlbumArtsName );
    72     TX_LOG_ARGS( "recommendation album art names: " << mRecommendationAlbumArtsName );
    66 
    73 
    67     mManager = new QNetworkAccessManager( this );
    74     mManager = new QNetworkAccessManager( this );      
    68       
    75     mAlbumArtDownloader = new QNetworkAccessManager( this );    // TODO: check if we can only use mManager
    69     mDownloadManager = new QNetworkAccessManager( this );
       
    70     connect( mDownloadManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( DownloadFinished( QNetworkReply * ) ) );
       
    71     
       
    72     mThumbnailManager = new ThumbnailManager( this );
    76     mThumbnailManager = new ThumbnailManager( this );
    73     mThumbnailManager->setQualityPreference( ThumbnailManager::OptimizeForQuality );
    77     mThumbnailManager->setQualityPreference( ThumbnailManager::OptimizeForQuality );
    74     mThumbnailManager->setThumbnailSize( ThumbnailManager::ThumbnailSmall );
    78     mThumbnailManager->setThumbnailSize( ThumbnailManager::ThumbnailSmall );
    75     QObject::connect( mThumbnailManager, SIGNAL( thumbnailReady( QPixmap , void * , int , int ) ),
    79 
    76             this, SLOT( thumbnailReady( QPixmap , void * , int , int  ) ) );
       
    77     // TODO: Use the album art in provided by 10.1 wk16 platform. Current one is in the binary        
       
    78     mDefaultRecommendationAlbumArt = QPixmap( ":/mpdetailsviewicons/qtg_large_music_album.svg" );    
       
    79      
       
    80     TX_EXIT
    80     TX_EXIT
    81 }
    81 }
    82 
    82 
    83 MpQueryManager::~MpQueryManager()
    83 MpQueryManager::~MpQueryManager()
    84 {
    84 {
    85     TX_ENTRY
    85     TX_ENTRY
       
    86     reset();
    86     if ( mManager ) {
    87     if ( mManager ) {
    87        mManager->deleteLater();
    88        mManager->deleteLater();
    88      }
    89     }
    89     if ( mDownloadManager ) {
    90     if ( mAlbumArtDownloader ) {
    90        mDownloadManager->deleteLater();
    91        mAlbumArtDownloader->deleteLater();
    91     }
    92     }
    92     delete mThumbnailManager;
    93     if( mThumbnailManager ) {
       
    94         mThumbnailManager->deleteLater();
       
    95     }
    93     TX_EXIT
    96     TX_EXIT
    94 }
    97 }
    95 
    98 
    96 
    99 
    97 void MpQueryManager::clearNetworkReplies()
   100 void MpQueryManager::clearNetworkReplies()
    98 {
   101 {
       
   102     mRequestType = NoRequest; 
    99     disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );     
   103     disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );     
   100     TX_ENTRY_ARGS( "Reply count = " << mReplys.count() );    
   104     TX_ENTRY_ARGS( "Reply count = " << mReplys.count() );    
   101     for ( int i = 0; i < mReplys.count(); i++ ) {
   105     for ( int i = 0; i < mReplys.count(); ++i ) {
   102         QNetworkReply *reply = mReplys.at( i );
   106         QNetworkReply *reply = mReplys.at( i );
   103         disconnect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );        
   107         disconnect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );        
   104         if ( reply != NULL ) {
   108         if ( reply != NULL ) {
   105             reply->close();
   109             reply->close();
   106             reply->deleteLater();
   110             reply->deleteLater();
   107             reply = NULL;
   111             reply = NULL;
   108         }   
   112         }
   109     }
   113     }
   110     mReplys.clear();
   114     mReplys.clear();
   111     TX_EXIT
   115     TX_EXIT
   112 }
   116 }
   113 
   117 
   121     // TODO: country information handling, MCC
   125     // TODO: country information handling, MCC
   122     QString queryURI("http://api.music.ovi.com/1.0/ru/?");
   126     QString queryURI("http://api.music.ovi.com/1.0/ru/?");
   123     constructRequest( queryURI );
   127     constructRequest( queryURI );
   124     TX_LOG_ARGS( "queryURI : " << queryURI );
   128     TX_LOG_ARGS( "queryURI : " << queryURI );
   125     retrieveInformation( queryURI );
   129     retrieveInformation( queryURI );
       
   130     mRequestType = LocalStoreRequest;    
   126     TX_EXIT    
   131     TX_EXIT    
   127 }
   132 }
   128     
   133     
   129 void MpQueryManager::queryInspireMeItems(QString artist,QString album,QString title)
   134 void MpQueryManager::queryInspireMeItems(QString artist,QString album,QString title)
   130 {
   135 {
   131     TX_ENTRY    
   136     TX_ENTRY    
   132     mArtist=artist;
   137     mArtist=artist;
   133     mAlbum=album;
   138     mAlbum=album;
   134     mTitle=title;
   139     mTitle=title;
   135     // start querying inspire me items
   140     // start querying inspire me items
   136     QString queryRecommendation("http://api.music.ovi.com/1.0/gb/releases/recommend/?");
   141     QString queryRecommendation("http://api.music.ovi.com/1.0/" + mMusicStore + "/releases/recommend/?");
   137     constructRequest( queryRecommendation );
   142     constructRequest( queryRecommendation );
   138     TX_LOG_ARGS( "queryRecommendation : " << queryRecommendation );
   143 	// TODO: Store the token to a cenrep key	
       
   144     // TODO: Tokens change per new ovi api release. 
       
   145 	//       Need to figure out a way to get them updated on the fly
       
   146     queryRecommendation.append("&Token=03574704-e3d1-4466-9691-e0b34c7abfff");
       
   147 
       
   148     TX_LOG_ARGS( queryRecommendation );
   139     retrieveInformation( queryRecommendation );
   149     retrieveInformation( queryRecommendation );
       
   150     mRequestType = InspireMeItemsMetadataRequest;
   140     TX_EXIT
   151     TX_EXIT
   141 }
   152 }
   142 
   153 
   143 void MpQueryManager::clearRecommendations()
   154 void MpQueryManager::clearRecommendations()
   144 {
   155 {
   145     TX_ENTRY    
   156     TX_ENTRY
       
   157     mRecommendationCount = 0;
   146     mDownloadedAlbumArts = 0;
   158     mDownloadedAlbumArts = 0;
   147     mAlbumArtsReadyCount = 0;
   159     mAlbumArtsReadyCount = 0;
   148     for ( int i = 0; i < KRecommendationCount; i++ ) {
   160     mRecommendationSongs.clear();
   149        mRecommendationSongs.clear();
   161     mRecommendationArtists.clear();
   150        mRecommendationArtists.clear();
   162     mRecommendationAlbumArtsLink.clear();
   151        mRecommendationAlbumArtsLink.clear();
   163     mRecommendationAlbumArtsMap.clear();
   152        mRecommendationAlbumArtsMap.clear();      
   164     for ( int i = 0; i < mRecommendationAlbumArtsName.count(); ++i ) {
   153        QFile file( mRecommendationAlbumArtsName.at( i ) );        
   165        QFile file( mRecommendationAlbumArtsName.at( i ) );
   154        if ( file.exists() ) {
   166        TX_LOG_ARGS( "File " << file.fileName() << " exists: " << file.exists() );
   155            if ( file.remove() ) {
   167        if ( file.exists() && file.remove() ) {
   156                TX_LOG_ARGS( "File removed - " << file.fileName() );
   168             TX_LOG_ARGS( "File " << file.fileName() << " removed");
   157            }
       
   158            else {
       
   159                TX_LOG_ARGS( "Cannot remove file - " << file.fileName() );
       
   160            }
       
   161        } else {
       
   162            TX_LOG_ARGS( "File doesn't exist - " << file.fileName() );
       
   163        }
   169        }
   164     }
   170     }
   165     TX_EXIT    
   171     TX_EXIT    
   166 }
   172 }
   167 
   173 
   168 /*!
   174 
   169  Return recommendation songs
   175 
   170  */
   176 /*!
   171 QStringList MpQueryManager::recommendationSongs()
   177  Returns the Local Music Store(if available) to be used while querying "Inspire Me" Items
   172 {
   178  */
   173     TX_LOG  
   179 void MpQueryManager::queryLocalMusicStore()
   174     return mRecommendationSongs;
   180 {
       
   181     TX_ENTRY
       
   182     QString imsi,mcc;
       
   183 
       
   184     XQSysInfo sysInfo( this );
       
   185     imsi = sysInfo.imsi();
       
   186     mcc= imsi.left(3);
       
   187     TX_LOG_ARGS( "mcc : " << mcc );
       
   188     
       
   189     QString queryLocalMusicStore("http://api.music.cq1.brislabs.com/1.0/?mcc=" + mcc + "&token=06543e34-0261-40a4-a03a-9e09fe110c1f");
       
   190     TX_LOG_ARGS( "queryLocalMusicStore : " << queryLocalMusicStore );
       
   191     retrieveInformation( queryLocalMusicStore );
       
   192     mRequestType = LocalStoreRequest;
       
   193     TX_EXIT
       
   194 }
       
   195 
       
   196 
       
   197 int MpQueryManager::recommendationsCount() const
       
   198 {
       
   199     TX_LOG_ARGS ("count: " << mRecommendationSongs.count());
       
   200     return mRecommendationSongs.count();
       
   201 }
       
   202 
       
   203 QString MpQueryManager::recommendedSong(int index) const
       
   204 {
       
   205     QString result;
       
   206     if( (0 <= index) && (index < mRecommendationSongs.count())) {
       
   207         result = mRecommendationSongs.at(index);
       
   208     }
       
   209     TX_LOG_ARGS ("recommendedSong: " << result);    
       
   210     return result; 
   175 }
   211 }
   176 
   212 
   177 /*!
   213 /*!
   178  Return recommendation artists
   214  Return recommendation artists
   179  */
   215  */
   180 QStringList MpQueryManager::recommendationArtists()
   216 QString MpQueryManager::recommendedArtist(int index) const
   181 {
   217 {
   182     TX_LOG  
   218     QString result;
   183     return mRecommendationArtists;
   219     if( (0 <= index) && (index < mRecommendationArtists.count())) {
   184 }
   220         result = mRecommendationArtists.at(index);
   185 
   221     }
   186 /*!
   222     TX_LOG_ARGS ("recommendedArtist: " << result);    
   187  Return recommendation album arts links
   223     return result;
   188  */
       
   189 QStringList MpQueryManager::recommendationAlbumArtsLink()
       
   190 {
       
   191     TX_LOG  
       
   192     return mRecommendationAlbumArtsLink;
       
   193 }
       
   194 
       
   195 /*!
       
   196  Return map of name and pixmap
       
   197  */
       
   198 QMap<QString, QPixmap>  MpQueryManager::recommendationAlbumArtsMap()
       
   199 {
       
   200     TX_LOG  
       
   201     return mRecommendationAlbumArtsMap;
       
   202 }
       
   203 
       
   204 /*!
       
   205  Insert one uri & pixmap item into map
       
   206  */
       
   207 void MpQueryManager::insertMapItem( const QString &uri, const QPixmap &pixmap )
       
   208 {
       
   209     TX_ENTRY_ARGS( "Map Item URI: " << uri );
       
   210     mRecommendationAlbumArtsMap.insert( uri, pixmap );
       
   211     TX_EXIT
       
   212 }
   224 }
   213 
   225 
   214 /*!
   226 /*!
   215  Slot to call when getting response
   227  Slot to call when getting response
   216  */
   228  */
   219     TX_ENTRY
   231     TX_ENTRY
   220     QString errorStr;
   232     QString errorStr;
   221     int errorLine;
   233     int errorLine;
   222     int errorColumn;
   234     int errorColumn;
   223     bool parsingSuccess;
   235     bool parsingSuccess;
   224     
   236         
   225     if ( reply->error() == QNetworkReply::NoError )
   237     if ( reply->error() != QNetworkReply::NoError ) {
   226     {
   238 		TX_LOG_ARGS("reply->error(): " << reply->error());
   227         parsingSuccess = mDomDocument.setContent( reply, true, &errorStr, &errorLine, &errorColumn );
   239         signalError();
   228         if ( parsingSuccess ) {
   240         return;
   229             handleParsedXML();  //CodeScanner throws a warning mis-interpreting the trailing 'L' to be a leaving function.
   241     }
   230         } else {
   242         
   231             // TODO: agree on error handling            
   243     parsingSuccess = mDomDocument.setContent( reply, true, &errorStr, &errorLine, &errorColumn );
   232             TX_LOG_ARGS( "XML parsing error" );
   244     if ( !parsingSuccess ) {
   233         }
   245 		TX_LOG_ARGS("Parsing Received Content Failed");
   234     }
   246         signalError();
   235     else
   247         return;
   236     {
   248     }
   237         // TODO: agree on error handling
   249 
   238         TX_LOG_ARGS( "Network error in retrieving Information" );
   250     handleParsedXML();  //CodeScanner throws a warning mis-interpreting the trailing 'L' to be a leaving function.
   239         emit networkError();
   251     
   240     }
   252     mReplys.removeAll(reply); // remove it so that we wont process it again
   241     TX_EXIT
   253     reply->deleteLater(); // make sure reply is deleted, as we longer care about it
       
   254     
       
   255     TX_EXIT
       
   256 }
       
   257 
       
   258 void MpQueryManager::signalError()
       
   259 {
       
   260     TX_ENTRY; 
       
   261     switch(mRequestType) {
       
   262         case InspireMeItemsMetadataRequest:
       
   263             TX_LOG_ARGS("emit inspireMeItemsRetrievalError");
       
   264             emit inspireMeItemsRetrievalError();
       
   265             break;
       
   266         case InspireMeItemsAlbumArtRequest:
       
   267             TX_LOG_ARGS("Warning: InspireMeItemsAlbumArtRequestError, will keep using the default AA icon");            
       
   268             break;    
       
   269         case LocalStoreRequest:
       
   270             TX_LOG_ARGS("emit localMusicStoreRetrievalError");            
       
   271             emit localMusicStoreRetrievalError();
       
   272             break;
       
   273         case NoRequest:   
       
   274         default:
       
   275             TX_LOG_ARGS("Warning!! Possible uninitialized mRequestType");            
       
   276             break;                                 
       
   277     }
       
   278     TX_EXIT    
   242 }
   279 }
   243 
   280 
   244 /*!
   281 /*!
   245  Slot to call when there is network error
   282  Slot to call when there is network error
   246  */
   283  */
   247 void MpQueryManager::retrieveInformationNetworkError( QNetworkReply::NetworkError error )
   284 void MpQueryManager::retrieveInformationNetworkError( QNetworkReply::NetworkError error )
   248 {
   285 {
       
   286     TX_ENTRY_ARGS( "Network error for retrieving Information" << error);    
   249     // TODO: agree on error handling
   287     // TODO: agree on error handling
       
   288 
   250 	Q_UNUSED(error)
   289 	Q_UNUSED(error)
   251     TX_ENTRY_ARGS( "Network error for retrieving Information" << error);
   290 
       
   291     disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );     
       
   292     signalError();
   252     TX_EXIT
   293     TX_EXIT
   253 }
   294 }
   254 
   295 
   255 /*!
   296 /*!
   256  Slot to call when there is ssl error
   297  Slot to call when there is ssl error
   257  */
   298  */
   258 void MpQueryManager::retrieveInformationSslErrors( const QList<QSslError> &/*error*/ )
   299 void MpQueryManager::retrieveInformationSslErrors( const QList<QSslError> &/*error*/ )
   259 {   
   300 {
   260     // TODO: agree on error handling
   301     // TODO: agree on error handling
   261     TX_ENTRY_ARGS( "SSL error for retrieving Information" );
   302     TX_ENTRY_ARGS( "SSL error for retrieving Information" );
       
   303     disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );     
       
   304     signalError();    
   262     TX_EXIT
   305     TX_EXIT
   263 }
   306 }
   264 
   307 
   265 /*!
   308 /*!
   266  Slot to call when downloading finished
   309  Slot to call when downloading finished
   267  */
   310  */
   268 void MpQueryManager::DownloadFinished( QNetworkReply* reply )
   311 void MpQueryManager::albumArtDownloaded( QNetworkReply* reply )
   269 {
   312 {
   270     TX_ENTRY_ARGS( "mDownloadedAlbumArts = " << mDownloadedAlbumArts );
   313     TX_ENTRY_ARGS( "mDownloadedAlbumArts = " << mDownloadedAlbumArts );
   271     if ( reply->error() == QNetworkReply::NoError )
   314     TX_ENTRY_ARGS( "QNetworkReply obj " << reply);
   272         {
   315     
       
   316     // It seems we get several finished signals for the same reply obj
       
   317     // do nothing if we get a second signal
       
   318     if( mReplys.indexOf(reply) == -1 ) {
       
   319         TX_LOG_ARGS("Warning: QNetworkReply AA request may have been processed in previous call: " << reply );
       
   320         return;
       
   321     }
       
   322         
       
   323     if ( reply->error() == QNetworkReply::NoError ) {
       
   324         
   273         QString fileName = mRecommendationAlbumArtsName.at( mDownloadedAlbumArts );
   325         QString fileName = mRecommendationAlbumArtsName.at( mDownloadedAlbumArts );
   274         QByteArray imageData = reply->readAll();
   326         QByteArray imageData = reply->readAll();
   275         bool ret = writeImageToFile( imageData, fileName );
   327         bool ret = writeImageToFile( imageData, fileName );
   276 
   328 
   277         // If file writing went OK, emit a signal with the real filename
   329         // If file writing went OK, emit a signal with the real filename
   278         // If it failed, use empty filename (since file was removed in any case)
   330         // If it failed, use empty filename (since file was removed in any case)
   279         if ( ret )
   331         if ( ret ) {
   280             {
   332             // TODO: If album album arts come in different order than they have been asked,
       
   333             // then inspire me items will use swapped album arts. Correct
   281             setAlbumArtUri( mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), 
   334             setAlbumArtUri( mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), 
   282                             mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) );
   335                             mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) );
   283             }
   336         }
   284         else
   337         else {
   285             {
       
   286             setAlbumArtUri(mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), "");
   338             setAlbumArtUri(mRecommendationAlbumArtsLink.at( mDownloadedAlbumArts), "");
   287             }
   339         }
   288         }
   340         ++mDownloadedAlbumArts;
   289     else
   341         mReplys.removeAll(reply); // remove it so that we wont process it again
   290     {
   342         reply->deleteLater(); // make sure reply is deleted, as we longer care about it
   291         TX_LOG_ARGS( "Downloading album art failed!" );
   343     }
   292         emit networkError();
   344     else {
   293     }
   345         TX_LOG_ARGS( "Error: Downloading album art failed! Will keep using the default AA" );
   294     
   346     }
   295     mDownloadedAlbumArts++;
   347     
       
   348     if( mDownloadedAlbumArts == mRecommendationCount) {
       
   349         // no need to be informed anymore
       
   350         mAlbumArtDownloader->disconnect(this);
       
   351     }
       
   352     
   296     TX_EXIT
   353     TX_EXIT
   297 }
   354 }
   298 
   355 
   299 /*!
   356 /*!
   300  Write the image data to a file with the given filename.
   357  Write the image data to a file with the given filename.
   301  If writing operation fails for any reason (e.g. OOD),
   358  If writing operation fails for any reason (e.g. OOD),
   302  returns false, otherwise true.
   359  returns false, otherwise true.
   303  */
   360  */
   304 bool MpQueryManager::writeImageToFile(const QByteArray &aImageData, const QString &aImageFileName )
   361 bool MpQueryManager::writeImageToFile(const QByteArray &aImageData, const QString &aImageFileName )
   305     {
   362 {
   306     bool ret( false );
   363     bool ret( false );
   307     TX_ENTRY_ARGS( "imagefile: " << aImageFileName );
   364     TX_ENTRY_ARGS( "imagefile: " << aImageFileName );
   308     if ( aImageFileName.isEmpty() )
   365     if ( aImageFileName.isEmpty() ) {
   309         {
       
   310         TX_LOG_ARGS( "Only store two album arts" );
   366         TX_LOG_ARGS( "Only store two album arts" );
   311         }
   367     }
   312     else
   368     else {
   313         {
       
   314         QFile file( aImageFileName );
   369         QFile file( aImageFileName );
   315 
   370         if ( !file.open( QIODevice::ReadWrite ) ) {
   316         if ( !file.open( QIODevice::ReadWrite ) )
       
   317             {
       
   318             TX_LOG_ARGS( "Unable to open file" );
   371             TX_LOG_ARGS( "Unable to open file" );
   319             }
   372         }
   320         else
   373         else {
   321             {
       
   322             qint64 writtenBytes = file.write( aImageData );
   374             qint64 writtenBytes = file.write( aImageData );
   323 
       
   324             // Verify file write status
   375             // Verify file write status
   325             if ( writtenBytes < aImageData.size() )
   376             if ( writtenBytes < aImageData.size() ) {
   326                 {
       
   327                 // If write succeeded only partially, or completely failed,
   377                 // If write succeeded only partially, or completely failed,
   328                 // remove the file from filesystem to remove risk of corruption
   378                 // remove the file from filesystem to remove risk of corruption
   329                 TX_LOG_ARGS( "Wrote only " << writtenBytes << " bytes, aborting operation!" );
   379                 TX_LOG_ARGS( "Wrote only " << writtenBytes << " bytes, aborting operation!" );
   330                 file.close();
   380                 file.close();
   331                 QFile::remove( mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) );
   381                 QFile::remove( mRecommendationAlbumArtsName.at( mDownloadedAlbumArts ) );
   332                 }
   382             }
   333             else
   383             else {
   334                 {
       
   335                 // If write fully succeeded, flush contents
   384                 // If write fully succeeded, flush contents
   336                 TX_LOG_ARGS( "Wrote all the bytes (" << writtenBytes << "), flushing and closing!");
   385                 TX_LOG_ARGS( "Wrote all the bytes (" << writtenBytes << "), flushing and closing!");
   337                 file.flush();
   386                 file.flush();
   338                 file.close();
   387                 file.close();
   339                 ret = true;
   388                 ret = true;
   340                 }
       
   341             }
   389             }
   342         }
   390         }
       
   391     }
   343     TX_LOG_ARGS( "Returning with value: " << ret );
   392     TX_LOG_ARGS( "Returning with value: " << ret );
   344     TX_EXIT
   393     TX_EXIT
   345     return ret;
   394     return ret;
   346     }
   395 }
   347 
   396 
   348 /*!
   397 /*!
   349  Get Atom response from Ovi server based on query
   398  Get Atom response from Ovi server based on query
   350  */
   399  */
   351 void MpQueryManager::retrieveInformation( const QString &urlEncoded )
   400 void MpQueryManager::retrieveInformation( const QString &urlEncoded )
   352 {
   401 {
   353     TX_ENTRY_ARGS( "urlEconded = " << urlEncoded)
   402     TX_ENTRY_ARGS( "urlEconded = " << urlEncoded)
   354     connect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );    
   403     connect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ), Qt::UniqueConnection );
   355     QNetworkReply *reply = mManager->get( QNetworkRequest( QUrl( urlEncoded ) ) );
   404     QNetworkReply *reply = mManager->get( QNetworkRequest( QUrl( urlEncoded ) ) );
   356     mReplys.append( reply );
   405     mReplys.append( reply );
   357     
   406     
   358     connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );
   407     connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );
   359     connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) );
   408     connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) );
   367 void MpQueryManager::handleParsedXML()
   416 void MpQueryManager::handleParsedXML()
   368 {
   417 {
   369     TX_ENTRY
   418     TX_ENTRY
   370     QDomElement rootElement = mDomDocument.documentElement();
   419     QDomElement rootElement = mDomDocument.documentElement();
   371     
   420     
   372     if ( rootElement.attribute( "type" ) == "search" ) {
   421     if ( rootElement.attribute( "type" ) == "recommendedTracks" ) {
   373         TX_LOG_ARGS( "URI response" )
   422         TX_LOG_ARGS( "Recommendation response" )
   374         QString result;
       
   375         QDomElement entry = rootElement.firstChildElement( "entry" );
   423         QDomElement entry = rootElement.firstChildElement( "entry" );
   376         while ( !entry.isNull() )
   424         mRecommendationCount = 0;
   377         {
   425         while ( !entry.isNull() && mRecommendationCount < KRecommendationCount ) {
   378             if ( entry.attribute( "type" ) == "musictrack" ) {
   426             if ( entry.attribute( "type" ) == "musictrack" ) {
   379                 QDomElement link = entry.firstChildElement( "link" );
   427                 QDomElement link = entry.firstChildElement( "link" );
   380                 while ( !link.isNull() )
   428                 while ( !link.isNull() ) {
   381                 {
       
   382                     if ( link.attribute( "rel" ) == "alternate"
       
   383                         && link.attribute( "type" ) == "text/html" ) {
       
   384                         result = link.attribute( "href" );
       
   385                     }
       
   386                     link = link.nextSiblingElement( "link" );
       
   387                 }
       
   388             }
       
   389             entry = entry.nextSiblingElement( "entry" );
       
   390         }
       
   391 		// Signal that the url was received. Might be empty string.
       
   392 		emit searchUrlRetrieved( result );
       
   393     } else if ( rootElement.attribute( "type" ) == "recommendedTracks" ) {
       
   394         TX_LOG_ARGS( "Recommendation response" )
       
   395         QDomElement entry = rootElement.firstChildElement( "entry" );
       
   396         QNetworkReply *reply;
       
   397         int count = 0;
       
   398         while ( !entry.isNull() && count < KRecommendationCount )
       
   399         {
       
   400             if ( entry.attribute( "type" ) == "musictrack" ) {
       
   401                 QDomElement link = entry.firstChildElement( "link" );
       
   402                 while ( !link.isNull() )
       
   403                 {
       
   404                     if ( link.attribute( "title" ) == "albumart100" ) {
   429                     if ( link.attribute( "title" ) == "albumart100" ) {
   405                         mRecommendationAlbumArtsLink.append( link.attribute( "href" ) );
   430                         mRecommendationAlbumArtsLink.append( link.attribute( "href" ) );
       
   431                         // TODO: This may get called twice for one inspire me item. Investigate why
       
   432                         mRecommendationAlbumArtsMap.insert( link.attribute( "href" ), mDefaultRecommendationAlbumArt );                      
   406                         break;
   433                         break;
   407                     } else {
   434                     }
       
   435                     else {
   408                         link = link.nextSiblingElement( "link" );
   436                         link = link.nextSiblingElement( "link" );
   409                     }                    
   437                     }
   410                 }
   438                 }
   411                 QDomElement metadata = entry.firstChildElement( "metadata" );
   439                 QDomElement metadata = entry.firstChildElement( "metadata" );
   412                 mRecommendationSongs.append( metadata.firstChildElement( "name" ).text() );
   440                 mRecommendationSongs.append( metadata.firstChildElement( "name" ).text() );
   413                 mRecommendationArtists.append( metadata.firstChildElement( "primaryartist" ).text() );
   441                 mRecommendationArtists.append( metadata.firstChildElement( "primaryartist" ).text() );
   414                 count++;
   442                 ++mRecommendationCount;
   415             }
   443             }
   416             entry = entry.nextSiblingElement( "entry" );
   444             entry = entry.nextSiblingElement( "entry" );
   417         }          
   445         }
   418         
   446  
   419         for (int i = 0; i < KRecommendationCount; i++ ) {
   447         emit inspireMeItemsMetadataRetrieved();
       
   448 
       
   449         QNetworkReply *reply = 0;
       
   450         // we need to channel the retrieved album arts to albumArtDownloaded slot only
       
   451         disconnect( mManager, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( retrieveInformationFinished( QNetworkReply * ) ) );        
       
   452         for (int i = 0; i < mRecommendationCount; i++ ) {
   420             TX_LOG_ARGS( "song name: " << mRecommendationSongs.at(i) );
   453             TX_LOG_ARGS( "song name: " << mRecommendationSongs.at(i) );
   421             TX_LOG_ARGS( "Artist name: " << mRecommendationArtists.at(i) );
   454             TX_LOG_ARGS( "Artist name: " << mRecommendationArtists.at(i) );
   422             TX_LOG_ARGS( "Album art link: " << mRecommendationAlbumArtsLink.at(i) );
   455             TX_LOG_ARGS( "Album art link: " << mRecommendationAlbumArtsLink.at(i) );
   423             
   456             mRequestType = InspireMeItemsAlbumArtRequest;
   424             if ( mRecommendationAlbumArtsLink.at( i ).contains( "http", Qt::CaseInsensitive ) ) {
   457             if ( mRecommendationAlbumArtsLink.at( i ).contains( "http", Qt::CaseInsensitive ) ) {
   425                 reply = mDownloadManager->get( QNetworkRequest( QUrl( mRecommendationAlbumArtsLink.at(i) ) ) );
   458                 reply = mAlbumArtDownloader->get( QNetworkRequest( QUrl( mRecommendationAlbumArtsLink.at(i) ) ) );
   426                 mReplys.append( reply );
   459                 mReplys.append( reply );
   427                 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );
   460                 connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( retrieveInformationNetworkError( QNetworkReply::NetworkError ) ) );
   428                 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) );
   461                 connect( reply, SIGNAL( sslErrors( QList<QSslError> ) ), this, SLOT( retrieveInformationSslErrors( QList<QSslError> ) ) );
   429             }             
   462             }
   430         }
   463         }
   431     } else {
   464        // we have queried for album arts for inspire me items. Now, time to wait for a response        
       
   465        connect( mAlbumArtDownloader, SIGNAL( finished( QNetworkReply * ) ), this, SLOT( albumArtDownloaded( QNetworkReply * ) ) );
       
   466 
       
   467     }
       
   468     else if ( rootElement.attribute( "type" ) == "storeList" ) {
       
   469 		TX_LOG_ARGS( "Music Store List" )
       
   470         QDomElement entry = rootElement.firstChildElement( "workspace" );
       
   471         QString previousMusicStore = mMusicStore;
       
   472         mMusicStore = entry.attribute( "countryCode" );
       
   473         if(!mMusicStore.isEmpty()) {
       
   474             bool musicStoreUpdated = (previousMusicStore != mMusicStore);
       
   475         	TX_LOG_ARGS("Music Store" << mMusicStore );
       
   476             emit localMusicStoreRetrieved(musicStoreUpdated);
       
   477         }
       
   478         else {
       
   479             emit localMusicStoreRetrievalError();   
       
   480         }		
       
   481     }
       
   482     else {
   432         TX_LOG_ARGS( "Not supported response" )
   483         TX_LOG_ARGS( "Not supported response" )
   433     }
   484     }
   434     TX_EXIT
   485     TX_EXIT
   435 }
   486 }
   436 
   487 
       
   488 void MpQueryManager::clearThumbnails()
       
   489 {
       
   490     TX_ENTRY
       
   491     for(int i = 0; i < mThumbnailRequests.count(); ++i ) {
       
   492         mThumbnailManager->cancelRequest(mThumbnailRequests.at(i));
       
   493     }
       
   494     mThumbnailRequests.clear();    
       
   495     for(int i = 0; i < mRecommendationAlbumArtsName.count(); ++i) {
       
   496         mThumbnailManager->deleteThumbnails(mRecommendationAlbumArtsName.at(i)); // async, returns immidiately
       
   497     }
       
   498     TX_EXIT        
       
   499 }
       
   500 
       
   501 void MpQueryManager::reset()
       
   502 {
       
   503     TX_ENTRY
       
   504     mManager->disconnect(this);
       
   505     mAlbumArtDownloader->disconnect(this);
       
   506     mThumbnailManager->disconnect(this);
       
   507     clearNetworkReplies();
       
   508     clearRecommendations();
       
   509     clearThumbnails();
       
   510     mRecommendationAlbumArtsMap.clear();
       
   511     TX_EXIT
       
   512 }
       
   513     
   437 /*!
   514 /*!
   438  Construct the query for fetching URI & recommendations
   515  Construct the query for fetching URI & recommendations
   439  */
   516  */
   440 void MpQueryManager::constructRequest( QString &uri )
   517 void MpQueryManager::constructRequest( QString &uri )
   441 {
   518 {
   466 {
   543 {
   467     TX_ENTRY
   544     TX_ENTRY
   468     QString str;
   545     QString str;
   469     if ( keys.length() != values.length() ) {
   546     if ( keys.length() != values.length() ) {
   470         TX_LOG_ARGS( "Error: keys length is not equal to values length" ); 
   547         TX_LOG_ARGS( "Error: keys length is not equal to values length" ); 
   471     } else {
   548     }
       
   549     else {
   472         for ( int i = 0; i < keys.length(); i++ ) {
   550         for ( int i = 0; i < keys.length(); i++ ) {
   473             QString tValue = values.at( i );
   551             QString tValue = values.at( i );
   474             if ( 0 != tValue.length() )
   552             if ( 0 != tValue.length() ) {
   475             {
       
   476                 str += keys.at( i ) + "=" + values.at( i ) + "&";
   553                 str += keys.at( i ) + "=" + values.at( i ) + "&";
   477             }
   554             }
   478         }
   555         }
   479     }
   556     }
   480     TX_EXIT
   557     TX_EXIT
   484 /*!
   561 /*!
   485  Sets recommendation album art
   562  Sets recommendation album art
   486 */
   563 */
   487 void MpQueryManager::setAlbumArtUri( const QString &albumArtUri, const QString &albumArtName )
   564 void MpQueryManager::setAlbumArtUri( const QString &albumArtUri, const QString &albumArtName )
   488 {
   565 {
       
   566     // TODO: rename this function. Doing too many things
   489     TX_ENTRY_ARGS( "albumArtUri = " << albumArtUri )
   567     TX_ENTRY_ARGS( "albumArtUri = " << albumArtUri )
   490     TX_LOG_ARGS( "albumArtName = " << albumArtName )
   568     TX_LOG_ARGS( "albumArtName = " << albumArtName )
   491     if ( !albumArtUri.isEmpty() && !albumArtName.isEmpty() ) {
   569     if ( !albumArtUri.isEmpty() && !albumArtName.isEmpty() ) {
       
   570         // TODO: this is no good to pass the address of the albumArtUri. It is an item in the list, which can cleaned
   492         int id = mThumbnailManager->getThumbnail( albumArtName, reinterpret_cast<void *>( const_cast<QString *>( &albumArtUri ) ) );
   571         int id = mThumbnailManager->getThumbnail( albumArtName, reinterpret_cast<void *>( const_cast<QString *>( &albumArtUri ) ) );
   493         if ( id == KUndefined ) {
   572         if ( id == KUndefined ) {
   494             // Request failed. Set default album art.
   573             // Request failed. Set default album art
   495             insertMapItem( albumArtUri, mDefaultRecommendationAlbumArt );
   574             mRecommendationAlbumArtsMap.insert( albumArtUri, mDefaultRecommendationAlbumArt );
       
   575         }
       
   576         else {
       
   577             // Async request went throu
       
   578             TX_LOG_ARGS("Request to thumbnail manager made. Id: " << id)
       
   579             mThumbnailRequests.append(id);
       
   580             mThumbnailManager->disconnect( this ); // to prevent multiple same connections with thumbnailmanager
       
   581             QObject::connect( mThumbnailManager, SIGNAL( thumbnailReady( QPixmap , void * , int , int ) ),
       
   582             this, SLOT( thumbnailReady( QPixmap , void * , int , int  ) ) );
   496         }
   583         }
   497     }
   584     }
   498     else {
   585     else {
   499         // No album art uri. Set default album art.
   586         // No album art uri. Set default album art.
   500         insertMapItem( albumArtUri, mDefaultRecommendationAlbumArt );
   587         mRecommendationAlbumArtsMap.insert( albumArtUri, mDefaultRecommendationAlbumArt );
   501     }
   588     }
   502     TX_EXIT
   589     TX_EXIT
   503 }
   590 }
   504 
   591 
   505 /*!
   592 /*!
   506  Slot to handle the recommendation album art 
   593  Slot to handle the recommendation album art 
   507 */
   594 */
   508 void MpQueryManager::thumbnailReady(
   595 void MpQueryManager::thumbnailReady(
   509         const QPixmap& pixmap,
   596         const QPixmap pixmap,
   510         void *data,
   597         void *data,
   511         int /*id*/,
   598         int id,
   512         int error  )
   599         int error  )
   513 {
   600 {
   514     TX_ENTRY
   601     TX_ENTRY
   515     // TODO: Hkn: use qobject_cast
   602 
       
   603     if( mThumbnailRequests.indexOf(id) == -1 ) {
       
   604         TX_LOG_ARGS("Warning: some old thumbnail request from previous song. Ignoring")
       
   605         return;
       
   606     }
       
   607     
       
   608     // TODO: Using data from array, which can be reset. There must be a safer way    
   516     QString uri = *( reinterpret_cast<QString *>( data ) );
   609     QString uri = *( reinterpret_cast<QString *>( data ) );
   517     TX_LOG_ARGS( "Uri: " << uri );
   610     TX_LOG_ARGS( "Uri: " << uri );
   518     
   611     
   519     if ( error == 0 ) {
   612     if ( error == 0 ) {
   520         TX_LOG_ARGS( "album art link: " << uri );
   613         TX_LOG_ARGS( "album art link: " << uri );
   521         insertMapItem( uri, pixmap );
   614         mRecommendationAlbumArtsMap.insert( uri, HbIcon(QIcon(pixmap)) );
   522     } else {
   615     }
   523         insertMapItem( uri, mDefaultRecommendationAlbumArt );
   616     else {
   524     }
   617         mRecommendationAlbumArtsMap.insert( uri, mDefaultRecommendationAlbumArt );        
   525     if(++mAlbumArtsReadyCount == KRecommendationCount) {
   618     }
   526         emit recommendationAlbumArtsReady();
   619 
   527     }    
   620     emit inspireMeItemAlbumArtReady();    
   528     TX_EXIT
   621     TX_EXIT
   529 }
   622 }
       
   623 
       
   624 bool MpQueryManager::isLocalMusicStore() const
       
   625 {
       
   626     TX_LOG_ARGS( "isLocalMusicStore = " << !mMusicStore.isEmpty() )
       
   627     return !mMusicStore.isEmpty();
       
   628 }
       
   629 
       
   630 HbIcon MpQueryManager::recommendedAlbumArt(int index) const
       
   631 {
       
   632     TX_LOG_ARGS( "index = " << index )
       
   633     return mRecommendationAlbumArtsMap.value( mRecommendationAlbumArtsLink.at( index ) );
       
   634 }