summaryrefslogtreecommitdiffstats
path: root/amarok/src/tracktooltip.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'amarok/src/tracktooltip.cpp')
-rw-r--r--amarok/src/tracktooltip.cpp351
1 files changed, 351 insertions, 0 deletions
diff --git a/amarok/src/tracktooltip.cpp b/amarok/src/tracktooltip.cpp
new file mode 100644
index 00000000..08cae102
--- /dev/null
+++ b/amarok/src/tracktooltip.cpp
@@ -0,0 +1,351 @@
+/*
+ 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.
+*/
+
+/*
+ tracktooltip.cpp
+ begin: Tue 10 Feb 2004
+ copyright: (C) 2004 by Christian Muehlhaeuser
+ email: chris@chris.de
+
+ copyright: (C) 2005 by Gábor Lehel
+ email: illissius@gmail.com
+*/
+
+#include "amarok.h"
+#include "app.h"
+#include "amarokconfig.h"
+#include "debug.h"
+#include "metabundle.h"
+#include "moodbar.h"
+#include "collectiondb.h"
+#include "playlist.h"
+#include "playlistitem.h"
+#include "podcastbundle.h"
+#include <tqapplication.h>
+#include <kstandarddirs.h>
+
+
+#include "tracktooltip.h"
+
+
+TrackToolTip *TrackToolTip::instance()
+{
+ static TrackToolTip tip;
+ return &tip;
+}
+
+TrackToolTip::TrackToolTip(): m_haspos( false )
+{
+ connect( CollectionDB::instance(), TQT_SIGNAL( coverChanged( const TQString &, const TQString & ) ),
+ this, TQT_SLOT( slotCoverChanged( const TQString &, const TQString & ) ) );
+ connect( CollectionDB::instance(), TQT_SIGNAL( imageFetched( const TQString & ) ),
+ this, TQT_SLOT( slotImageChanged( const TQString & ) ) );
+ connect( Playlist::instance(), TQT_SIGNAL( columnsChanged() ), this, TQT_SLOT( slotUpdate() ) );
+ connect( CollectionDB::instance(), TQT_SIGNAL( scoreChanged( const TQString&, float ) ),
+ this, TQT_SLOT( slotUpdate( const TQString& ) ) );
+ connect( CollectionDB::instance(), TQT_SIGNAL( ratingChanged( const TQString&, int ) ),
+ this, TQT_SLOT( slotUpdate( const TQString& ) ) );
+ // Only connect this once -- m_tags exists for the lifetime of this instance
+ connect( &m_tags.moodbar(), TQT_SIGNAL( jobEvent( int ) ),
+ TQT_SLOT( slotMoodbarEvent() ) );
+ // This is so the moodbar can be re-rendered when AlterMood is changed
+ connect( App::instance(), TQT_SIGNAL( moodbarPrefs( bool, bool, int, bool ) ),
+ TQT_SLOT( slotMoodbarEvent() ) );
+ clear();
+}
+
+void TrackToolTip::addToWidget( TQWidget *widget )
+{
+ if( widget && !m_widgets.containsRef( widget ) )
+ {
+ m_widgets.append( widget );
+ Amarok::ToolTip::add( this, widget );
+ }
+}
+
+void TrackToolTip::removeFromWidget( TQWidget *widget )
+{
+ if( widget && m_widgets.containsRef( widget ) )
+ {
+ Amarok::ToolTip::remove( widget );
+ m_widgets.removeRef( widget );
+ }
+}
+
+
+#define MOODBAR_WIDTH 150
+
+void TrackToolTip::setTrack( const MetaBundle &tags, bool force )
+{
+ if( force || m_tags != tags || m_tags.url() != tags.url() )
+ {
+ m_haspos = false;
+ m_tooltip = TQString();
+
+ TQStringList left, right;
+ const TQString tableRow = "<tr><td width=70 align=right>%1:</td><td align=left>%2</td></tr>";
+
+ TQString filename = "", title = ""; //special case these, put the first one encountered on top
+
+ Playlist *playlist = Playlist::instance();
+ const int n = playlist->numVisibleColumns();
+ for( int i = 0; i < n; ++i )
+ {
+ const int column = playlist->mapToLogicalColumn( i );
+
+ if( column == PlaylistItem::Score )
+ {
+ const float score = CollectionDB::instance()->getSongPercentage( tags.url().path() );
+ if( score > 0.f )
+ {
+ right << TQString::number( score, 'f', 2 ); // 2 digits after decimal point
+ left << playlist->columnText( column );
+ }
+ }
+ else if( column == PlaylistItem::Rating )
+ {
+ const int rating = CollectionDB::instance()->getSongRating( tags.url().path() );
+ if( rating > 0 )
+ {
+ TQString s;
+ for( int i = 0; i < rating / 2; ++i )
+ s += TQString( "<img src=\"%1\" height=\"%2\" width=\"%3\">" )
+ .arg( locate( "data", "amarok/images/star.png" ) )
+ .arg( TQFontMetrics( TQToolTip::font() ).height() )
+ .arg( TQFontMetrics( TQToolTip::font() ).height() );
+ if( rating % 2 )
+ s += TQString( "<img src=\"%1\" height=\"%2\" width=\"%3\">" )
+ .arg( locate( "data", "amarok/images/smallstar.png" ) )
+ .arg( TQFontMetrics( TQToolTip::font() ).height() )
+ .arg( TQFontMetrics( TQToolTip::font() ).height() );
+ right << s;
+ left << playlist->columnText( column );
+ }
+ }
+ else if( column == PlaylistItem::Mood )
+ {
+ if( !AmarokConfig::showMoodbar() )
+ continue;
+
+ m_tags.moodbar().load();
+
+ switch( tags.moodbar_const().state() )
+ {
+ case Moodbar::JobQueued:
+ case Moodbar::JobRunning:
+ right << tags.prettyText( column );
+ left << playlist->columnText( column );
+ break;
+
+ case Moodbar::Loaded:
+ {
+ // Ok so this is a hack, but it works quite well.
+ // Save an image in the user's home directory just so
+ // it can be referenced in an <img> tag. Store which
+ // moodbar is saved in m_moodbarURL so we don't have
+ // to re-save it every second.
+ left << playlist->columnText( column );
+ TQString filename = ::locateLocal( "data",
+ "amarok/mood_tooltip.png" );
+ int height = TQFontMetrics( TQToolTip::font() ).height() - 2;
+
+ if( m_moodbarURL != tags.url().url() )
+ {
+ TQPixmap moodbar
+ = const_cast<MetaBundle&>( tags ).moodbar().draw(
+ MOODBAR_WIDTH, height );
+ moodbar.save( filename, "PNG", 100 );
+ m_moodbarURL = tags.url().url();
+ }
+
+ right << TQString( "<img src=\"%1\" height=\"%2\" width=\"%3\">" )
+ .arg( filename ).arg( height ).arg( MOODBAR_WIDTH );
+ }
+ break;
+
+ default:
+ // no tag
+ break;
+ }
+ }
+ else if( column == PlaylistItem::PlayCount )
+ {
+ const int count = CollectionDB::instance()->getPlayCount( tags.url().path() );
+ if( count > 0 )
+ {
+ right << TQString::number( count );
+ left << playlist->columnText( column );
+ }
+ }
+ else if( column == PlaylistItem::LastPlayed )
+ {
+ const uint lastPlayed = CollectionDB::instance()->getLastPlay( tags.url().path() ).toTime_t();
+ right << Amarok::verboseTimeSince( lastPlayed );
+ left << playlist->columnText( column );
+ }
+ else if( column == PlaylistItem::Filename && title.isEmpty() )
+ filename = tags.prettyText( column );
+ else if( column == PlaylistItem::Title && filename.isEmpty() )
+ title = tags.prettyText( column );
+ else if( column != PlaylistItem::Length )
+ {
+ const TQString tag = tags.prettyText( column );
+ if( !tag.isEmpty() )
+ {
+ right << tag;
+ left << playlist->columnText( column );
+ }
+ }
+ }
+
+ if( !filename.isEmpty() )
+ {
+ right.prepend( filename );
+ left.prepend( playlist->columnText( PlaylistItem::Filename ) );
+ }
+ else if( !title.isEmpty() )
+ {
+ right.prepend( title );
+ left.prepend( playlist->columnText( PlaylistItem::Title ) );
+ }
+
+ if( tags.length() > 0 ) //special case this too, always on the bottom
+ {
+ m_haspos = true;
+ right << "%9 / " + tags.prettyLength();
+ left << playlist->columnText( PlaylistItem::Length );
+ }
+
+ //NOTE it seems to be necessary to <center> each element indivdually
+ m_tooltip += "<center><b>Amarok</b></center><table cellpadding='2' cellspacing='2' align='center'><tr>";
+
+ m_tooltip += "%1"; //the cover gets substituted in, in tooltip()
+ m_cover = CollectionDB::instance()->podcastImage( tags, true );
+ if( m_cover.isEmpty() || m_cover.contains( "nocover" ) != -1 )
+ {
+ m_cover = CollectionDB::instance()->albumImage( tags, true, 150 );
+ if ( m_cover == CollectionDB::instance()->notAvailCover() )
+ m_cover = TQString();
+ }
+
+ m_tooltip += "<td><table cellpadding='0' cellspacing='0'>";
+
+ if (tags.title().isEmpty() || tags.artist().isEmpty())
+ // no title or no artist, so we add prettyTitle
+ m_tooltip += TQString ("<tr><td align=center colspan='2'>%1</td></tr>")
+ .arg(tags.veryNiceTitle());
+ for( uint x = 0; x < left.count(); ++x )
+ if ( !right[x].isEmpty() )
+ m_tooltip += tableRow.arg( left[x] ).arg( right[x] );
+
+ m_tooltip += "</table></td>";
+ m_tooltip += "</tr></table></center>";
+
+ m_tags = tags;
+ updateWidgets();
+ }
+}
+
+void TrackToolTip::setPos( int pos )
+{
+ if( m_pos != pos )
+ {
+ m_pos = pos;
+ updateWidgets();
+ }
+}
+
+void TrackToolTip::clear()
+{
+ m_pos = 0;
+ m_cover = TQString();
+ m_tooltip = i18n( "Amarok - rediscover your music" );
+ m_tags = MetaBundle();
+ m_tags.setUrl( KURL() );
+
+ updateWidgets();
+}
+
+TQPair<TQString, TQRect> TrackToolTip::toolTipText( TQWidget*, const TQPoint& ) const
+{
+ return TQPair<TQString, TQRect>( tooltip(), TQRect() );
+}
+
+void TrackToolTip::slotCoverChanged( const TQString &artist, const TQString &album )
+{
+ if( artist == m_tags.artist() && album == m_tags.album() )
+ {
+ m_cover = CollectionDB::instance()->albumImage( m_tags, true, 150 );
+ if( m_cover == CollectionDB::instance()->notAvailCover() )
+ m_cover = TQString();
+
+ updateWidgets();
+ }
+}
+
+void TrackToolTip::slotImageChanged( const TQString &remoteURL )
+{
+ PodcastEpisodeBundle peb;
+ if( CollectionDB::instance()->getPodcastEpisodeBundle( m_tags.url().url(), &peb ) )
+ {
+ PodcastChannelBundle pcb;
+ if( CollectionDB::instance()->getPodcastChannelBundle( peb.parent().url(), &pcb ) )
+ {
+ if( pcb.imageURL().url() == remoteURL )
+ {
+ m_cover = CollectionDB::instance()->podcastImage( remoteURL );
+ if( m_cover == CollectionDB::instance()->notAvailCover() )
+ m_cover = TQString();
+
+ updateWidgets();
+ }
+
+ }
+ }
+}
+
+void TrackToolTip::slotUpdate( const TQString &url )
+{
+ if( url.isNull() || url == m_tags.url().path() )
+ setTrack( m_tags, true );
+}
+
+void
+TrackToolTip::slotMoodbarEvent( void )
+{
+ // Clear this so the moodbar gets redrawn
+ m_moodbarURL = TQString();
+ // Reset the moodbar in case AlterMood has changed
+ m_tags.moodbar().reset();
+
+ setTrack( m_tags, true );
+}
+
+
+TQString TrackToolTip::tooltip() const
+{
+ TQString tip = m_tooltip;;
+ if( !m_tags.isEmpty() )
+ {
+ if( !m_cover.isEmpty() )
+ tip = tip.arg( TQString( "<td><table cellpadding='0' cellspacing='0'><tr><td>"
+ "<img src='%1'>"
+ "</td></tr></table></td>" ).arg( m_cover ) );
+ else
+ tip = tip.arg("");
+ if( m_haspos )
+ tip = tip.arg( MetaBundle::prettyLength( m_pos / 1000, true ) );
+ }
+ return tip;
+}
+
+void TrackToolTip::updateWidgets()
+{
+ Amarok::ToolTip::updateTip();
+}
+
+#include "tracktooltip.moc"