diff options
Diffstat (limited to 'amarok/src/tracktooltip.cpp')
| -rw-r--r-- | amarok/src/tracktooltip.cpp | 351 |
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" |
