--- 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();
}