|
|
|
// (c) Pierpaolo Di Panfilo 2004
|
|
|
|
// (c) 2005 Isaiah Damron <xepo@trifault.net>
|
|
|
|
// See COPYING file for licensing information
|
|
|
|
|
|
|
|
#include "amarok.h"
|
|
|
|
#include "amarokconfig.h"
|
|
|
|
#include "browserToolBar.h"
|
|
|
|
#include "clicklineedit.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "collectionbrowser.h" //manipulateThe()
|
|
|
|
#include "collectiondb.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "coverfetcher.h"
|
|
|
|
#include "covermanager.h"
|
|
|
|
#include "pixmapviewer.h"
|
|
|
|
#include "playlist.h"
|
|
|
|
|
|
|
|
#include <tqdesktopwidget.h> //ctor: desktop size
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqfontmetrics.h> //paintItem()
|
|
|
|
#include <tqimage.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqobjectlist.h> //used to delete all cover fetchers
|
|
|
|
#include <tqpainter.h> //paintItem()
|
|
|
|
#include <tqpalette.h> //paintItem()
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqpoint.h>
|
|
|
|
#include <tqprogressdialog.h>
|
|
|
|
#include <tqrect.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqtimer.h> //search filter timer
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqvbox.h>
|
|
|
|
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
#include <tdeconfig.h>
|
|
|
|
#include <kcursor.h>
|
|
|
|
#include <tdefiledialog.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <tdelistview.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdemessagebox.h> //showCoverMenu()
|
|
|
|
#include <tdemultipledrag.h>
|
|
|
|
#include <tdeio/netaccess.h>
|
|
|
|
#include <tdepopupmenu.h> //showCoverMenu()
|
|
|
|
#include <kprogress.h>
|
|
|
|
#include <kpushbutton.h>
|
|
|
|
#include <ksqueezedtextlabel.h> //status label
|
|
|
|
#include <kstatusbar.h>
|
|
|
|
#include <kstringhandler.h> //paintItem
|
|
|
|
#include <tdetoolbar.h>
|
|
|
|
#include <tdetoolbarbutton.h> //clear filter button
|
|
|
|
#include <kurl.h>
|
|
|
|
#include <kurldrag.h>
|
|
|
|
#include <twin.h>
|
|
|
|
|
|
|
|
static TQString artistToSelectInInitFunction;
|
|
|
|
CoverManager *CoverManager::s_instance = 0;
|
|
|
|
|
|
|
|
class ArtistItem : public TDEListViewItem
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ArtistItem(TQListView *view, TQListViewItem *item, const TQString &text)
|
|
|
|
: TDEListViewItem(view, item, text) {}
|
|
|
|
protected:
|
|
|
|
int compare( TQListViewItem* i, int col, bool ascending ) const
|
|
|
|
{
|
|
|
|
Q_UNUSED(col);
|
|
|
|
Q_UNUSED(ascending);
|
|
|
|
|
|
|
|
TQString a = text(0);
|
|
|
|
TQString b = i->text(0);
|
|
|
|
|
|
|
|
if ( a.startsWith( "the ", false ) )
|
|
|
|
CollectionView::manipulateThe( a, true );
|
|
|
|
if ( b.startsWith( "the ", false ) )
|
|
|
|
CollectionView::manipulateThe( b, true );
|
|
|
|
|
|
|
|
return TQString::localeAwareCompare( a.lower(), b.lower() );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
CoverManager::CoverManager()
|
|
|
|
: TQSplitter( 0, "TheCoverManager" )
|
|
|
|
, m_timer( new TQTimer( this ) ) //search filter timer
|
|
|
|
, m_fetchCounter( 0 )
|
|
|
|
, m_fetchingCovers( 0 )
|
|
|
|
, m_coversFetched( 0 )
|
|
|
|
, m_coverErrors( 0 )
|
|
|
|
{
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
s_instance = this;
|
|
|
|
|
|
|
|
// Sets caption and icon correctly (needed e.g. for GNOME)
|
|
|
|
kapp->setTopWidget( this );
|
|
|
|
setCaption( kapp->makeStdCaption( i18n("Cover Manager") ) );
|
|
|
|
setWFlags( WDestructiveClose );
|
|
|
|
setMargin( 4 );
|
|
|
|
|
|
|
|
//artist listview
|
|
|
|
m_artistView = new TDEListView( this );
|
|
|
|
m_artistView->addColumn(i18n( "Albums By" ));
|
|
|
|
m_artistView->setFullWidth( true );
|
|
|
|
m_artistView->setSorting( 0 );
|
|
|
|
m_artistView->setMinimumWidth( 180 );
|
|
|
|
ArtistItem *item = 0;
|
|
|
|
|
|
|
|
//load artists from the collection db
|
|
|
|
const TQStringList artists = CollectionDB::instance()->artistList( false, false );
|
|
|
|
foreach( artists )
|
|
|
|
{
|
|
|
|
TQString artist = *it;
|
|
|
|
item = new ArtistItem( m_artistView, item, artist );
|
|
|
|
item->setPixmap( 0, SmallIcon( Amarok::icon( "artist" ) ) );
|
|
|
|
}
|
|
|
|
m_artistView->sort();
|
|
|
|
|
|
|
|
m_artistView->setSorting( -1 );
|
|
|
|
ArtistItem *last = static_cast<ArtistItem *>(m_artistView->lastItem());
|
|
|
|
item = new ArtistItem( m_artistView, 0, i18n( "All Albums" ) );
|
|
|
|
item->setPixmap( 0, SmallIcon( Amarok::icon( "album" ) ) );
|
|
|
|
|
|
|
|
QueryBuilder qb;
|
|
|
|
qb.addReturnValue( QueryBuilder::tabAlbum, QueryBuilder::valName );
|
|
|
|
qb.groupBy( QueryBuilder::tabAlbum, QueryBuilder::valName );
|
|
|
|
qb.setOptions( QueryBuilder::optOnlyCompilations );
|
|
|
|
qb.setLimit( 0, 1 );
|
|
|
|
if ( qb.run().count() ) {
|
|
|
|
item = new ArtistItem( m_artistView, last, i18n( "Various Artists" ) );
|
|
|
|
item->setPixmap( 0, SmallIcon("personal") );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQVBox *vbox = new TQVBox( this );
|
|
|
|
TQHBox *hbox = new TQHBox( vbox );
|
|
|
|
|
|
|
|
vbox->setSpacing( 4 );
|
|
|
|
hbox->setSpacing( 4 );
|
|
|
|
|
|
|
|
{ //<Search LineEdit>
|
|
|
|
TQHBox *searchBox = new TQHBox( hbox );
|
|
|
|
TDEToolBar* searchToolBar = new Browser::ToolBar( searchBox );
|
|
|
|
TDEToolBarButton *button = new TDEToolBarButton( "locationbar_erase", 0, searchToolBar );
|
|
|
|
m_searchEdit = new ClickLineEdit( i18n( "Enter search terms here" ), searchToolBar );
|
|
|
|
m_searchEdit->setFrame( TQFrame::Sunken );
|
|
|
|
|
|
|
|
searchToolBar->setStretchableWidget( m_searchEdit );
|
|
|
|
connect( button, TQT_SIGNAL(clicked()), m_searchEdit, TQT_SLOT(clear()) );
|
|
|
|
|
|
|
|
TQToolTip::add( button, i18n( "Clear search field" ) );
|
|
|
|
TQToolTip::add( m_searchEdit, i18n( "Enter space-separated terms to search in the albums" ) );
|
|
|
|
|
|
|
|
hbox->setStretchFactor( searchBox, 1 );
|
|
|
|
} //</Search LineEdit>
|
|
|
|
|
|
|
|
// view menu
|
|
|
|
m_viewMenu = new TDEPopupMenu( this );
|
|
|
|
m_viewMenu->insertItem( i18n("All Albums"), AllAlbums );
|
|
|
|
m_viewMenu->insertItem( i18n("Albums With Cover"), AlbumsWithCover );
|
|
|
|
m_viewMenu->insertItem( i18n("Albums Without Cover"), AlbumsWithoutCover );
|
|
|
|
m_viewMenu->setItemChecked( AllAlbums, true );
|
|
|
|
connect( m_viewMenu, TQT_SIGNAL( activated(int) ), TQT_SLOT( changeView(int) ) );
|
|
|
|
|
|
|
|
#ifdef AMAZON_SUPPORT
|
|
|
|
// amazon locale menu
|
|
|
|
m_amazonLocaleMenu = new TDEPopupMenu( this );
|
|
|
|
m_amazonLocaleMenu->insertItem( i18n("International"), CoverFetcher::International );
|
|
|
|
m_amazonLocaleMenu->insertItem( i18n("Canada"), CoverFetcher::Canada );
|
|
|
|
m_amazonLocaleMenu->insertItem( i18n("France"), CoverFetcher::France );
|
|
|
|
m_amazonLocaleMenu->insertItem( i18n("Germany"), CoverFetcher::Germany );
|
|
|
|
m_amazonLocaleMenu->insertItem( i18n("Japan"), CoverFetcher::Japan);
|
|
|
|
m_amazonLocaleMenu->insertItem( i18n("United Kingdom"), CoverFetcher::UK );
|
|
|
|
connect( m_amazonLocaleMenu, TQT_SIGNAL( activated(int) ), TQT_SLOT( changeLocale(int) ) );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TDEToolBar* toolBar = new TDEToolBar( hbox );
|
|
|
|
toolBar->setIconText( TDEToolBar::IconTextRight );
|
|
|
|
toolBar->setFrameShape( TQFrame::NoFrame );
|
|
|
|
toolBar->insertButton( "view_choose", 1, m_viewMenu, true, i18n( "View" ) );
|
|
|
|
#ifdef AMAZON_SUPPORT
|
|
|
|
toolBar->insertButton( "babelfish", 2, m_amazonLocaleMenu, true, i18n( "Amazon Locale" ) );
|
|
|
|
|
|
|
|
TQString locale = AmarokConfig::amazonLocale();
|
|
|
|
m_currentLocale = CoverFetcher::localeStringToID( locale );
|
|
|
|
m_amazonLocaleMenu->setItemChecked( m_currentLocale, true );
|
|
|
|
|
|
|
|
//fetch missing covers button
|
|
|
|
m_fetchButton = new KPushButton( KGuiItem( i18n("Fetch Missing Covers"), Amarok::icon( "download" ) ), hbox );
|
|
|
|
connect( m_fetchButton, TQT_SIGNAL(clicked()), TQT_SLOT(fetchMissingCovers()) );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//cover view
|
|
|
|
m_coverView = new CoverView( vbox );
|
|
|
|
|
|
|
|
//status bar
|
|
|
|
KStatusBar *m_statusBar = new KStatusBar( vbox );
|
|
|
|
m_statusBar->addWidget( m_statusLabel = new KSqueezedTextLabel( m_statusBar ), 4 );
|
|
|
|
m_statusLabel->setIndent( 3 );
|
|
|
|
m_statusBar->addWidget( m_progressBox = new TQHBox( m_statusBar ), 1, true );
|
|
|
|
KPushButton *stopButton = new KPushButton( KGuiItem(i18n("Abort"), "stop"), m_progressBox );
|
|
|
|
connect( stopButton, TQT_SIGNAL(clicked()), TQT_SLOT(stopFetching()) );
|
|
|
|
m_progress = new KProgress( m_progressBox );
|
|
|
|
m_progress->setCenterIndicator( true );
|
|
|
|
|
|
|
|
const int h = m_statusLabel->height() + 3;
|
|
|
|
m_statusLabel->setFixedHeight( h );
|
|
|
|
m_progressBox->setFixedHeight( h );
|
|
|
|
m_progressBox->hide();
|
|
|
|
|
|
|
|
|
|
|
|
// signals and slots connections
|
|
|
|
connect( m_artistView, TQT_SIGNAL(selectionChanged( TQListViewItem* ) ),
|
|
|
|
TQT_SLOT(slotArtistSelected( TQListViewItem* )) );
|
|
|
|
connect( m_coverView, TQT_SIGNAL(contextMenuRequested( TQIconViewItem*, const TQPoint& )),
|
|
|
|
TQT_SLOT(showCoverMenu( TQIconViewItem*, const TQPoint& )) );
|
|
|
|
connect( m_coverView, TQT_SIGNAL(executed( TQIconViewItem* )),
|
|
|
|
TQT_SLOT(coverItemExecuted( TQIconViewItem* )) );
|
|
|
|
connect( m_timer, TQT_SIGNAL(timeout()),
|
|
|
|
TQT_SLOT(slotSetFilter()) );
|
|
|
|
connect( m_searchEdit, TQT_SIGNAL(textChanged( const TQString& )),
|
|
|
|
TQT_SLOT(slotSetFilterTimeout()) );
|
|
|
|
|
|
|
|
#ifdef AMAZON_SUPPORT
|
|
|
|
connect( CollectionDB::instance(), TQT_SIGNAL(coverFetched( const TQString&, const TQString& )),
|
|
|
|
TQT_SLOT(coverFetched( const TQString&, const TQString& )) );
|
|
|
|
connect( CollectionDB::instance(), TQT_SIGNAL(coverRemoved( const TQString&, const TQString& )),
|
|
|
|
TQT_SLOT(coverRemoved( const TQString&, const TQString& )) );
|
|
|
|
connect( CollectionDB::instance(), TQT_SIGNAL(coverFetcherError( const TQString& )),
|
|
|
|
TQT_SLOT(coverFetcherError()) );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_currentView = AllAlbums;
|
|
|
|
|
|
|
|
TQSize size = TQApplication::desktop()->screenGeometry( this ).size() / 1.5;
|
|
|
|
resize( Amarok::config( "Cover Manager" )->readSizeEntry( "Window Size", &size ) );
|
|
|
|
|
|
|
|
show();
|
|
|
|
|
|
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(init()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CoverManager::~CoverManager()
|
|
|
|
{
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
Amarok::config( "Cover Manager" )->writeEntry( "Window Size", size() );
|
|
|
|
|
|
|
|
s_instance = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::init()
|
|
|
|
{
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
TQListViewItem *item = 0;
|
|
|
|
|
|
|
|
if ( !artistToSelectInInitFunction.isEmpty() )
|
|
|
|
for ( item = m_artistView->firstChild(); item; item = item->nextSibling() )
|
|
|
|
if ( item->text( 0 ) == artistToSelectInInitFunction )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ( item == 0 )
|
|
|
|
item = m_artistView->firstChild();
|
|
|
|
|
|
|
|
m_artistView->setSelected( item, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CoverViewDialog::CoverViewDialog( const TQString& artist, const TQString& album, TQWidget *parent )
|
|
|
|
: TQDialog( parent, 0, false, WDestructiveClose | WType_TopLevel | WNoAutoErase )
|
|
|
|
, m_pixmap( CollectionDB::instance()->albumImage( artist, album, false, 0 ) )
|
|
|
|
{
|
|
|
|
KWin::setType( winId(), NET::Utility );
|
|
|
|
kapp->setTopWidget( this );
|
|
|
|
setCaption( kapp->makeStdCaption( i18n("%1 - %2").arg( artist, album ) ) );
|
|
|
|
|
|
|
|
m_layout = new TQHBoxLayout( this );
|
|
|
|
m_layout->setAutoAdd( true );
|
|
|
|
m_pixmapViewer = new PixmapViewer( this, m_pixmap );
|
|
|
|
|
|
|
|
setFixedSize( m_pixmapViewer->maximalSize() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::viewCover( const TQString& artist, const TQString& album, TQWidget *parent ) //static
|
|
|
|
{
|
|
|
|
//TQDialog means "escape" works as expected
|
|
|
|
TQDialog *dialog = new CoverViewDialog( artist, album, parent );
|
|
|
|
dialog->show();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString CoverManager::amazonTld() //static
|
|
|
|
{
|
|
|
|
if (AmarokConfig::amazonLocale() == "us")
|
|
|
|
return "com";
|
|
|
|
else if (AmarokConfig::amazonLocale()== "jp")
|
|
|
|
return "co.jp";
|
|
|
|
else if (AmarokConfig::amazonLocale() == "uk")
|
|
|
|
return "co.uk";
|
|
|
|
else if (AmarokConfig::amazonLocale() == "ca")
|
|
|
|
return "ca";
|
|
|
|
else
|
|
|
|
return AmarokConfig::amazonLocale();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::fetchMissingCovers() //SLOT
|
|
|
|
{
|
|
|
|
#ifdef AMAZON_SUPPORT
|
|
|
|
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
for ( TQIconViewItem *item = m_coverView->firstItem(); item; item = item->nextItem() ) {
|
|
|
|
CoverViewItem *coverItem = static_cast<CoverViewItem*>( item );
|
|
|
|
if( !coverItem->hasCover() ) {
|
|
|
|
m_fetchCovers += coverItem->artist() + " @@@ " + coverItem->album();
|
|
|
|
m_fetchingCovers++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !m_fetchCounter ) //loop isn't started yet
|
|
|
|
fetchCoversLoop();
|
|
|
|
|
|
|
|
updateStatusBar();
|
|
|
|
m_fetchButton->setEnabled( false );
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::fetchCoversLoop() //SLOT
|
|
|
|
{
|
|
|
|
#ifdef AMAZON_SUPPORT
|
|
|
|
|
|
|
|
if( m_fetchCounter < m_fetchCovers.count() ) {
|
|
|
|
//get artist and album from keyword
|
|
|
|
const TQStringList values = TQStringList::split( " @@@ ", m_fetchCovers[m_fetchCounter], true );
|
|
|
|
|
|
|
|
if( values.count() > 1 )
|
|
|
|
CollectionDB::instance()->fetchCover( this, values[0], values[1], m_fetchCovers.count() != 1); //edit mode when fetching 1 cover
|
|
|
|
|
|
|
|
m_fetchCounter++;
|
|
|
|
|
|
|
|
// Wait 1 second, since amazon caps the number of accesses per client
|
|
|
|
TQTimer::singleShot( 1000, this, TQT_SLOT( fetchCoversLoop() ) );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_fetchCovers.clear();
|
|
|
|
m_fetchCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::showOnce( const TQString &artist )
|
|
|
|
{
|
|
|
|
if ( !s_instance ) {
|
|
|
|
artistToSelectInInitFunction = artist;
|
|
|
|
new CoverManager(); //shows itself
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
s_instance->setActiveWindow();
|
|
|
|
s_instance->raise();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverManager::slotArtistSelected( TQListViewItem *item ) //SLOT
|
|
|
|
{
|
|
|
|
if( item->depth() ) //album item
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQString artist = item->text(0);
|
|
|
|
|
|
|
|
if( artist.endsWith( ", The" ) )
|
|
|
|
CollectionView::instance()->manipulateThe( artist, false );
|
|
|
|
|
|
|
|
m_coverView->clear();
|
|
|
|
m_coverItems.clear();
|
|
|
|
|
|
|
|
// reset current view mode state to "AllAlbum" which is the default on artist change in left panel
|
|
|
|
m_currentView = AllAlbums;
|
|
|
|
m_viewMenu->setItemChecked( AllAlbums, true );
|
|
|
|
m_viewMenu->setItemChecked( AlbumsWithCover, false );
|
|
|
|
m_viewMenu->setItemChecked( AlbumsWithoutCover, false );
|
|
|
|
|
|
|
|
TQProgressDialog progress( this, 0, true );
|
|
|
|
progress.setLabelText( i18n("Loading Thumbnails...") );
|
|
|
|
progress.TQDialog::setCaption( i18n("...") );
|
|
|
|
|
|
|
|
//NOTE we MUST show the dialog, otherwise the closeEvents get processed
|
|
|
|
// in the processEvents() calls below, GRUMBLE! TQt sux0rs
|
|
|
|
progress.show();
|
|
|
|
progress.repaint( false ); //ensures the dialog isn't blank
|
|
|
|
|
|
|
|
//this is an extra processEvent call for the sake of init() and aesthetics
|
|
|
|
//it isn't necessary
|
|
|
|
kapp->processEvents();
|
|
|
|
|
|
|
|
//this can be a bit slow
|
|
|
|
TQApplication::setOverrideCursor( KCursor::waitCursor() );
|
|
|
|
QueryBuilder qb;
|
|
|
|
TQStringList albums;
|
|
|
|
|
|
|
|
qb.addReturnValue( QueryBuilder::tabArtist, QueryBuilder::valName );
|
|
|
|
qb.addReturnValue( QueryBuilder::tabAlbum, QueryBuilder::valName );
|
|
|
|
|
|
|
|
qb.excludeMatch( QueryBuilder::tabAlbum, i18n( "Unknown" ) );
|
|
|
|
qb.sortBy( QueryBuilder::tabAlbum, QueryBuilder::valName );
|
|
|
|
qb.setOptions( QueryBuilder::optRemoveDuplicates );
|
|
|
|
qb.setOptions( QueryBuilder::optNoCompilations );
|
|
|
|
|
|
|
|
if ( item != m_artistView->firstChild() )
|
|
|
|
qb.addMatches( QueryBuilder::tabArtist, artist );
|
|
|
|
|
|
|
|
albums = qb.run();
|
|
|
|
|
|
|
|
//also retrieve compilations when we're showing all items (first treenode) or
|
|
|
|
//"Various Artists" (last treenode)
|
|
|
|
if ( item == m_artistView->firstChild() || item == m_artistView->lastChild() )
|
|
|
|
{
|
|
|
|
TQStringList cl;
|
|
|
|
|
|
|
|
qb.clear();
|
|
|
|
qb.addReturnValue( QueryBuilder::tabAlbum, QueryBuilder::valName );
|
|
|
|
|
|
|
|
qb.excludeMatch( QueryBuilder::tabAlbum, i18n( "Unknown" ) );
|
|
|
|
qb.sortBy( QueryBuilder::tabAlbum, QueryBuilder::valName );
|
|
|
|
qb.setOptions( QueryBuilder::optRemoveDuplicates );
|
|
|
|
qb.setOptions( QueryBuilder::optOnlyCompilations );
|
|
|
|
cl = qb.run();
|
|
|
|
|
|
|
|
for ( uint i = 0; i < cl.count(); i++ ) {
|
|
|
|
albums.append( i18n( "Various Artists" ) );
|
|
|
|
albums.append( cl[ i ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQApplication::restoreOverrideCursor();
|
|
|
|
|
|
|
|
progress.setTotalSteps( (albums.count()/2) + (albums.count()/10) );
|
|
|
|
|
|
|
|
//insert the covers first because the list view is soooo paint-happy
|
|
|
|
//doing it in the second loop looks really bad, unfortunately
|
|
|
|
//this is the slowest step in the bit that we can't process events
|
|
|
|
uint x = 0;
|
|
|
|
foreach( albums )
|
|
|
|
{
|
|
|
|
const TQString artist = *it;
|
|
|
|
const TQString album = *(++it);
|
|
|
|
m_coverItems.append( new CoverViewItem( m_coverView, m_coverView->lastItem(), artist, album ) );
|
|
|
|
|
|
|
|
if ( ++x % 50 == 0 ) {
|
|
|
|
progress.setProgress( x / 5 ); // we do it less often due to bug in TQt, ask Max
|
|
|
|
kapp->processEvents(); // TQProgressDialog also calls this, but not always due to TQt bug!
|
|
|
|
|
|
|
|
//only worth testing for after processEvents() is called
|
|
|
|
if( progress.wasCancelled() )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//now, load the thumbnails
|
|
|
|
for( TQIconViewItem *item = m_coverView->firstItem(); item; item = item->nextItem() ) {
|
|
|
|
progress.setProgress( progress.progress() + 1 );
|
|
|
|
kapp->processEvents();
|
|
|
|
|
|
|
|
if( progress.wasCancelled() )
|
|
|
|
break;
|
|
|
|
|
|
|
|
static_cast<CoverViewItem*>(item)->loadCover();
|
|
|
|
}
|
|
|
|
|
|
|
|
updateStatusBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverManager::showCoverMenu( TQIconViewItem *item, const TQPoint &p ) //SLOT
|
|
|
|
{
|
|
|
|
#define item static_cast<CoverViewItem*>(item)
|
|
|
|
if( !item ) return;
|
|
|
|
|
|
|
|
enum { SHOW, FETCH, CUSTOM, DELETE, APPEND };
|
|
|
|
|
|
|
|
TDEPopupMenu menu;
|
|
|
|
|
|
|
|
menu.insertTitle( i18n( "Cover Image" ) );
|
|
|
|
|
|
|
|
TQPtrList<CoverViewItem> selected = selectedItems();
|
|
|
|
if( selected.count() > 1 ) {
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "download" ) ), i18n( "&Fetch Selected Covers" ), FETCH );
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "files" ) ), i18n( "Set &Custom Cover for Selected Albums" ), CUSTOM );
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "remove" ) ), i18n( "&Unset Selected Covers" ), DELETE );
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "add_playlist" ) ), i18n( "&Append to Playlist" ), APPEND );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "zoom" ) ), i18n( "&Show Fullsize" ), SHOW );
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "download" ) ), i18n( "&Fetch From amazon.%1" ).arg( CoverManager::amazonTld() ), FETCH );
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "files" ) ), i18n( "Set &Custom Cover" ), CUSTOM );
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "add_playlist" ) ), i18n( "&Append to Playlist" ), APPEND );
|
|
|
|
menu.insertSeparator();
|
|
|
|
|
|
|
|
menu.insertItem( SmallIconSet( Amarok::icon( "remove" ) ), i18n( "&Unset Cover" ), DELETE );
|
|
|
|
menu.setItemEnabled( SHOW, item->hasCover() );
|
|
|
|
menu.setItemEnabled( DELETE, item->canRemoveCover() );
|
|
|
|
}
|
|
|
|
#ifndef AMAZON_SUPPORT
|
|
|
|
menu.setItemEnabled( FETCH, false );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
switch( menu.exec(p) ) {
|
|
|
|
case SHOW:
|
|
|
|
viewCover( item->artist(), item->album(), this );
|
|
|
|
break;
|
|
|
|
|
|
|
|
#ifdef AMAZON_SUPPORT
|
|
|
|
case FETCH:
|
|
|
|
fetchSelectedCovers();
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
case CUSTOM:
|
|
|
|
{
|
|
|
|
setCustomSelectedCovers();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case DELETE:
|
|
|
|
deleteSelectedCovers();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case APPEND:
|
|
|
|
{
|
|
|
|
CoverViewItem* sel;
|
|
|
|
for ( sel = selected.first(); sel; sel = selected.next() )
|
|
|
|
{
|
|
|
|
TQString artist_id;
|
|
|
|
TQString album_id;
|
|
|
|
artist_id.setNum( CollectionDB::instance()->artistID( sel->artist() ) );
|
|
|
|
album_id.setNum( CollectionDB::instance()->albumID( sel->album() ) );
|
|
|
|
Playlist::instance()->insertMedia( CollectionDB::instance()->albumTracks( artist_id, album_id ), Playlist::Append );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default: ;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef item
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverManager::coverItemExecuted( TQIconViewItem *item ) //SLOT
|
|
|
|
{
|
|
|
|
#define item static_cast<CoverViewItem*>(item)
|
|
|
|
|
|
|
|
if( !item ) return;
|
|
|
|
|
|
|
|
item->setSelected( true );
|
|
|
|
if ( item->hasCover() )
|
|
|
|
viewCover( item->artist(), item->album(), this );
|
|
|
|
else
|
|
|
|
fetchSelectedCovers();
|
|
|
|
|
|
|
|
#undef item
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::slotSetFilter() //SLOT
|
|
|
|
{
|
|
|
|
m_filter = m_searchEdit->text();
|
|
|
|
|
|
|
|
m_coverView->selectAll( false);
|
|
|
|
TQIconViewItem *item = m_coverView->firstItem();
|
|
|
|
while ( item )
|
|
|
|
{
|
|
|
|
TQIconViewItem *tmp = item->nextItem();
|
|
|
|
m_coverView->takeItem( item );
|
|
|
|
item = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_coverView->setAutoArrange( false );
|
|
|
|
for( TQIconViewItem *item = m_coverItems.first(); item; item = m_coverItems.next() )
|
|
|
|
{
|
|
|
|
CoverViewItem *coverItem = static_cast<CoverViewItem*>(item);
|
|
|
|
if( coverItem->album().contains( m_filter, false ) || coverItem->artist().contains( m_filter, false ) )
|
|
|
|
m_coverView->insertItem( item, m_coverView->lastItem() );
|
|
|
|
}
|
|
|
|
m_coverView->setAutoArrange( true );
|
|
|
|
|
|
|
|
m_coverView->arrangeItemsInGrid();
|
|
|
|
updateStatusBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::slotSetFilterTimeout() //SLOT
|
|
|
|
{
|
|
|
|
if ( m_timer->isActive() ) m_timer->stop();
|
|
|
|
m_timer->start( 180, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::changeView( int id ) //SLOT
|
|
|
|
{
|
|
|
|
if( m_currentView == id ) return;
|
|
|
|
|
|
|
|
//clear the iconview without deleting items
|
|
|
|
m_coverView->selectAll( false);
|
|
|
|
TQIconViewItem *item = m_coverView->firstItem();
|
|
|
|
while ( item ) {
|
|
|
|
TQIconViewItem *tmp = item->nextItem();
|
|
|
|
m_coverView->takeItem( item );
|
|
|
|
item = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_coverView->setAutoArrange(false );
|
|
|
|
for( TQIconViewItem *item = m_coverItems.first(); item; item = m_coverItems.next() ) {
|
|
|
|
bool show = false;
|
|
|
|
CoverViewItem *coverItem = static_cast<CoverViewItem*>(item);
|
|
|
|
if( !m_filter.isEmpty() ) {
|
|
|
|
if( !coverItem->album().contains( m_filter, false ) && !coverItem->artist().contains( m_filter, false ) )
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( id == AllAlbums ) //show all albums
|
|
|
|
show = true;
|
|
|
|
else if( id == AlbumsWithCover && coverItem->hasCover() ) //show only albums with cover
|
|
|
|
show = true;
|
|
|
|
else if( id == AlbumsWithoutCover && !coverItem->hasCover() ) //show only albums without cover
|
|
|
|
show = true;
|
|
|
|
|
|
|
|
if( show ) m_coverView->insertItem( item, m_coverView->lastItem() );
|
|
|
|
}
|
|
|
|
m_coverView->setAutoArrange( true );
|
|
|
|
|
|
|
|
m_viewMenu->setItemChecked( m_currentView, false );
|
|
|
|
m_viewMenu->setItemChecked( id, true );
|
|
|
|
|
|
|
|
m_coverView->arrangeItemsInGrid();
|
|
|
|
m_currentView = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverManager::changeLocale( int id ) //SLOT
|
|
|
|
{
|
|
|
|
TQString locale = CoverFetcher::localeIDToString( id );
|
|
|
|
AmarokConfig::setAmazonLocale( locale );
|
|
|
|
m_amazonLocaleMenu->setItemChecked( m_currentLocale, false );
|
|
|
|
m_amazonLocaleMenu->setItemChecked( id, true );
|
|
|
|
m_currentLocale = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::coverFetched( const TQString &artist, const TQString &album ) //SLOT
|
|
|
|
{
|
|
|
|
loadCover( artist, album );
|
|
|
|
m_coversFetched++;
|
|
|
|
updateStatusBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::coverRemoved( const TQString &artist, const TQString &album ) //SLOT
|
|
|
|
{
|
|
|
|
loadCover( artist, album );
|
|
|
|
m_coversFetched--;
|
|
|
|
updateStatusBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::coverFetcherError()
|
|
|
|
{
|
|
|
|
DEBUG_FUNC_INFO
|
|
|
|
|
|
|
|
m_coverErrors++;
|
|
|
|
updateStatusBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::stopFetching()
|
|
|
|
{
|
|
|
|
Debug::Block block( __PRETTY_FUNCTION__ );
|
|
|
|
|
|
|
|
m_fetchCovers.clear();
|
|
|
|
m_fetchCounter = 0;
|
|
|
|
|
|
|
|
//delete all cover fetchers
|
|
|
|
TQObjectList* list = queryList( "CoverFetcher" );
|
|
|
|
for( TQObject *obj = list->first(); obj; obj = list->next() )
|
|
|
|
obj->deleteLater();
|
|
|
|
|
|
|
|
delete list;
|
|
|
|
|
|
|
|
m_fetchingCovers = 0;
|
|
|
|
updateStatusBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
// PRIVATE
|
|
|
|
|
|
|
|
void CoverManager::loadCover( const TQString &artist, const TQString &album )
|
|
|
|
{
|
|
|
|
for( TQIconViewItem *item = m_coverItems.first(); item; item = m_coverItems.next() )
|
|
|
|
{
|
|
|
|
CoverViewItem *coverItem = static_cast<CoverViewItem*>(item);
|
|
|
|
if ( album == coverItem->album() && ( artist == coverItem->artist() || ( artist.isEmpty() && coverItem->artist().isEmpty() ) ) )
|
|
|
|
{
|
|
|
|
coverItem->loadCover();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverManager::setCustomSelectedCovers()
|
|
|
|
{
|
|
|
|
//function assumes something is selected
|
|
|
|
TQPtrList<CoverViewItem> selected = selectedItems();
|
|
|
|
CoverViewItem* first = selected.getFirst();
|
|
|
|
|
|
|
|
TQString artist_id; artist_id.setNum( CollectionDB::instance()->artistID( first->artist() ) );
|
|
|
|
TQString album_id; album_id.setNum( CollectionDB::instance()->albumID( first->album() ) );
|
|
|
|
TQStringList values = CollectionDB::instance()->albumTracks( artist_id, album_id );
|
|
|
|
|
|
|
|
TQString startPath = ":homedir";
|
|
|
|
if ( !values.isEmpty() ) {
|
|
|
|
KURL url;
|
|
|
|
url.setPath( values.first() );
|
|
|
|
startPath = url.directory();
|
|
|
|
}
|
|
|
|
KURL file = KFileDialog::getImageOpenURL( startPath, this, i18n( "Select Cover Image File" ) );
|
|
|
|
if ( !file.isEmpty() ) {
|
|
|
|
tqApp->processEvents(); //it may takes a while so process pending events
|
|
|
|
TQString tmpFile;
|
|
|
|
TQImage image = CollectionDB::fetchImage(file, tmpFile);
|
|
|
|
for ( CoverViewItem* item = selected.first(); item; item = selected.next() ) {
|
|
|
|
CollectionDB::instance()->setAlbumImage( item->artist(), item->album(), image );
|
|
|
|
item->loadCover();
|
|
|
|
}
|
|
|
|
TDEIO::NetAccess::removeTempFile( tmpFile );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverManager::fetchSelectedCovers()
|
|
|
|
{
|
|
|
|
TQPtrList<CoverViewItem> selected = selectedItems();
|
|
|
|
for ( CoverViewItem* item = selected.first(); item; item = selected.next() )
|
|
|
|
m_fetchCovers += item->artist() + " @@@ " + item->album();
|
|
|
|
|
|
|
|
m_fetchingCovers += selected.count();
|
|
|
|
|
|
|
|
if( !m_fetchCounter ) //loop isn't started yet
|
|
|
|
fetchCoversLoop();
|
|
|
|
|
|
|
|
updateStatusBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::deleteSelectedCovers()
|
|
|
|
{
|
|
|
|
TQPtrList<CoverViewItem> selected = selectedItems();
|
|
|
|
|
|
|
|
int button = KMessageBox::warningContinueCancel( this,
|
|
|
|
i18n( "Are you sure you want to remove this cover from the Collection?",
|
|
|
|
"Are you sure you want to delete these %n covers from the Collection?",
|
|
|
|
selected.count() ),
|
|
|
|
TQString(),
|
|
|
|
KStdGuiItem::del() );
|
|
|
|
|
|
|
|
if ( button == KMessageBox::Continue ) {
|
|
|
|
for ( CoverViewItem* item = selected.first(); item; item = selected.next() ) {
|
|
|
|
tqApp->processEvents();
|
|
|
|
if ( CollectionDB::instance()->removeAlbumImage( item->artist(), item->album() ) ) //delete selected cover
|
|
|
|
coverRemoved( item->artist(), item->album() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQPtrList<CoverViewItem> CoverManager::selectedItems()
|
|
|
|
{
|
|
|
|
TQPtrList<CoverViewItem> selectedItems;
|
|
|
|
for ( TQIconViewItem* item = m_coverView->firstItem(); item; item = item->nextItem() )
|
|
|
|
if ( item->isSelected() )
|
|
|
|
selectedItems.append( static_cast<CoverViewItem*>(item) );
|
|
|
|
|
|
|
|
return selectedItems;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverManager::updateStatusBar()
|
|
|
|
{
|
|
|
|
TQString text;
|
|
|
|
|
|
|
|
//cover fetching info
|
|
|
|
if( m_fetchingCovers ) {
|
|
|
|
//update the progress bar
|
|
|
|
m_progress->setTotalSteps( m_fetchingCovers );
|
|
|
|
m_progress->setProgress( m_coversFetched + m_coverErrors );
|
|
|
|
if( m_progressBox->isHidden() )
|
|
|
|
m_progressBox->show();
|
|
|
|
|
|
|
|
//update the status text
|
|
|
|
if( m_coversFetched + m_coverErrors >= m_progress->totalSteps() ) {
|
|
|
|
//fetching finished
|
|
|
|
text = i18n( "Finished." );
|
|
|
|
if( m_coverErrors )
|
|
|
|
text += i18n( " Cover not found", " <b>%n</b> covers not found", m_coverErrors );
|
|
|
|
//reset counters
|
|
|
|
m_fetchingCovers = 0;
|
|
|
|
m_coversFetched = 0;
|
|
|
|
m_coverErrors = 0;
|
|
|
|
TQTimer::singleShot( 2000, this, TQT_SLOT( updateStatusBar() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_fetchingCovers == 1 ) {
|
|
|
|
TQStringList values = TQStringList::split( " @@@ ", m_fetchCovers[0], true ); //get artist and album name
|
|
|
|
if ( values.count() >= 2 )
|
|
|
|
{
|
|
|
|
if( values[0].isEmpty() )
|
|
|
|
text = i18n( "Fetching cover for %1..." ).arg( values[1] );
|
|
|
|
else
|
|
|
|
text = i18n( "Fetching cover for %1 - %2..." ).arg( values[0], values[1] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( m_fetchingCovers ) {
|
|
|
|
text = i18n( "Fetching 1 cover: ", "Fetching <b>%n</b> covers... : ", m_fetchingCovers );
|
|
|
|
if( m_coversFetched )
|
|
|
|
text += i18n( "1 fetched", "%n fetched", m_coversFetched );
|
|
|
|
if( m_coverErrors ) {
|
|
|
|
if( m_coversFetched ) text += i18n(" - ");
|
|
|
|
text += i18n( "1 not found", "%n not found", m_coverErrors );
|
|
|
|
}
|
|
|
|
if( m_coversFetched + m_coverErrors == 0 )
|
|
|
|
text += i18n( "Connecting..." );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_coversFetched = 0;
|
|
|
|
m_coverErrors = 0;
|
|
|
|
|
|
|
|
uint totalCounter = 0, missingCounter = 0;
|
|
|
|
|
|
|
|
if( m_progressBox->isShown() )
|
|
|
|
m_progressBox->hide();
|
|
|
|
|
|
|
|
//album info
|
|
|
|
for( TQIconViewItem *item = m_coverView->firstItem(); item; item = item->nextItem() ) {
|
|
|
|
totalCounter++;
|
|
|
|
if( !static_cast<CoverViewItem*>( item )->hasCover() )
|
|
|
|
missingCounter++; //counter for albums without cover
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !m_filter.isEmpty() )
|
|
|
|
text = i18n( "1 result for \"%1\"", "%n results for \"%1\"", totalCounter ).arg( m_filter );
|
|
|
|
else if( m_artistView->selectedItem() ) {
|
|
|
|
text = i18n( "1 album", "%n albums", totalCounter );
|
|
|
|
if( m_artistView->selectedItem() != m_artistView->firstChild() ) //showing albums by an artist
|
|
|
|
{
|
|
|
|
TQString artist = m_artistView->selectedItem()->text(0);
|
|
|
|
if( artist.endsWith( ", The" ) )
|
|
|
|
CollectionView::instance()->manipulateThe( artist, false );
|
|
|
|
text += i18n( " by " ) + artist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( missingCounter )
|
|
|
|
text += i18n(" - ( <b>%1</b> without cover )" ).arg( missingCounter );
|
|
|
|
|
|
|
|
#ifdef AMAZON_SUPPORT
|
|
|
|
m_fetchButton->setEnabled( missingCounter );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
m_statusLabel->setText( text );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverManager::setStatusText( TQString text )
|
|
|
|
{
|
|
|
|
m_oldStatusText = m_statusLabel->text();
|
|
|
|
m_statusLabel->setText( text );
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// CLASS CoverView
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
CoverView::CoverView( TQWidget *parent, const char *name, WFlags f )
|
|
|
|
: TDEIconView( parent, name, f )
|
|
|
|
{
|
|
|
|
Debug::Block block( __PRETTY_FUNCTION__ );
|
|
|
|
|
|
|
|
setArrangement( TQIconView::LeftToRight );
|
|
|
|
setResizeMode( TQIconView::Adjust );
|
|
|
|
setSelectionMode( TQIconView::Extended );
|
|
|
|
arrangeItemsInGrid();
|
|
|
|
setAutoArrange( true );
|
|
|
|
setItemsMovable( false );
|
|
|
|
|
|
|
|
// as long as TQIconView only shows tooltips when the cursor is over the
|
|
|
|
// icon (and not the text), we have to create our own tooltips
|
|
|
|
setShowToolTips( false );
|
|
|
|
|
|
|
|
connect( this, TQT_SIGNAL( onItem( TQIconViewItem * ) ), TQT_SLOT( setStatusText( TQIconViewItem * ) ) );
|
|
|
|
connect( this, TQT_SIGNAL( onViewport() ), CoverManager::instance(), TQT_SLOT( updateStatusBar() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQDragObject *CoverView::dragObject()
|
|
|
|
{
|
|
|
|
CoverViewItem *item = static_cast<CoverViewItem*>( currentItem() );
|
|
|
|
if( !item )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const TQString sql = "SELECT tags.url FROM tags, album WHERE album.name %1 AND tags.album = album.id ORDER BY tags.track;";
|
|
|
|
const TQStringList values = CollectionDB::instance()->query( sql.arg( CollectionDB::likeCondition( item->album() ) ) );
|
|
|
|
|
|
|
|
KURL::List urls;
|
|
|
|
for( TQStringList::ConstIterator it = values.begin(), end = values.end(); it != end; ++it )
|
|
|
|
urls += *it;
|
|
|
|
|
|
|
|
TQString imagePath = CollectionDB::instance()->albumImage( item->artist(), item->album(), false, 1 );
|
|
|
|
KMultipleDrag *drag = new KMultipleDrag( this );
|
|
|
|
drag->setPixmap( item->coverPixmap() );
|
|
|
|
drag->addDragObject( new TQIconDrag( this ) );
|
|
|
|
drag->addDragObject( new TQImageDrag( TQImage( imagePath ) ) );
|
|
|
|
drag->addDragObject( new KURLDrag( urls ) );
|
|
|
|
|
|
|
|
return drag;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverView::setStatusText( TQIconViewItem *item )
|
|
|
|
{
|
|
|
|
#define item static_cast<CoverViewItem *>( item )
|
|
|
|
if ( !item )
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool sampler = false;
|
|
|
|
//compilations have valDummy for artist. see QueryBuilder::addReturnValue(..) for explanation
|
|
|
|
//FIXME: Don't rely on other independent code, use an sql query
|
|
|
|
if( item->artist().isEmpty() ) sampler = true;
|
|
|
|
|
|
|
|
TQString tipContent = i18n( "%1 - %2" ).arg( sampler ? i18n("Various Artists") : item->artist() )
|
|
|
|
.arg( item->album() );
|
|
|
|
|
|
|
|
CoverManager::instance()->setStatusText( tipContent );
|
|
|
|
|
|
|
|
#undef item
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// CLASS CoverViewItem
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
CoverViewItem::CoverViewItem( TQIconView *parent, TQIconViewItem *after, const TQString &artist, const TQString &album )
|
|
|
|
: TDEIconViewItem( parent, after, album )
|
|
|
|
, m_artist( artist )
|
|
|
|
, m_album( album )
|
|
|
|
, m_coverImagePath( CollectionDB::instance()->albumImage( m_artist, m_album, false, 0, &m_embedded ) )
|
|
|
|
, m_coverPixmap( 0 )
|
|
|
|
{
|
|
|
|
setDragEnabled( true );
|
|
|
|
setDropEnabled( true );
|
|
|
|
calcRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CoverViewItem::hasCover() const
|
|
|
|
{
|
|
|
|
return !m_coverImagePath.endsWith( "nocover.png" ) && TQFile::exists( m_coverImagePath );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoverViewItem::loadCover()
|
|
|
|
{
|
|
|
|
m_coverImagePath = CollectionDB::instance()->albumImage( m_artist, m_album, false, 1, &m_embedded );
|
|
|
|
m_coverPixmap = TQPixmap( m_coverImagePath ); //create the scaled cover
|
|
|
|
|
|
|
|
repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverViewItem::calcRect( const TQString& )
|
|
|
|
{
|
|
|
|
int thumbWidth = AmarokConfig::coverPreviewSize();
|
|
|
|
|
|
|
|
TQFontMetrics fm = iconView()->fontMetrics();
|
|
|
|
TQRect itemPixmapRect( 5, 1, thumbWidth, thumbWidth );
|
|
|
|
TQRect itemRect = rect();
|
|
|
|
itemRect.setWidth( thumbWidth + 10 );
|
|
|
|
itemRect.setHeight( thumbWidth + fm.lineSpacing() + 2 );
|
|
|
|
TQRect itemTextRect( 0, thumbWidth+2, itemRect.width(), fm.lineSpacing() );
|
|
|
|
|
|
|
|
setPixmapRect( itemPixmapRect );
|
|
|
|
setTextRect( itemTextRect );
|
|
|
|
setItemRect( itemRect );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverViewItem::paintItem(TQPainter* p, const TQColorGroup& cg)
|
|
|
|
{
|
|
|
|
TQRect itemRect = rect();
|
|
|
|
|
|
|
|
p->save();
|
|
|
|
p->translate( itemRect.x(), itemRect.y() );
|
|
|
|
|
|
|
|
// draw the border
|
|
|
|
p->setPen( cg.mid() );
|
|
|
|
p->drawRect( 0, 0, itemRect.width(), pixmapRect().height()+2 );
|
|
|
|
|
|
|
|
// draw the cover image
|
|
|
|
if( !m_coverPixmap.isNull() )
|
|
|
|
p->drawPixmap( pixmapRect().x() + (pixmapRect().width() - m_coverPixmap.width())/2,
|
|
|
|
pixmapRect().y() + (pixmapRect().height() - m_coverPixmap.height())/2, m_coverPixmap );
|
|
|
|
|
|
|
|
//justify the album name
|
|
|
|
TQString str = text();
|
|
|
|
TQFontMetrics fm = p->fontMetrics();
|
|
|
|
int nameWidth = fm.width( str );
|
|
|
|
if( nameWidth > textRect().width() )
|
|
|
|
{
|
|
|
|
str = KStringHandler::rPixelSqueeze( str, p->fontMetrics(), textRect().width() );
|
|
|
|
}
|
|
|
|
p->setPen( cg.text() );
|
|
|
|
p->drawText( textRect(), TQt::AlignCenter, str );
|
|
|
|
|
|
|
|
if( isSelected() ) {
|
|
|
|
p->setPen( cg.highlight() );
|
|
|
|
p->drawRect( pixmapRect() );
|
|
|
|
p->drawRect( pixmapRect().left()+1, pixmapRect().top()+1, pixmapRect().width()-2, pixmapRect().height()-2);
|
|
|
|
p->drawRect( pixmapRect().left()+2, pixmapRect().top()+2, pixmapRect().width()-4, pixmapRect().height()-4);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverViewItem::dropped( TQDropEvent *e, const TQValueList<TQIconDragItem> & )
|
|
|
|
{
|
|
|
|
if( TQImageDrag::canDecode( e ) ) {
|
|
|
|
if( hasCover() ) {
|
|
|
|
int button = KMessageBox::warningContinueCancel( iconView(),
|
|
|
|
i18n( "Are you sure you want to overwrite this cover?"),
|
|
|
|
i18n("Overwrite Confirmation"),
|
|
|
|
i18n("&Overwrite") );
|
|
|
|
if( button == KMessageBox::Cancel )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQImage img;
|
|
|
|
TQImageDrag::decode( e, img );
|
|
|
|
CollectionDB::instance()->setAlbumImage( artist(), album(), img );
|
|
|
|
m_coverImagePath = CollectionDB::instance()->albumImage( m_artist, m_album, false, 0 );
|
|
|
|
loadCover();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverViewItem::dragEntered()
|
|
|
|
{
|
|
|
|
setSelected( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoverViewItem::dragLeft()
|
|
|
|
{
|
|
|
|
setSelected( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "covermanager.moc"
|