Commit c0b31f1e authored by Sven Krohlas's avatar Sven Krohlas
Browse files

Use the context info applet to show further infos about a selected item

An artist might be handy to give it a better look, but the functionality
is there and doesn't look that bad. It shows the contents of an album
including cover, artist search, add to cart and preview links.

BUG:288807
FIXED-IN:2.7
parent 8a0e1f66
......@@ -5,6 +5,7 @@ Amarok ChangeLog
VERSION 2.7-Beta 1
FEATURES:
* Amazon store: It is now possible to add items to your shopping cart using amarok:// URLs.
* Amazon store: Use the context info applet to show further infos about a selected item.
CHANGES:
* Last.fm Skip button removed; Last.fm API no longer provides it. (BR 305576)
......
/****************************************************************************************
* Copyright (c) 2012 Sven Krohlas <sven@getamarok.com> *
* *
* This program is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 2 of the License, or (at your option) any later *
* version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
#include "AmazonInfoParser.h"
#include "Amazon.h"
#include "AmazonConfig.h"
#include "core/interfaces/Logger.h"
#include "core/support/Components.h"
#include <QDomDocument>
#include <QTemporaryFile>
void
AmazonInfoParser::getInfo( Meta::ArtistPtr artist )
{
// atm this should not be called from anywhere
Q_UNUSED( artist );
}
void
AmazonInfoParser::getInfo( Meta::AlbumPtr album )
{
showLoading( i18n( "Loading album info..." ) );
Meta::AmazonAlbum *amazonAlbum = dynamic_cast<Meta::AmazonAlbum *>( album.data() );
if( !amazonAlbum )
return;
QString urlString;
urlString += MP3_MUSIC_STORE_HOST;
urlString += "/?apikey=";
urlString += MP3_MUSIC_STORE_KEY;
urlString += "&Player=amarok&Location=";
urlString += AmazonConfig::instance()->country();
urlString += "&method=LoadAlbum";
urlString += "&ASIN=" + amazonAlbum->asin();
QTemporaryFile tempFile;
tempFile.setAutoRemove( false ); // file must be removed later
if( !tempFile.open() )
{
Amarok::Components::logger()->longMessage( i18n( "<b>MP3 Music Store</b><br/><br/>Error: Unable to write temporary file. :-(" ) );
return;
}
KIO::FileCopyJob *requestJob = KIO::file_copy( urlString, KUrl( tempFile.fileName() ), 0700 , KIO::HideProgressInfo | KIO::Overwrite );
connect( requestJob, SIGNAL( result( KJob* ) ), this, SLOT( albumInfoDownloadComplete( KJob* ) ) );
requestJob->start();
}
void
AmazonInfoParser::getInfo( Meta::TrackPtr track )
{
// atm this should not be called from anywhere
Q_UNUSED( track );
}
void
AmazonInfoParser::showFrontPage()
{
// TODO: show some stuff here. recommendations? charts?
QString contextHtml;
emit( info( contextHtml ) );
}
void
AmazonInfoParser::albumInfoDownloadComplete( KJob *requestJob )
{
if( requestJob->error() )
{
Amarok::Components::logger()->longMessage( i18n( "<b>MP3 Music Store</b><br/><br/>Error: Querying MP3 Music Store database failed. :-(" ) );
debug() << requestJob->errorString();
requestJob->deleteLater();
return;
}
QString tempFileName;
KIO::FileCopyJob *job = dynamic_cast<KIO::FileCopyJob*>( requestJob );
if( job )
tempFileName = job->destUrl().toLocalFile();
QString contextHtml;
QDomDocument responseDocument;
QFile responseFile( tempFileName );
if( !responseFile.open( QIODevice::ReadOnly ) )
{
debug() << "ERROR opening temp file";
QFile::remove( tempFileName );
return;
}
QString errorMsg;
int errorLine;
int errorColumn;
if( !responseDocument.setContent( &responseFile, false, &errorMsg, &errorLine, &errorColumn ) ) // parse error
{
debug() << responseDocument.toString();
debug() << "Parse ERROR";
debug() << "Message:" << errorMsg;
debug() << "Line:" << errorLine;
debug() << "Column:" << errorColumn;
// let's keep the temp file in case of an error
//QFile::remove( m_tempFileName );
return;
}
QString trackAsin, albumAsin, albumPrice;
QString artist, albumTitle, trackTitle;
QString trackPrice, imgUrl;
QString addToCartUrl, searchUrl;
QUrl playableUrl;
QDomNodeList albumItemsList = responseDocument.documentElement().firstChildElement( QLatin1String( "albums" ) ).elementsByTagName( QString( "item" ) );
QDomNodeList trackItemsList = responseDocument.documentElement().firstChildElement( QLatin1String( "tracks" ) ).elementsByTagName( QString( "item" ) );
// album parsing, there should only be exactly one album
if( albumItemsList.size() == 1 )
{
albumAsin = albumItemsList.at( 0 ).firstChildElement( QLatin1String( "asin" ) ).firstChild().nodeValue();
artist = albumItemsList.at( 0 ).firstChildElement( QLatin1String( "artist" ) ).firstChild().nodeValue();
albumTitle = albumItemsList.at( 0 ).firstChildElement( QLatin1String( "album" ) ).firstChild().nodeValue();
albumPrice = albumItemsList.at( 0 ).firstChildElement( QLatin1String( "price" ) ).firstChild().nodeValue();
imgUrl = albumItemsList.at( 0 ).firstChildElement( QLatin1String( "img" ) ).firstChild().nodeValue();
}
addToCartUrl = "amarok://service-amazonstore?asin=" + albumAsin + "&command=addToCart&name=" + artist + " - " + albumTitle + "&price=" + albumPrice;
contextHtml += "<h3>" + artist + " - " + albumTitle + " (" + Amazon::prettyPrice( albumPrice ) + ")</h3><br/>";
contextHtml += "<center><a href=\"" + addToCartUrl +"\"><img width=\"150px\" src=\"" + imgUrl + "\"></img><br/>" + i18n( "Add to cart" ) + "</a></center>";
contextHtml += "<br/><table>";
contextHtml += "<tr><td><strong>" + i18n( "Artist" ) + "</strong></td>";
contextHtml += "<td><strong>" + i18n( "Track" ) + "</strong></td>";
contextHtml += "<td><strong>" + i18n( "Price" ) + "</strong></td>";
contextHtml += "<td></td></tr>";
// track parsing
for( int i = 0; i < trackItemsList.size(); i++ )
{
artist = trackItemsList.at( i ).firstChildElement( QLatin1String( "artist" ) ).firstChild().nodeValue();
trackPrice = trackItemsList.at( i ).firstChildElement( QLatin1String( "price" ) ).firstChild().nodeValue();
trackTitle = trackItemsList.at( i ).firstChildElement( QLatin1String( "title" ) ).firstChild().nodeValue();
trackAsin = trackItemsList.at( i ).firstChildElement( QLatin1String( "asin" ) ).firstChild().nodeValue();
searchUrl = "amarok://navigate/MP3%20Music%20Store/?filter=" + artist;
playableUrl = "http://www.amazon." + AmazonConfig::instance()->country() + "/gp/dmusic/get_sample_url.html?ASIN=" + trackAsin;
addToCartUrl = "amarok://service-amazonstore?asin=" + trackAsin + "&command=addToCart&name=" + artist + " - " + trackTitle + "&price=" + trackPrice;
contextHtml += "<tr><td><a href=\"" + searchUrl + "\">" + artist + "</a></td>";
contextHtml += "<td><a href=\"amarok://play/" + playableUrl.toEncoded().toBase64() + "\">" + trackTitle + "</a></td>";
contextHtml += "<td>" + Amazon::prettyPrice( trackPrice ) + "</td>";
contextHtml += "<td><a href=\"" + addToCartUrl + "\">" + i18n( "Add to cart" ) + "</a></td></tr>";
}
contextHtml += "</table>";
QFile::remove( tempFileName );
responseFile.close();
emit( info( contextHtml ) );
}
#include "AmazonInfoParser.moc"
/****************************************************************************************
* Copyright (c) 2012 Sven Krohlas <sven@getamarok.com> *
* *
* This program is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 2 of the License, or (at your option) any later *
* version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
#ifndef AMAZONINFOPARSER_H
#define AMAZONINFOPARSER_H
#include "../InfoParserBase.h"
#include "AmazonMeta.h"
#include <kio/job.h>
#include <kio/jobclasses.h>
class AmazonInfoParser : public InfoParserBase
{
Q_OBJECT
public:
AmazonInfoParser()
: InfoParserBase() {}
~AmazonInfoParser() {}
virtual void getInfo( Meta::ArtistPtr artist );
virtual void getInfo( Meta::AlbumPtr album );
virtual void getInfo( Meta::TrackPtr track );
void showFrontPage();
private slots:
void albumInfoDownloadComplete( KJob *requestJob );
};
#endif // AMAZONINFOPARSER_H
/****************************************************************************************
* Copyright (c) 2011 Sven Krohlas <sven@getamarok.com> *
* Copyright (c) 2011, 2012 Sven Krohlas <sven@getamarok.com> *
* The Amazon store in based upon the Magnatune store in Amarok, *
* Copyright (c) 2006,2007 Nikolaj Hald Nielsen <nhn@kde.org> *
* *
......@@ -147,6 +147,10 @@ AmazonStore::polish()
connect( m_itemView, SIGNAL( itemDoubleClicked( QModelIndex ) ), this, SLOT( itemDoubleClicked( QModelIndex ) ) );
connect( m_itemView, SIGNAL( searchForAlbum( QModelIndex ) ), this, SLOT( searchForAlbum( QModelIndex ) ) );
m_amazonInfoParser = new AmazonInfoParser();
setInfoParser( m_amazonInfoParser );
m_amazonInfoParser->showFrontPage();
AmazonUrlRunner *runner = new AmazonUrlRunner();
connect( runner, SIGNAL( search( const QString ) ), this, SLOT( newSearchRequest( QString ) ) );
The::amarokUrlHandler()->registerRunner( runner, runner->command() );
......@@ -160,13 +164,12 @@ void
AmazonStore::addToCart()
{
QString asin, name, price;
int id = 0;
int id = m_itemModel->idForIndex( m_selectedIndex );;
// get item from collection
if( m_itemModel->isAlbum( m_selectedIndex ) ) // album
{
Meta::AmazonAlbum* album;
id = m_itemModel->idForIndex( m_selectedIndex );
album = dynamic_cast<Meta::AmazonAlbum*>( m_collection->albumById( id ).data() );
......@@ -180,7 +183,6 @@ AmazonStore::addToCart()
else // track
{
Meta::AmazonTrack* track;
id = m_itemModel->idForIndex( m_selectedIndex );
track = dynamic_cast<Meta::AmazonTrack*>( m_collection->trackById( id ).data() );
if( !track )
......@@ -248,12 +250,11 @@ AmazonStore::itemDoubleClicked( QModelIndex index )
// for albums: search for the album ASIN to get details about it
// for tracks: add it to the playlist
int id = 0;
int id = m_itemModel->idForIndex( index );
if( m_itemModel->isAlbum( index ) ) // album
{
Meta::AmazonAlbum* album;
id = m_itemModel->idForIndex( index );
album = dynamic_cast<Meta::AmazonAlbum*>( m_collection->albumById( id ).data() );
if( !album )
......@@ -264,7 +265,6 @@ AmazonStore::itemDoubleClicked( QModelIndex index )
else // track
{
Meta::AmazonTrack* track;
id = m_itemModel->idForIndex( index );
track = dynamic_cast<Meta::AmazonTrack*>( m_collection->trackById( id ).data() );
if( !track )
......@@ -281,6 +281,16 @@ AmazonStore::itemSelected( QModelIndex index )
{
m_addToCartButton->setEnabled( true );
m_selectedIndex = index;
int id = m_itemModel->idForIndex( index );
Meta::AlbumPtr album;
if( m_itemModel->isAlbum( index ) )
album = m_collection->albumById( id ).data();
else // track
album = m_collection->trackById( id ).data()->album();
m_amazonInfoParser->getInfo( album );
}
void
......@@ -488,10 +498,10 @@ AmazonStore::initView()
connect( m_checkoutButton, SIGNAL( clicked() ), this, SLOT( checkout() ) );
}
QString AmazonStore::iso3166toAmazon(const QString& country)
QString AmazonStore::iso3166toAmazon( const QString& country )
{
static QHash<QString, QString> table;
if(table.isEmpty())
if( table.isEmpty() )
{
table["fr"] = "fr";
table["at"] = "de";
......@@ -502,7 +512,7 @@ QString AmazonStore::iso3166toAmazon(const QString& country)
table["us"] = "com";
}
return table.value(country, "none");
return table.value( country, "none" );
}
/* private slots */
......@@ -579,13 +589,13 @@ AmazonStore::forward()
void
AmazonStore::countryUpdated()
{
QString country(AmazonConfig::instance()->country());
QString country( AmazonConfig::instance()->country() );
if( country.isEmpty() || country == QLatin1String( "none" ) )
return;
if( m_wantCountryWidget )
{
m_wantCountryWidget->setParent(0);
m_wantCountryWidget->setParent( 0 );
m_wantCountryWidget->deleteLater();
m_wantCountryWidget = 0;
}
......
......@@ -20,6 +20,7 @@
#define AMAZONSTORE_H
#include "AmazonCollection.h"
#include "AmazonInfoParser.h"
#include "AmazonItemTreeModel.h"
#include "AmazonItemTreeView.h"
#include "AmazonMeta.h"
......@@ -40,6 +41,7 @@
#include <threadweaver/ThreadWeaver.h>
class AmazonMetaFactory;
class AmazonInfoParser;
class AmazonWantCountryWidget;
......@@ -113,7 +115,7 @@ public slots:
void itemDoubleClicked( QModelIndex index );
/**
* Activates buttons required to interact with the currently selected item.
* Activates buttons required to interact with the currently selected item and updates the context view.
* @param index The QModelIndex of the item.
*/
void itemSelected( QModelIndex index );
......@@ -189,6 +191,8 @@ private:
QModelIndex m_selectedIndex;
AmazonInfoParser* m_amazonInfoParser;
private slots:
/**
* Parse the API reply XML document.
......
......@@ -16,6 +16,7 @@ add_subdirectory( images )
set( amarok_service_amazonstore_PART_SRCS
AmazonCollection.cpp
AmazonConfig.cpp
AmazonInfoParser.cpp
AmazonItemTreeModel.cpp
AmazonItemTreeView.cpp
AmazonParser.cpp
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment