You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
amarok/amarok/src/magnatunebrowser/magnatunebrowser.cpp

524 lines
16 KiB

/*
Copyright (c) 2006 Nikolaj Hald Nielsen <nhnFreespirit@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "amarok.h"
#include "magnatunebrowser.h"
#include "playlist.h"
#include "magnatunedatabasehandler.h"
#include "debug.h"
#include <kstandarddirs.h> //locate()
#include <kurl.h>
#include <kiconloader.h> //multiTabBar icons
#include <ktempfile.h>
#include <tqsplitter.h>
#include <tqdragobject.h>
#include <tqlabel.h>
MagnatuneBrowser *MagnatuneBrowser::s_instance = 0;
MagnatuneBrowser::MagnatuneBrowser( const char *name )
: TQVBox( 0, name )
{
DEBUG_BLOCK
initTopPanel( );
TQSplitter *spliter = new TQSplitter( Qt::Vertical, this );
debug() << "Magnatune browser starting..." << endl;
m_listView = new MagnatuneListView( spliter );
m_popupMenu = new TQPopupMenu( spliter, "MagnatuneMenu" );
m_artistInfobox = new MagnatuneArtistInfoBox( spliter, "ArtistInfoBox" );
initBottomPanel();
//connect (m_listView, TQT_SIGNAL(executed(KListViewItem *)), this, TQT_SLOT(itemExecuted(KListViewItem *)));
connect( m_listView, TQT_SIGNAL( doubleClicked( TQListViewItem * ) ),
this, TQT_SLOT( itemExecuted( TQListViewItem * ) ) );
connect( m_listView, TQT_SIGNAL( selectionChanged( TQListViewItem * ) ),
this, TQT_SLOT( selectionChanged( TQListViewItem * ) ) );
connect( m_listView, TQT_SIGNAL( rightButtonClicked ( TQListViewItem *, const TQPoint &, int ) ),
this, TQT_SLOT( showPopupMenu( TQListViewItem *, const TQPoint &, int ) ) );
connect( m_popupMenu, TQT_SIGNAL( aboutToShow() ),
this, TQT_SLOT( menuAboutToShow() ) );
m_currentInfoUrl = "";
m_purchaseHandler = 0;
m_redownloadHandler = 0;
m_purchaseInProgress = false;
m_polished = false;
}
void MagnatuneBrowser::itemExecuted( TQListViewItem * item )
{
DEBUG_BLOCK;
switch ( item->depth() )
{
case 2:
addTrackToPlaylist( dynamic_cast<MagnatuneListViewTrackItem *>( item ) );
break;
case 1:
addAlbumToPlaylist( dynamic_cast<MagnatuneListViewAlbumItem *>( item ) );
break;
case 0:
addArtistToPlaylist( dynamic_cast<MagnatuneListViewArtistItem *>( item ) );
break;
default:
break;
}
}
void MagnatuneBrowser::addTrackToPlaylist( MagnatuneTrack *item )
{
if ( !item ) return ; // sanity check
debug() << "Magnatune browser: adding single track" << endl;
TQString url = item->getHifiURL();
Playlist * playlist = Playlist::instance();
playlist->insertMedia( KURL( url ) );
}
void MagnatuneBrowser::addAlbumToPlaylist( MagnatuneAlbum * item )
{
if ( !item ) return ; // sanity check
debug() << "Magnatune browser: adding album" << endl;
MagnatuneTrackList tracks = MagnatuneDatabaseHandler::instance() ->getTracksByAlbumId( item->getId() );
MagnatuneTrackList::iterator it;
for ( it = tracks.begin(); it != tracks.end(); ++it )
addTrackToPlaylist( &( *it ) );
}
void MagnatuneBrowser::addArtistToPlaylist( MagnatuneArtist *item )
{
if ( !item ) return ; // sanity check
debug() << "Magnatune browser: adding artist" << endl;
MagnatuneAlbumList albums = MagnatuneDatabaseHandler::instance() ->getAlbumsByArtistId( item->getId(), "" );
MagnatuneAlbumList::iterator it;
for ( it = albums.begin(); it != albums.end(); ++it )
addAlbumToPlaylist( &( *it ) );
}
void MagnatuneBrowser::selectionChanged( TQListViewItem *item )
{
if ( !item ) return ; // sanity check
debug() << "Selection changed..." << endl;
if ( item->depth() == 0 )
m_purchaseAlbumButton->setEnabled( false );
else
if ( ! m_purchaseInProgress )
m_purchaseAlbumButton->setEnabled( true );
if ( !m_isInfoShown )
return ;
switch ( item->depth() )
{
case 0:
{
MagnatuneListViewArtistItem * artistItem = dynamic_cast<MagnatuneListViewArtistItem *>( item );
if ( artistItem && m_currentInfoUrl != artistItem->getHomeURL() )
{
m_currentInfoUrl = artistItem->getHomeURL();
m_artistInfobox->displayArtistInfo( KURL( m_currentInfoUrl ) );
}
}
break;
case 1:
{
MagnatuneListViewAlbumItem *albumItem = dynamic_cast<MagnatuneListViewAlbumItem *>( item );
if ( albumItem && m_currentInfoUrl != albumItem->getCoverURL() )
{
m_currentInfoUrl = albumItem->getCoverURL();
m_artistInfobox->displayAlbumInfo( albumItem );
}
}
break;
case 2:
{
// a track is selected, show the corrosponding album info!
MagnatuneListViewTrackItem *trackItem = dynamic_cast<MagnatuneListViewTrackItem*>( item );
if (!trackItem) {
debug() << "dynamic_cast to trackItem failed!" << endl;
return;
}
int albumId = trackItem->getAlbumId();
MagnatuneAlbum album = MagnatuneDatabaseHandler::instance() ->getAlbumById( albumId );
m_artistInfobox->displayAlbumInfo( &album );
}
break;
default:
break;
}
}
void MagnatuneBrowser::showPopupMenu( TQListViewItem * item, const TQPoint & pos, int /*column*/ )
{
if ( !item ) return ;
m_popupMenu->exec( pos );
}
void MagnatuneBrowser::addSelectionToPlaylist( )
{
TQListViewItem * selectedItem = m_listView->selectedItem();
switch ( selectedItem->depth() )
{
case 0:
addArtistToPlaylist( dynamic_cast<MagnatuneListViewArtistItem *>( selectedItem ) );
break;
case 1:
addAlbumToPlaylist( dynamic_cast<MagnatuneListViewAlbumItem *>( selectedItem ) );
break;
case 2:
addTrackToPlaylist( dynamic_cast<MagnatuneListViewTrackItem *>( selectedItem ) );
}
}
void MagnatuneBrowser::menuAboutToShow( )
{
m_popupMenu->clear();
TQListViewItem *selectedItem = m_listView->selectedItem();
if ( !selectedItem ) return ;
switch ( selectedItem->depth() )
{
case 0:
m_popupMenu->insertItem( i18n( "Add artist to playlist" ), this, TQT_SLOT( addSelectionToPlaylist() ) );
break;
case 1:
m_popupMenu->insertItem( i18n( "Add album to playlist" ), this, TQT_SLOT( addSelectionToPlaylist() ) );
m_popupMenu->insertItem( i18n( "Purchase album" ), this, TQT_SLOT( purchaseSelectedAlbum() ) );
break;
case 2:
m_popupMenu->insertItem( i18n( "Add track to playlist" ), this, TQT_SLOT( addSelectionToPlaylist() ) );
m_popupMenu->insertItem( i18n( "Purchase album" ), this, TQT_SLOT( purchaseAlbumContainingSelectedTrack() ) );
}
}
void MagnatuneBrowser::purchaseButtonClicked( )
{
if ( !m_purchaseInProgress )
{
m_purchaseInProgress = true;
m_purchaseAlbumButton->setEnabled( false );
if ( m_listView->selectedItem() ->depth() == 1 )
purchaseSelectedAlbum( );
else if ( m_listView->selectedItem() ->depth() == 2 )
purchaseAlbumContainingSelectedTrack( );
}
}
void MagnatuneBrowser::purchaseSelectedAlbum( )
{
if ( !m_purchaseHandler )
{
m_purchaseHandler = new MagnatunePurchaseHandler();
m_purchaseHandler->setParent( this );
connect( m_purchaseHandler, TQT_SIGNAL( purchaseCompleted( bool ) ), this, TQT_SLOT( purchaseCompleted( bool ) ) );
}
MagnatuneListViewAlbumItem *selectedAlbum = dynamic_cast<MagnatuneListViewAlbumItem *>( m_listView->selectedItem() );
if (selectedAlbum)
m_purchaseHandler->purchaseAlbum( *selectedAlbum );
}
void MagnatuneBrowser::purchaseAlbumContainingSelectedTrack( )
{
if ( !m_purchaseHandler )
{
m_purchaseHandler = new MagnatunePurchaseHandler();
m_purchaseHandler->setParent( this );
connect( m_purchaseHandler, TQT_SIGNAL( purchaseCompleted( bool ) ), this, TQT_SLOT( purchaseCompleted( bool ) ) );
}
MagnatuneListViewTrackItem *selectedTrack = dynamic_cast<MagnatuneListViewTrackItem *>( m_listView->selectedItem() );
if (!selectedTrack) {
debug() << "dynamic_cast to selected track failed!" << endl;
return;
}
MagnatuneAlbum album( MagnatuneDatabaseHandler::instance() ->getAlbumById( selectedTrack->getAlbumId() ) );
m_purchaseHandler->purchaseAlbum( album );
}
void MagnatuneBrowser::initTopPanel( )
{
m_topPanel = new TQHBox( this, "topPanel", 0 );
m_topPanel->setMaximumHeight( 24 );
m_topPanel->setSpacing( 2 );
m_topPanel->setMargin( 2 );
new TQLabel ( i18n( "Genre: " ), m_topPanel, "genreLabel", 0 );
m_genreComboBox = new TQComboBox( false, m_topPanel, "genreComboBox" );
updateGenreBox();
m_advancedFeaturesButton = new TQPushButton( i18n( "Redownload" ), m_topPanel, "advancedButton" );
connect( m_advancedFeaturesButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( processRedownload() ) );
connect( m_genreComboBox, TQT_SIGNAL( activated ( int ) ), this, TQT_SLOT( genreChanged() ) );
}
void MagnatuneBrowser::initBottomPanel()
{
m_bottomPanel = new TQVBox( this, "bottomPanel", 0 );
m_bottomPanel->setMaximumHeight( 54 );
m_bottomPanel->setSpacing( 2 );
m_bottomPanel->setMargin( 2 );
TQHBox *hBox = new TQHBox( m_bottomPanel, "bottomHBox", 0 );
hBox->setMaximumHeight( 24 );
hBox->setSpacing( 2 );
//hBox->setMargin( 2 );
m_purchaseAlbumButton = new TQPushButton( i18n( "Purchase Album" ), m_bottomPanel, "purchaseButton" );
m_purchaseAlbumButton->setIconSet( SmallIconSet( Amarok::icon( "download" ) ) );
m_purchaseAlbumButton->setEnabled( false );
m_purchaseAlbumButton->setMaximumHeight( 24 );
m_updateListButton = new TQPushButton( i18n( "Update" ), hBox, "updateButton" );
m_updateListButton->setIconSet( SmallIconSet( Amarok::icon( "rescan" ) ) );
m_showInfoToggleButton = new TQPushButton( i18n( "Show Info" ) , hBox, "showInfoCheckbox" );
m_showInfoToggleButton->setToggleButton( true );
m_showInfoToggleButton->setIconSet( SmallIconSet( Amarok::icon( "info" ) ) );
m_showInfoToggleButton->setOn( true );
m_isInfoShown = true;
connect( m_showInfoToggleButton, TQT_SIGNAL( toggled( bool ) ), this, TQT_SLOT( showInfo( bool ) ) );
connect( m_updateListButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( updateButtonClicked() ) );
connect( m_purchaseAlbumButton, TQT_SIGNAL( clicked() ) , this, TQT_SLOT( purchaseButtonClicked() ) );
}
void MagnatuneBrowser::updateButtonClicked()
{
m_updateListButton->setEnabled( false );
updateMagnatuneList();
}
bool MagnatuneBrowser::updateMagnatuneList()
{
//download new list from magnatune
m_listDownloadJob = KIO::storedGet( KURL( "http://magnatune.com/info/album_info.xml" ), false, false );
Amarok::StatusBar::instance() ->newProgressOperation( m_listDownloadJob )
.setDescription( i18n( "Downloading Magnatune.com Database" ) )
.setAbortSlot( TQT_TQOBJECT(this), TQT_SLOT( listDownloadCancelled() ) );
connect( m_listDownloadJob, TQT_SIGNAL( result( KIO::Job* ) ), TQT_SLOT( listDownloadComplete( KIO::Job* ) ) );
return true;
}
void MagnatuneBrowser::listDownloadComplete( KIO::Job * downLoadJob )
{
if ( downLoadJob != m_listDownloadJob )
return ; //not the right job, so let's ignore it
m_updateListButton->setEnabled( true );
if ( !downLoadJob->error() == 0 )
{
//TODO: error handling here
return ;
}
KIO::StoredTransferJob* const storedJob = static_cast<KIO::StoredTransferJob*>( downLoadJob );
TQString list = TQString( storedJob->data() );
KTempFile tfile;
m_tempFileName = tfile.name();
TQFile file( m_tempFileName );
if ( file.open( IO_WriteOnly ) )
{
TQTextStream stream( &file );
stream << list;
file.close();
}
MagnatuneXmlParser * parser = new MagnatuneXmlParser( m_tempFileName );
connect( parser, TQT_SIGNAL( doneParsing() ), TQT_SLOT( doneParsing() ) );
ThreadManager::instance() ->queueJob( parser );
}
void MagnatuneBrowser::listDownloadCancelled( )
{
Amarok::StatusBar::instance() ->endProgressOperation( m_listDownloadJob );
m_listDownloadJob->kill( true );
delete m_listDownloadJob;
m_listDownloadJob = 0;
debug() << "Aborted xml download" << endl;
m_updateListButton->setEnabled( true );
}
void MagnatuneBrowser::showInfo( bool show )
{
if ( show )
{
m_isInfoShown = true;
m_artistInfobox->widget() ->setMaximumHeight( 2000 );
}
else
{
m_artistInfobox->widget() ->setMaximumHeight( 0 );
m_isInfoShown = false;
}
}
void MagnatuneBrowser::updateList()
{
DEBUG_BLOCK
const TQString genre = m_genreComboBox->currentText();
MagnatuneArtistList artists;
artists = MagnatuneDatabaseHandler::instance() ->getArtistsByGenre( genre );
m_listView->clear();
MagnatuneArtistList::iterator it;
for ( it = artists.begin(); it != artists.end(); ++it )
new MagnatuneListViewArtistItem( ( *it ), m_listView );
m_listView->repaintContents();
}
void MagnatuneBrowser::genreChanged()
{
debug() << "Genre changed..." << endl;
updateList( );
}
void MagnatuneBrowser::doneParsing()
{
DEBUG_BLOCK
updateList();
updateGenreBox( );
updateList(); // stupid stupid hack....
if( !TQFile::remove( m_tempFileName ) )
debug() << "Couldn't remove temp file at " << m_tempFileName << endl;
m_tempFileName = TQString();
}
void MagnatuneBrowser::updateGenreBox()
{
const TQStringList genres = MagnatuneDatabaseHandler::instance() ->getAlbumGenres();
m_genreComboBox->clear();
m_genreComboBox->insertItem ( "All" , 0 ); // should not be i18n'ed as it is
//used as a trigger in the code in the database handler.
foreach( genres )
m_genreComboBox->insertItem( ( *it ), -1 );
}
void MagnatuneBrowser::processRedownload( )
{
if ( m_redownloadHandler == 0 )
{
m_redownloadHandler = new MagnatuneRedownloadHandler( this );
}
m_redownloadHandler->showRedownloadDialog();
}
void MagnatuneBrowser::purchaseCompleted( bool /*success*/ )
{
if ( m_purchaseHandler != 0 )
{
delete m_purchaseHandler;
m_purchaseHandler = 0;
}
m_purchaseAlbumButton->setEnabled( true );
m_purchaseInProgress = false;
debug() << "Purchase operation complete" << endl;
//TODO: display some kind of success dialog here?
}
void MagnatuneBrowser::polish( )
{
DEBUG_BLOCK;
if (!m_polished) {
m_polished = true;
updateList( );
m_artistInfobox->begin( KURL( locate( "data", "amarok/data/" ) ) );
m_artistInfobox->write( "<table align='center' border='0'><tbody align='center' valign='top'>"
"<tr align='center'><td><div align='center'>"
"<IMG src='magnatune_logo.png' width='200' height='36' align='center' border='0'>"
"</div></td></tr><tr><td><BR>"
+ i18n( "Welcome to Amarok's integrated Magnatune.com store. If this is the "
"first time you run it, you must update the database by pressing the "
"'Update' button below." )
+ "</td></tr></tbody></table>" );
m_artistInfobox->end();
}
}
#include "magnatunebrowser.moc"