/*************************************************************************** * Copyright (C) 2005 Max Howell * * (C) 2004 Frederik Holljen * * (C) 2005 Gábor Lehel * * * * 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. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "amarok.h" #include "amarokcore/amarokconfig.h" #include "debug.h" #include "enginecontroller.h" #include "queueLabel.h" #include "metabundle.h" #include "sliderwidget.h" #include "statusbar.h" #include #include #include #include #include // stuff that must be included last //#include "startupTips.h" #include "timeLabel.h" #include "toggleLabel.h" #include "toggleLabel.moc" #include "selectLabel.h" #include "selectLabel.moc" namespace Amarok { KAction *action( const char *name ) { return Amarok::actionCollection()->action( name ); } //TODO disable hide statusbar? or show when required? that sucks though. StatusBar* StatusBar::s_instance = 0; StatusBar::StatusBar( TQWidget *parent, const char *name ) : KDE::StatusBar( parent, name ) , EngineObserver( EngineController::instance() ) , m_timeLength( 9 ) , m_pauseTimer( new TQTimer( this ) ) { s_instance = this; //static member // total songs count m_itemCountLabel = new TQLabel( this ); m_itemCountLabel->setAlignment( TQt::AlignCenter ); m_itemCountLabel->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Fixed ); //positionBox TQWidget *positionBox = new TQWidget( this, "positionBox" ); TQBoxLayout *box = new TQHBoxLayout( positionBox, 1, 3 ); m_slider = new Amarok::PrettySlider( Qt::Horizontal, Amarok::PrettySlider::Normal, positionBox ); // the two time labels. m_timeLable is the left one, // m_timeLabel2 the right one. m_timeLabel = new TimeLabel( positionBox ); m_slider->setMinimumWidth( m_timeLabel->width() ); m_timeLabel2 = new TimeLabel( positionBox ); m_slider->setMinimumWidth( m_timeLabel2->width() ); // TODO Both labels need tooltips (string freeze?) TQWidget *hbox = new TQWidget( this ); TQBoxLayout *tqlayout = new TQHBoxLayout( hbox, 0, 2 ); tqlayout->addSpacing( 3 ); tqlayout->addWidget( m_queueLabel = new QueueLabel( hbox ) ); tqlayout->addWidget( new SelectLabel( static_cast( Amarok::action( "repeat" ) ), hbox ) ); tqlayout->addWidget( new SelectLabel( static_cast( Amarok::action( "random_mode" ) ), hbox ) ); tqlayout->addSpacing( 3 ); //TODO reimplement insertChild() instead addWidget( m_itemCountLabel ); addWidget( hbox ); addWidget( positionBox ); box->addSpacing( 3 ); box->addWidget( m_timeLabel ); box->addWidget( m_slider ); box->addWidget( m_timeLabel2 ); #ifdef TQ_WS_MAC // don't overlap the resize handle with the time display box->addSpacing( 12 ); #endif if( !AmarokConfig::leftTimeDisplayEnabled() ) m_timeLabel->hide(); connect( m_slider, TQT_SIGNAL(sliderReleased( int )), EngineController::instance(), TQT_SLOT(seek( int )) ); connect( m_slider, TQT_SIGNAL(valueChanged( int )), TQT_SLOT(drawTimeDisplay( int )) ); // set us up the bomb engineStateChanged( Engine::Empty ); //slotItemCountChanged( 0 ); // for great justice! connect( m_pauseTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotPauseTimer()) ); slotItemCountChanged( 0, 0, 0, 0, 0, 0 ); //see statupTips.h //KDE::showNextTip( this ); //session stuff //setShown( AmarokConfig::showStatusBar() ); } void StatusBar::engineStateChanged( Engine::State state, Engine::State /*oldState*/ ) { m_pauseTimer->stop(); switch ( state ) { case Engine::Empty: m_slider->setEnabled( false ); m_slider->setMinValue( 0 ); //needed because setMaxValue() calls with bogus values can change minValue m_slider->setMaxValue( 0 ); m_slider->newBundle( MetaBundle() ); // Set an empty bundle m_timeLabel->setEnabled( false ); //must be done after the setValue() above, due to a signal connection m_timeLabel2->setEnabled( false ); setMainText( TQString() ); break; case Engine::Paused: m_mainTextLabel->setText( i18n( "Amarok is paused" ) ); // display TEMPORARY message m_pauseTimer->start( 300 ); break; case Engine::Playing: DEBUG_LINE_INFO resetMainText(); // if we were paused, this is necessary m_timeLabel->setEnabled( true ); m_timeLabel2->setEnabled( true ); break; case Engine::Idle: ; //just do nothing, idle is temporary and a limbo state } } void StatusBar::engineNewMetaData( const MetaBundle &bundle, bool /*trackChanged*/ ) { #define escapeHTML(s) TQString(s).replace( "&", "&" ).replace( "<", "<" ).replace( ">", ">" ) TQString title = escapeHTML( bundle.title() ); TQString prettyTitle = escapeHTML( bundle.prettyTitle() ); TQString artist = escapeHTML( bundle.artist() ); TQString album = escapeHTML( bundle.album() ); TQString length = escapeHTML( bundle.prettyLength() ); #undef escapeHTML if ( bundle.artist() == "Mike Oldfield" && bundle.title() == "Amarok" ) { longMessage( i18n( "

One of Mike Oldfield's best pieces of work, Amarok, inspired the name behind " "the audio-player you are currently using. Thanks for choosing Amarok!

" "

Mark Kretschmann
Max Howell
Chris Muehlhaeuser
" "The many other people who have helped make Amarok what it is

" ), KDE::StatusBar::Information ); } // ugly because of translation requirements if( !title.isEmpty() && !artist.isEmpty() && !album.isEmpty() ) title = i18n( "track by artist on album", "%1 by %2 on %3" ) .tqarg( title, artist, album ); else if( !title.isEmpty() && !artist.isEmpty() ) title = i18n( "track by artist", "%1 by %2" ) .tqarg( title, artist ); else if( !album.isEmpty() ) // we try for pretty title as it may come out better title = i18n( "track on album", "%1 on %2" ) .tqarg( prettyTitle, album ); else title = "" + prettyTitle + ""; if( title.isEmpty() ) title = i18n( "Unknown track" ); // don't show '-' or '?' if( length.length() > 1 ) { title += " ("; title += length; title += ')'; } setMainText( i18n( "Playing: %1" ).tqarg( title ) ); m_slider->newBundle( bundle ); engineTrackLengthChanged( bundle.length() ); } void StatusBar::slotItemCountChanged( int newCount, int newLength, //total int visCount, int visLength, //visible int selCount, int selLength ) //selected { const bool hasSel = ( selCount > 1 ), hasVis = ( visCount != newCount ); TQString text = ( hasSel && hasVis ) ? i18n( "%1 selected of %2 visible tracks" ) .tqarg( selCount ).tqarg( visCount ) : ( hasVis && newCount == 1 ) ? i18n( "0 visible of 1 track" ) : ( hasVis ) ? i18n( "%1 visible of %2 tracks" ).tqarg( visCount).tqarg( newCount ) : ( hasSel ) ? i18n( "%1 selected of %2 tracks" ).tqarg( selCount ).tqarg( newCount ) : i18n( "1 track", "%n tracks", newCount ); int getValue = 0; if( hasSel ) getValue = selLength; else if( hasVis ) getValue = visLength; else getValue = newLength; if( getValue ) m_itemCountLabel->setText( i18n( "X visible/selected tracks (time) ", "%1 (%2)" ).tqarg( text, MetaBundle::fuzzyTime( getValue ) ) ); else m_itemCountLabel->setText( text ); TQToolTip::add( m_itemCountLabel, i18n( "Play-time: %1" ).tqarg( MetaBundle::veryPrettyTime( getValue ) ) ); } void StatusBar::engineTrackPositionChanged( long position, bool /*userSeek*/ ) { m_slider->setValue( position ); if ( !m_slider->isEnabled() ) drawTimeDisplay( position ); } void StatusBar::engineTrackLengthChanged( long length ) { m_slider->setMinValue( 0 ); m_slider->setMaxValue( length * 1000 ); m_slider->setEnabled( length > 0 ); m_timeLength = MetaBundle::prettyTime( length ).length()+1; // account for - in remaining time } void StatusBar::drawTimeDisplay( int ms ) //SLOT { int seconds = ms / 1000; int seconds2 = seconds; // for the second label. const uint trackLength = EngineController::instance()->bundle().length(); if( AmarokConfig::leftTimeDisplayEnabled() ) m_timeLabel->show(); else m_timeLabel->hide(); // when the left label shows the remaining time and it's not a stream if( AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 ) { seconds2 = seconds; seconds = trackLength - seconds; // when the left label shows the remaining time and it's a stream } else if( AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 ) { seconds2 = seconds; seconds = 0; // for streams // when the right label shows the remaining time and it's not a stream } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 ) { seconds2 = trackLength - seconds; // when the right label shows the remaining time and it's a stream } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 ) { seconds2 = 0; } TQString s1 = MetaBundle::prettyTime( seconds ); TQString s2 = MetaBundle::prettyTime( seconds2 ); // when the left label shows the remaining time and it's not a stream if( AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 ) { s1.prepend( '-' ); // when the right label shows the remaining time and it's not a stream } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 ) { s2.prepend( '-' ); } while( (int)s1.length() < m_timeLength ) s1.prepend( ' ' ); while( (int)s2.length() < m_timeLength ) s2.prepend( ' ' ); s1 += ' '; s2 += ' '; m_timeLabel->setText( s1 ); m_timeLabel2->setText( s2 ); if( AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 ) { m_timeLabel->setEnabled( false ); m_timeLabel2->setEnabled( true ); } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 ) { m_timeLabel->setEnabled( true ); m_timeLabel2->setEnabled( false ); } else { m_timeLabel->setEnabled( true ); m_timeLabel2->setEnabled( true ); } } void StatusBar::slotPauseTimer() //slot { static uint counter = 0; if ( counter == 0 ) { m_timeLabel->erase(); m_timeLabel2->erase(); } else { m_timeLabel->update(); m_timeLabel2->update(); } ++counter &= 3; } /////////////////// //MessageQueue /////////////////// MessageQueue::MessageQueue() : m_queueMessages(true) {} MessageQueue* MessageQueue::instance() { static MessageQueue mq; return &mq; } void MessageQueue::addMessage(const TQString& message) { if(m_queueMessages) m_messages.push(message); else StatusBar::instance()->longMessage(message); } void MessageQueue::sendMessages() { m_queueMessages = false; while(! m_messages.isEmpty()) { StatusBar::instance()->longMessage(m_messages.pop()); } } } //namespace Amarok #include "statusbar.moc"