File indexing completed on 2024-05-19 04:50:19

0001 /****************************************************************************************
0002  * Copyright (c) 2006,2007 Nikolaj Hald Nielsen <nhn@kde.org>                           *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #include "MagnatuneStore.h"
0018 
0019 #include "core/support/Amarok.h"
0020 #include "core/support/Components.h"
0021 #include "core/logger/Logger.h"
0022 #include "amarokurls/AmarokUrlHandler.h"
0023 #include "browsers/CollectionTreeItem.h"
0024 #include "browsers/CollectionTreeView.h"
0025 #include "browsers/SingleCollectionTreeItemModel.h"
0026 #include "EngineController.h"
0027 #include "MagnatuneConfig.h"
0028 #include "MagnatuneDatabaseWorker.h"
0029 #include "MagnatuneInfoParser.h"
0030 #include "MagnatuneNeedUpdateWidget.h"
0031 #include "browsers/InfoProxy.h"
0032 #include "MagnatuneUrlRunner.h"
0033 
0034 #include "ui_MagnatuneSignupDialogBase.h"
0035 
0036 #include "../ServiceSqlRegistry.h"
0037 #include "core-impl/collections/support/CollectionManager.h"
0038 #include "core/support/Debug.h"
0039 #include "playlist/PlaylistModelStack.h"
0040 #include "widgets/SearchWidget.h"
0041 
0042 #include <QAction>
0043 #include <QDateTime>
0044 #include <QMenu>
0045 #include <QStandardPaths>
0046 #include <QTemporaryFile>
0047 #include <QToolBar>
0048 #include <QToolButton>
0049 #include <QUrl>
0050 
0051 #include <KSharedConfig>
0052 #include <ThreadWeaver/ThreadWeaver>
0053 #include <ThreadWeaver/Queue>
0054 
0055 
0056 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
0057 // class MagnatuneServiceFactory
0058 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
0059 
0060 MagnatuneServiceFactory::MagnatuneServiceFactory()
0061     : ServiceFactory()
0062 {
0063 }
0064 
0065 void MagnatuneServiceFactory::init()
0066 {
0067     DEBUG_BLOCK
0068     MagnatuneStore* service = new MagnatuneStore( this, "Magnatune.com" );
0069     m_initialized = true;
0070     Q_EMIT newService( service );
0071 }
0072 
0073 QString MagnatuneServiceFactory::name()
0074 {
0075     return "Magnatune.com";
0076 }
0077 
0078 KConfigGroup MagnatuneServiceFactory::config()
0079 {
0080     return Amarok::config( "Service_Magnatune" );
0081 }
0082 
0083 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
0084 // class MagnatuneStore
0085 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
0086 
0087 MagnatuneStore::MagnatuneStore( MagnatuneServiceFactory* parent, const char *name )
0088         : ServiceBase( name, parent )
0089         , m_downloadHandler( nullptr )
0090         , m_redownloadHandler( nullptr )
0091         , m_needUpdateWidget( nullptr )
0092         , m_downloadInProgress( 0 )
0093         , m_currentAlbum( nullptr )
0094         , m_streamType( MagnatuneMetaFactory::OGG )
0095         , m_magnatuneTimestamp( 0 )
0096         , m_registry( nullptr )
0097         , m_signupInfoWidget( nullptr )
0098 {
0099     DEBUG_BLOCK
0100     setObjectName(name);
0101     //initTopPanel( );
0102 
0103     setShortDescription( i18n( "\"Fair trade\" online music store" ) );
0104     setIcon( QIcon::fromTheme( "view-services-magnatune-amarok" ) );
0105 
0106     // xgettext: no-c-format
0107     setLongDescription( i18n( "Magnatune.com is a different kind of record company with the motto \"We are not evil!\" 50% of every purchase goes directly to the artist and if you purchase an album through Amarok, the Amarok project receives a 10% commission. Magnatune.com also offers \"all you can eat\" memberships that lets you download as much of their music as you like." ) );
0108     setImagePath( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/hover_info_magnatune.png" ) );
0109 
0110 
0111     //initBottomPanel();
0112 //    m_currentlySelectedItem = 0;
0113 
0114     m_polished = false;
0115     //polish( );  //FIXME not happening when shown for some reason
0116 
0117 
0118     //do this stuff now to make us function properly as a track provider on startup. The expensive stuff will
0119     //not happen until the model is added to the view anyway.
0120     MagnatuneMetaFactory * metaFactory = new MagnatuneMetaFactory( "magnatune", this );
0121     
0122     MagnatuneConfig config;
0123     if ( config.isMember() ) {
0124         setMembership( config.membershipType(), config.username(), config.password() );
0125         metaFactory->setMembershipInfo( config.membershipPrefix(), m_username, m_password );
0126     }
0127 
0128     setStreamType( config.streamType() );
0129 
0130     metaFactory->setStreamType( m_streamType );
0131     m_registry = new ServiceSqlRegistry( metaFactory );
0132     m_collection = new Collections::MagnatuneSqlCollection( "magnatune", "Magnatune.com", metaFactory, m_registry );
0133     CollectionManager::instance()->addTrackProvider( m_collection );
0134     setServiceReady( true );
0135 }
0136 
0137 MagnatuneStore::~MagnatuneStore()
0138 {
0139     CollectionManager::instance()->removeTrackProvider( m_collection );
0140     delete m_registry;
0141     delete m_collection;
0142 }
0143 
0144 
0145 void MagnatuneStore::download( )
0146 {
0147     DEBUG_BLOCK
0148     if ( m_downloadInProgress )
0149         return;
0150 
0151     if ( !m_polished )
0152         polish();
0153 
0154     debug() << "here";
0155 
0156     //check if we need to start a download or show the signup dialog
0157     if( !m_isMember || m_membershipType != MagnatuneConfig::DOWNLOAD )
0158     {
0159         showSignupDialog();
0160         return;
0161     }
0162 
0163     m_downloadInProgress = true;
0164     m_downloadAlbumButton->setEnabled( false );
0165 
0166     if ( !m_downloadHandler )
0167     {
0168         m_downloadHandler = new MagnatuneDownloadHandler();
0169         m_downloadHandler->setParent( this );
0170         connect( m_downloadHandler, &MagnatuneDownloadHandler::downloadCompleted,
0171                  this, &MagnatuneStore::downloadCompleted );
0172     }
0173 
0174     if ( m_currentAlbum != nullptr )
0175         m_downloadHandler->downloadAlbum( m_currentAlbum );
0176 }
0177 
0178 
0179 void MagnatuneStore::downloadTrack( Meta::MagnatuneTrack * track )
0180 {
0181     Meta::MagnatuneAlbum * album = dynamic_cast<Meta::MagnatuneAlbum *>( track->album().data() );
0182     if ( album )
0183         downloadAlbum( album );
0184 }
0185 
0186 void MagnatuneStore::downloadAlbum( Meta::MagnatuneAlbum * album )
0187 {
0188     DEBUG_BLOCK
0189     if ( m_downloadInProgress )
0190         return;
0191 
0192     if ( !m_polished )
0193         polish();
0194 
0195     m_downloadInProgress = true;
0196     m_downloadAlbumButton->setEnabled( false );
0197 
0198     if ( !m_downloadHandler )
0199     {
0200         m_downloadHandler = new MagnatuneDownloadHandler();
0201         m_downloadHandler->setParent( this );
0202         connect( m_downloadHandler, &MagnatuneDownloadHandler::downloadCompleted,
0203                  this, &MagnatuneStore::downloadCompleted );
0204     }
0205 
0206     m_downloadHandler->downloadAlbum( album );
0207 }
0208 
0209 
0210 void MagnatuneStore::initTopPanel( )
0211 {
0212     QMenu *filterMenu = new QMenu( nullptr );
0213 
0214     QAction *action = filterMenu->addAction( i18n("Artist") );
0215     connect( action, &QAction::triggered, this, &MagnatuneStore::sortByArtist );
0216 
0217     action = filterMenu->addAction( i18n( "Artist / Album" ) );
0218     connect( action, &QAction::triggered, this, &MagnatuneStore::sortByArtistAlbum );
0219 
0220     action = filterMenu->addAction( i18n( "Album" ) ) ;
0221     connect( action, &QAction::triggered, this, &MagnatuneStore::sortByAlbum );
0222 
0223     action = filterMenu->addAction( i18n( "Genre / Artist" ) );
0224     connect( action, &QAction::triggered, this, &MagnatuneStore::sortByGenreArtist );
0225 
0226     action = filterMenu->addAction( i18n( "Genre / Artist / Album" ) );
0227     connect( action, &QAction::triggered, this, &MagnatuneStore::sortByGenreArtistAlbum );
0228 
0229     QAction *filterMenuAction = new QAction( QIcon::fromTheme( "preferences-other" ), i18n( "Sort Options" ), this );
0230     filterMenuAction->setMenu( filterMenu );
0231 
0232     m_searchWidget->toolBar()->addSeparator();
0233     m_searchWidget->toolBar()->addAction( filterMenuAction );
0234 
0235     QToolButton *tbutton = qobject_cast<QToolButton*>( m_searchWidget->toolBar()->widgetForAction( filterMenuAction ) );
0236     if( tbutton )
0237         tbutton->setPopupMode( QToolButton::InstantPopup );
0238 
0239     QMenu * actionsMenu = new QMenu( nullptr );
0240 
0241     action = actionsMenu->addAction( i18n( "Re-download" ) );
0242     connect( action, &QAction::triggered, this, &MagnatuneStore::processRedownload );
0243 
0244     m_updateAction = actionsMenu->addAction( i18n( "Update Database" ) );
0245     connect( m_updateAction, &QAction::triggered, this, &MagnatuneStore::updateButtonClicked );
0246 
0247     QAction *actionsMenuAction = new QAction( QIcon::fromTheme( "list-add" ), i18n( "Tools" ), this );
0248     actionsMenuAction->setMenu( actionsMenu );
0249 
0250     m_searchWidget->toolBar()->addAction( actionsMenuAction );
0251 
0252     tbutton = qobject_cast<QToolButton*>( m_searchWidget->toolBar()->widgetForAction( actionsMenuAction ) );
0253     if( tbutton )
0254         tbutton->setPopupMode( QToolButton::InstantPopup );
0255 
0256 }
0257 
0258 void MagnatuneStore::initBottomPanel()
0259 {
0260     //m_bottomPanel->setMaximumHeight( 24 );
0261 
0262     m_downloadAlbumButton = new QPushButton;
0263     m_downloadAlbumButton->setParent( m_bottomPanel );
0264 
0265     MagnatuneConfig config;
0266     if ( config.isMember() && config.membershipType() == MagnatuneConfig::DOWNLOAD )
0267     {
0268         m_downloadAlbumButton->setText( i18n( "Download Album" ) );
0269         m_downloadAlbumButton->setEnabled( false );
0270     }
0271     else if ( config.isMember() )
0272         m_downloadAlbumButton->hide();
0273     else
0274     {
0275         m_downloadAlbumButton->setText( i18n( "Signup" ) );
0276         m_downloadAlbumButton->setEnabled( true );
0277     }
0278 
0279     m_downloadAlbumButton->setObjectName( "downloadButton" );
0280     m_downloadAlbumButton->setIcon( QIcon::fromTheme( "download-amarok" ) );
0281     
0282     connect( m_downloadAlbumButton, &QPushButton::clicked, this, &MagnatuneStore::download );
0283 
0284     if ( !config.lastUpdateTimestamp() )
0285     {
0286         m_needUpdateWidget = new MagnatuneNeedUpdateWidget(m_bottomPanel);
0287 
0288         connect( m_needUpdateWidget, &MagnatuneNeedUpdateWidget::wantUpdate,
0289                  this, &MagnatuneStore::updateButtonClicked );
0290 
0291         m_downloadAlbumButton->setParent(nullptr);
0292     }
0293 }
0294 
0295 
0296 void MagnatuneStore::updateButtonClicked()
0297 {
0298     DEBUG_BLOCK
0299     m_updateAction->setEnabled( false );
0300     if ( m_needUpdateWidget )
0301         m_needUpdateWidget->disable();
0302 
0303     updateMagnatuneList();
0304 }
0305 
0306 
0307 bool MagnatuneStore::updateMagnatuneList()
0308 {
0309     DEBUG_BLOCK
0310     //download new list from magnatune
0311 
0312      debug() << "MagnatuneStore: start downloading xml file";
0313 
0314 
0315     QTemporaryFile tempFile;
0316 //     tempFile.setSuffix( ".bz2" );
0317     tempFile.setAutoRemove( false );  // file will be removed in MagnatuneXmlParser
0318     if( !tempFile.open() )
0319     {
0320         return false; //error
0321     }
0322 
0323     m_tempFileName = tempFile.fileName();
0324 
0325     m_listDownloadJob = KIO::file_copy( QUrl("http://magnatune.com/info/album_info_xml.bz2"),  QUrl::fromLocalFile( m_tempFileName ), 0700 , KIO::HideProgressInfo | KIO::Overwrite );
0326     Amarok::Logger::newProgressOperation( m_listDownloadJob, i18n( "Downloading Magnatune.com database..." ), this, &MagnatuneStore::listDownloadCancelled );
0327 
0328     connect( m_listDownloadJob, &KJob::result,
0329             this, &MagnatuneStore::listDownloadComplete );
0330 
0331     return true;
0332 }
0333 
0334 
0335 void MagnatuneStore::listDownloadComplete( KJob * downLoadJob )
0336 {
0337    DEBUG_BLOCK
0338    debug() << "MagnatuneStore: xml file download complete";
0339 
0340     if ( downLoadJob != m_listDownloadJob ) {
0341         debug() << "wrong job, ignoring....";
0342         return ; //not the right job, so let's ignore it
0343     }
0344 
0345     m_updateAction->setEnabled( true );
0346 
0347     if ( downLoadJob->error() != 0 )
0348     {
0349         debug() << "Got an error, bailing out: " << downLoadJob->errorString();
0350         //TODO: error handling here
0351         return ;
0352     }
0353 
0354 
0355     Amarok::Logger::shortMessage( i18n( "Updating the local Magnatune database."  ) );
0356     MagnatuneXmlParser * parser = new MagnatuneXmlParser( m_tempFileName );
0357     parser->setDbHandler( new MagnatuneDatabaseHandler() );
0358     connect( parser, &MagnatuneXmlParser::doneParsing, this, &MagnatuneStore::doneParsing );
0359 
0360     ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(parser) );
0361 }
0362 
0363 
0364 void MagnatuneStore::listDownloadCancelled( )
0365 {
0366     DEBUG_BLOCK
0367 
0368     m_listDownloadJob->kill();
0369     m_listDownloadJob = nullptr;
0370     debug() << "Aborted xml download";
0371 
0372     m_updateAction->setEnabled( true );
0373     if ( m_needUpdateWidget )
0374         m_needUpdateWidget->enable();
0375 }
0376 
0377 
0378 
0379 void MagnatuneStore::doneParsing()
0380 {
0381     debug() << "MagnatuneStore: done parsing";
0382     m_collection->emitUpdated();
0383 
0384     //update the last update timestamp
0385 
0386     MagnatuneConfig config;
0387     if ( m_magnatuneTimestamp == 0 )
0388         config.setLastUpdateTimestamp( QDateTime::currentDateTimeUtc().toSecsSinceEpoch() );
0389     else
0390         config.setLastUpdateTimestamp( m_magnatuneTimestamp );
0391 
0392     config.save();
0393 
0394     if ( m_needUpdateWidget )
0395     {
0396         m_needUpdateWidget->setParent(nullptr);
0397         m_needUpdateWidget->deleteLater();
0398         m_needUpdateWidget = nullptr;
0399 
0400         m_downloadAlbumButton->setParent(m_bottomPanel);
0401     }
0402 }
0403 
0404 
0405 void MagnatuneStore::processRedownload( )
0406 {
0407     debug() << "Process redownload";
0408 
0409     if ( m_redownloadHandler == nullptr )
0410     {
0411         m_redownloadHandler = new MagnatuneRedownloadHandler( this );
0412     }
0413     m_redownloadHandler->showRedownloadDialog();
0414 }
0415 
0416 
0417 void MagnatuneStore::downloadCompleted( bool )
0418 {
0419     delete m_downloadHandler;
0420     m_downloadHandler = nullptr;
0421 
0422     m_downloadAlbumButton->setEnabled( true );
0423     m_downloadInProgress = false;
0424 
0425     debug() << "Purchase operation complete";
0426 
0427     //TODO: display some kind of success dialog here?
0428 }
0429 
0430 
0431 void MagnatuneStore::itemSelected( CollectionTreeItem * selectedItem )
0432 {
0433     DEBUG_BLOCK
0434 
0435     //only care if the user has a download membership
0436     if( !m_isMember || m_membershipType != MagnatuneConfig::DOWNLOAD )
0437         return;
0438 
0439     //we only enable the purchase button if there is only one item selected and it happens to
0440     //be an album or a track
0441     Meta::DataPtr dataPtr = selectedItem->data();
0442 
0443     if ( auto track = AmarokSharedPointer<Meta::MagnatuneTrack>::dynamicCast( dataPtr ) )
0444     {
0445         debug() << "is right type (track)";
0446         m_currentAlbum = static_cast<Meta::MagnatuneAlbum *> ( track->album().data() );
0447         m_downloadAlbumButton->setEnabled( true );
0448     }
0449     else if ( auto album = AmarokSharedPointer<Meta::MagnatuneAlbum>::dynamicCast( dataPtr ) )
0450     {
0451         m_currentAlbum = album.data();
0452         debug() << "is right type (album) named " << m_currentAlbum->name();
0453 
0454         m_downloadAlbumButton->setEnabled( true );
0455     }
0456     else
0457     {
0458         debug() << "is wrong type";
0459         m_downloadAlbumButton->setEnabled( false );
0460     }
0461 }
0462 
0463 
0464 void MagnatuneStore::addMoodyTracksToPlaylist( const QString &mood, int count )
0465 {
0466     MagnatuneDatabaseWorker *databaseWorker = new MagnatuneDatabaseWorker();
0467     databaseWorker->fetchTrackswithMood( mood, count, m_registry );
0468     connect( databaseWorker, &MagnatuneDatabaseWorker::gotMoodyTracks, this, &MagnatuneStore::moodyTracksReady );
0469 
0470     ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(databaseWorker) );
0471 }
0472 
0473 
0474 void MagnatuneStore::polish()
0475 {
0476     DEBUG_BLOCK;
0477 
0478     if (!m_polished) {
0479         m_polished = true;
0480 
0481         initTopPanel( );
0482         initBottomPanel();
0483 
0484         QList<CategoryId::CatMenuId> levels;
0485         levels << CategoryId::Genre << CategoryId::Artist << CategoryId::Album;
0486 
0487         m_magnatuneInfoParser = new MagnatuneInfoParser();
0488 
0489         setInfoParser( m_magnatuneInfoParser );
0490         setModel( new SingleCollectionTreeItemModel( m_collection, levels ) );
0491 
0492         connect( qobject_cast<CollectionTreeView*>(m_contentView), &CollectionTreeView::itemSelected,
0493                  this, &MagnatuneStore::itemSelected );
0494 
0495         //add a custom url runner
0496         MagnatuneUrlRunner *runner = new MagnatuneUrlRunner();
0497 
0498         connect( runner, &MagnatuneUrlRunner::showFavorites, this, &MagnatuneStore::showFavoritesPage );
0499         connect( runner, &MagnatuneUrlRunner::showHome, this, &MagnatuneStore::showHomePage );
0500         connect( runner, &MagnatuneUrlRunner::showRecommendations, this, &MagnatuneStore::showRecommendationsPage );
0501         connect( runner, &MagnatuneUrlRunner::buyOrDownload, this, &MagnatuneStore::downloadSku );
0502         connect( runner, &MagnatuneUrlRunner::removeFromFavorites, this, &MagnatuneStore::removeFromFavorites );
0503 
0504         The::amarokUrlHandler()->registerRunner( runner, runner->command() );
0505     }
0506 
0507     MagnatuneInfoParser * parser = dynamic_cast<MagnatuneInfoParser *> ( infoParser() );
0508     if ( parser )
0509         parser->getFrontPage();
0510 
0511     //get a mood map we can show to the cloud view
0512 
0513     MagnatuneDatabaseWorker * databaseWorker = new MagnatuneDatabaseWorker();
0514     databaseWorker->fetchMoodMap();
0515     connect( databaseWorker, &MagnatuneDatabaseWorker::gotMoodMap, this, &MagnatuneStore::moodMapReady );
0516     ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(databaseWorker) );
0517 
0518     if ( MagnatuneConfig().autoUpdateDatabase() )
0519         checkForUpdates();
0520 }
0521 
0522 
0523 
0524 void MagnatuneStore::setMembership( int type, const QString & username, const QString & password)
0525 {
0526     m_isMember = true;
0527     m_membershipType = type;
0528     m_username = username;
0529     m_password = password;
0530 }
0531 
0532 
0533 void MagnatuneStore::moodMapReady(const QMap< QString, int > &map)
0534 {
0535     QVariantMap variantMap;
0536     QList<QVariant> strings;
0537     QList<QVariant> weights;
0538     QVariantMap dbusActions;
0539 
0540     foreach( const QString &key, map.keys() ) {
0541 
0542         strings << key;
0543         weights << map.value( key );
0544 
0545         QString escapedKey = key;
0546         escapedKey.replace( ' ', "%20" );
0547         QVariantMap action;
0548         action["component"]  = "/ServicePluginManager";
0549         action["function"] = "sendMessage";
0550         action["arg1"] = QStringLiteral( "Magnatune.com");
0551         action["arg2"] = QStringLiteral( "addMoodyTracks %1 10").arg( escapedKey );
0552 
0553         dbusActions[key] = action;
0554 
0555     }
0556 
0557     variantMap["cloud_name"] = QVariant( "Magnatune Moods" );
0558     variantMap["cloud_strings"] = QVariant( strings );
0559     variantMap["cloud_weights"] = QVariant( weights );
0560     variantMap["cloud_actions"] = QVariant( dbusActions );
0561 
0562     The::infoProxy()->setCloud( variantMap );
0563 }
0564 
0565 
0566 void MagnatuneStore::setStreamType( int type )
0567 {
0568     m_streamType = type;
0569 }
0570 
0571 void MagnatuneStore::checkForUpdates()
0572 {
0573     m_updateTimestampDownloadJob = KIO::storedGet( QUrl("http://magnatune.com/info/last_update_timestamp"), KIO::Reload, KIO::HideProgressInfo );
0574     connect( m_updateTimestampDownloadJob, &KJob::result, this, &MagnatuneStore::timestampDownloadComplete );
0575 }
0576 
0577 
0578 void MagnatuneStore::timestampDownloadComplete( KJob *  job )
0579 {
0580     DEBUG_BLOCK
0581 
0582     if ( job->error() != 0 )
0583     {
0584         //TODO: error handling here
0585         return ;
0586     }
0587     if ( job != m_updateTimestampDownloadJob )
0588         return ; //not the right job, so let's ignore it
0589 
0590 
0591     QString timestampString = ( ( KIO::StoredTransferJob* ) job )->data();
0592     debug() << "Magnatune timestamp: " << timestampString;
0593 
0594     bool ok;
0595     qulonglong magnatuneTimestamp = timestampString.toULongLong( &ok );
0596 
0597     MagnatuneConfig config;
0598     qulonglong localTimestamp = config.lastUpdateTimestamp();
0599 
0600     debug() << "Last update timestamp: " << QString::number( localTimestamp );
0601 
0602     if ( ok && magnatuneTimestamp > localTimestamp ) {
0603         m_magnatuneTimestamp = magnatuneTimestamp;
0604         updateButtonClicked();
0605     }
0606 }
0607 
0608 
0609 void MagnatuneStore::moodyTracksReady( const Meta::TrackList &tracks )
0610 {
0611     DEBUG_BLOCK
0612     The::playlistController()->insertOptioned( tracks, Playlist::Replace );
0613 }
0614 
0615 
0616 QString MagnatuneStore::messages()
0617 {
0618     QString text = i18n( "The Magnatune.com service accepts the following messages: \n\n\taddMoodyTracks mood count: Adds a number of random tracks with the specified mood to the playlist. The mood argument must have spaces escaped with %%20" );
0619 
0620     return text;
0621 }
0622 
0623 
0624 QString MagnatuneStore::sendMessage( const QString & message )
0625 {
0626     QStringList args = message.split( ' ', Qt::SkipEmptyParts );
0627 
0628     if ( args.size() < 1 ) {
0629         return i18n( "ERROR: No arguments supplied" );
0630     }
0631 
0632     if ( args[0] == "addMoodyTracks" ) {
0633         if ( args.size() != 3 ) {
0634             return i18n( "ERROR: Wrong number of arguments for addMoodyTracks" );
0635         }
0636 
0637         QString mood = args[1];
0638         mood = mood.replace( "%20", " " );
0639 
0640         bool ok;
0641         int count = args[2].toInt( &ok );
0642 
0643         if ( !ok )
0644             return i18n( "ERROR: Parse error for argument 2 ( count )" );
0645 
0646         addMoodyTracksToPlaylist( mood, count );
0647 
0648         return i18n( "ok" );
0649     }
0650 
0651     return i18n( "ERROR: Unknown argument." );
0652 }
0653 
0654 void MagnatuneStore::showFavoritesPage()
0655 {
0656     DEBUG_BLOCK
0657     m_magnatuneInfoParser->getFavoritesPage();
0658 }
0659 
0660 void MagnatuneStore::showHomePage()
0661 {
0662     DEBUG_BLOCK
0663     m_magnatuneInfoParser->getFrontPage();
0664 }
0665 
0666 void MagnatuneStore::showRecommendationsPage()
0667 {
0668     DEBUG_BLOCK
0669     m_magnatuneInfoParser->getRecommendationsPage();
0670 }
0671 
0672 void MagnatuneStore::downloadSku( const QString &sku )
0673 {
0674     DEBUG_BLOCK
0675     debug() << "sku: " << sku;
0676     MagnatuneDatabaseWorker * databaseWorker = new MagnatuneDatabaseWorker();
0677     databaseWorker->fetchAlbumBySku( sku, m_registry );
0678     connect( databaseWorker, &MagnatuneDatabaseWorker::gotAlbumBySku, this, &MagnatuneStore::downloadAlbum );
0679 
0680     ThreadWeaver::Queue::instance()->enqueue( QSharedPointer<ThreadWeaver::Job>(databaseWorker) );
0681 }
0682 
0683 void MagnatuneStore::addToFavorites( const QString &sku )
0684 {
0685     DEBUG_BLOCK
0686     MagnatuneConfig config;
0687 
0688     if( !config.isMember() )
0689         return;
0690 
0691     QString url = "http://%1:%2@%3.magnatune.com/member/favorites?action=add_api&sku=%4";
0692     url = url.arg( config.username(), config.password(), config.membershipPrefix(), sku );
0693 
0694     debug() << "favorites url: " << url;
0695 
0696     m_favoritesJob = KIO::storedGet( QUrl( url ), KIO::Reload, KIO::HideProgressInfo );
0697     connect( m_favoritesJob, &KJob::result, this, &MagnatuneStore::favoritesResult );
0698 }
0699 
0700 void MagnatuneStore::removeFromFavorites( const QString &sku )
0701 {
0702     DEBUG_BLOCK
0703     MagnatuneConfig config;
0704 
0705     if( !config.isMember() )
0706         return;
0707 
0708     QString url = "http://%1:%2@%3.magnatune.com/member/favorites?action=remove_api&sku=%4";
0709     url = url.arg( config.username(), config.password(), config.membershipPrefix(), sku );
0710 
0711     debug() << "favorites url: " << url;
0712 
0713     m_favoritesJob = KIO::storedGet( QUrl( url ), KIO::Reload, KIO::HideProgressInfo );
0714     connect( m_favoritesJob, &KJob::result, this, &MagnatuneStore::favoritesResult );
0715 }
0716 
0717 void MagnatuneStore::favoritesResult( KJob* addToFavoritesJob )
0718 {
0719     if( addToFavoritesJob != m_favoritesJob )
0720         return;
0721 
0722     QString result = m_favoritesJob->data();
0723 
0724     Amarok::Logger::longMessage( result );
0725 
0726     //show the favorites page
0727     showFavoritesPage();
0728 }
0729 
0730 void
0731 MagnatuneStore::showSignupDialog()
0732 {
0733 
0734     if ( m_signupInfoWidget== nullptr )
0735     {
0736         m_signupInfoWidget = new QDialog;
0737         Ui::SignupDialog ui;
0738         ui.setupUi( m_signupInfoWidget );
0739     }
0740 
0741      m_signupInfoWidget->show();
0742 }