Not crap after all...
[amarok.git] / src / progressslider.cpp
blob8f6f16a4f33fac6d3d6cd5aa819101bacd55ab15
1 /***************************************************************************
2 * copyright : (C) 2007 Dan Meltzer <hydrogen@notyetimplemented.com> *
3 **************************************************************************/
5 /***************************************************************************
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 ***************************************************************************/
14 #include "amarokconfig.h"
15 #include "debug.h"
16 #include "enginecontroller.h"
17 #include "progressslider.h"
18 #include "timeLabel.h"
20 #include <kpassivepopup.h>
21 #include <khbox.h>
23 #include <QHBoxLayout>
24 #include <QLabel>
25 #include <QList>
26 #include <QPolygon>
28 // Class ProgressSlider
29 ProgressSlider *ProgressSlider::s_instance = 0;
30 ProgressSlider::ProgressSlider( QWidget *parent ) :
31 Amarok::PrettySlider( Qt::Horizontal, Amarok::PrettySlider::Normal, parent )
33 s_instance = this;
34 setMouseTracking( true );
37 // Add A bookmark to the slider at given second
38 void
39 ProgressSlider::addBookmark( uint second )
41 if( !m_bookmarks.contains(second) )
42 m_bookmarks << second;
43 update();
47 void
48 ProgressSlider::addBookmarks( QList<uint> seconds )
50 foreach( uint it, seconds )
51 addBookmark( it );
54 void
55 ProgressSlider::paintEvent( QPaintEvent *e )
57 Amarok::PrettySlider::paintEvent( e );
59 if( isEnabled() )
61 QPainter p( this );
62 foreach( uint it, m_bookmarks )
64 const int pos = int( double( width() ) / maximum() * ( it * 1000 ) );
65 Bookmark pa( 3, it );
66 pa.setPoint( 0, pos - 5, 1 );
67 pa.setPoint( 1, pos + 5, 1 );
68 pa.setPoint( 2, pos, 9 );
69 p.setBrush( Qt::red );
70 m_polygons << pa;
71 p.drawConvexPolygon( pa );
76 void
77 ProgressSlider::mouseMoveEvent( QMouseEvent *e )
79 foreach( Bookmark p, m_polygons )
81 //only create a popup if the mouse enters a bookmark, not if it moves inside of one.
82 if( p.containsPoint( e->pos(), Qt::OddEvenFill ) && !p.containsPoint( oldpoint, Qt::OddEvenFill ) )
84 m_popup = new KPassivePopup( parentWidget() );
85 KHBox *khb = new KHBox( m_popup );
86 new QLabel( p.time(), khb );
87 m_popup->setView( khb );
88 m_popup->setAutoDelete( false );
89 m_popup->show( mapToGlobal( e->pos() ) );
90 oldpoint = e->pos();
92 //If the mouse moves outside of the bookmark, hide the popup
93 else if ( p.containsPoint( oldpoint, Qt::OddEvenFill) && !p.containsPoint( e->pos(), Qt::OddEvenFill ) )
95 if( m_popup->isVisible() )
96 m_popup->hide();
99 oldpoint = e->pos();
101 Amarok::PrettySlider::mouseMoveEvent( e );
104 void
105 ProgressSlider::mousePressEvent( QMouseEvent *e )
107 EngineController *ec = EngineController::instance();
108 foreach( Bookmark p, m_polygons )
109 if( p.containsPoint( e->pos(), Qt::OddEvenFill ) )
110 ec->seek( p.seconds() * 1000 );
112 Amarok::PrettySlider::mousePressEvent( e );
114 // END Class ProgressSlider
116 //Class ProgressWidget
117 ProgressWidget *ProgressWidget::s_instance = 0;
118 ProgressWidget::ProgressWidget( QWidget *parent )
119 : QWidget( parent ),
120 EngineObserver( EngineController::instance() )
122 s_instance = this;
124 QHBoxLayout *box = new QHBoxLayout( this );
125 setLayout( box );
126 box->setMargin( 1 );
127 box->setSpacing( 3 );
129 m_slider = new ProgressSlider( this );
131 // the two time labels. m_timeLabel is the left one,
132 // m_timeLabel2 the right one.
133 m_timeLabel = new TimeLabel( this );
134 m_timeLabel->setToolTip( i18n( "The amount of time elapsed in current song" ) );
136 m_timeLabel2 = new TimeLabel( this );
137 m_timeLabel->setToolTip( i18n( "The amount of time remaining in current song" ) );
139 box->addSpacing( 3 );
140 box->addWidget( m_timeLabel );
141 box->addWidget( m_slider );
142 box->addWidget( m_timeLabel2 );
143 #ifdef Q_WS_MAC
144 // don't overlap the resize handle with the time display
145 box->addSpacing( 12 );
146 #endif
148 if( !AmarokConfig::leftTimeDisplayEnabled() )
149 m_timeLabel->hide();
151 engineStateChanged( Engine::Empty );
153 connect( m_slider, SIGNAL(sliderReleased( int )), EngineController::instance(), SLOT(seek( int )) );
154 connect( m_slider, SIGNAL(valueChanged( int )), SLOT(drawTimeDisplay( int )) );
158 void
159 ProgressWidget::drawTimeDisplay( int ms ) //SLOT
161 int seconds = ms / 1000;
162 int seconds2 = seconds; // for the second label.
163 const uint trackLength = EngineController::instance()->bundle().length();
165 if( AmarokConfig::leftTimeDisplayEnabled() )
166 m_timeLabel->show();
167 else
168 m_timeLabel->hide();
170 // when the left label shows the remaining time and it's not a stream
171 if( AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 )
173 seconds2 = seconds;
174 seconds = trackLength - seconds;
175 // when the left label shows the remaining time and it's a stream
176 } else if( AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 )
178 seconds2 = seconds;
179 seconds = 0; // for streams
180 // when the right label shows the remaining time and it's not a stream
181 } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 )
183 seconds2 = trackLength - seconds;
184 // when the right label shows the remaining time and it's a stream
185 } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 )
187 seconds2 = 0;
190 QString s1 = MetaBundle::prettyTime( seconds );
191 QString s2 = MetaBundle::prettyTime( seconds2 );
193 // when the left label shows the remaining time and it's not a stream
194 if( AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 ) {
195 s1.prepend( '-' );
196 // when the right label shows the remaining time and it's not a stream
197 } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength > 0 )
199 s2.prepend( '-' );
202 while( (int)s1.length() < m_timeLength )
203 s1.prepend( ' ' );
205 while( (int)s2.length() < m_timeLength )
206 s2.prepend( ' ' );
208 s1 += ' ';
209 s2 += ' ';
211 m_timeLabel->setText( s1 );
212 m_timeLabel2->setText( s2 );
214 if( AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 )
216 m_timeLabel->setEnabled( false );
217 m_timeLabel2->setEnabled( true );
218 } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength == 0 )
220 m_timeLabel->setEnabled( true );
221 m_timeLabel2->setEnabled( false );
222 } else
224 m_timeLabel->setEnabled( true );
225 m_timeLabel2->setEnabled( true );
229 void
230 ProgressWidget::engineTrackPositionChanged( long position, bool /*userSeek*/ )
232 m_slider->setValue( position );
234 if ( !m_slider->isEnabled() )
235 drawTimeDisplay( position );
238 void
239 ProgressWidget::engineStateChanged( Engine::State state, Engine::State /*oldState*/ )
242 switch ( state ) {
243 case Engine::Empty:
244 m_slider->setEnabled( false );
245 m_slider->setMinimum( 0 ); //needed because setMaximum() calls with bogus values can change minValue
246 m_slider->setMaximum( 0 );
247 m_slider->newBundle( MetaBundle() ); // Set an empty bundle
248 m_timeLabel->setEnabled( false ); //must be done after the setValue() above, due to a signal connection
249 m_timeLabel2->setEnabled( false );
250 break;
252 case Engine::Playing:
253 case Engine::Paused:
254 DEBUG_LINE_INFO
255 m_timeLabel->setEnabled( true );
256 m_timeLabel2->setEnabled( true );
257 break;
259 case Engine::Idle:
260 ; //just do nothing, idle is temporary and a limbo state
264 void
265 ProgressWidget::engineNewMetaData( const MetaBundle &bundle, bool /*trackChanged*/ )
267 m_slider->newBundle( bundle );
268 engineTrackLengthChanged( bundle.length() );
269 m_slider->setMaximum( EngineController::instance()->bundle().length() * 1000 );
271 ProgressSlider::instance()->addBookmark( 20 );
272 ProgressSlider::instance()->addBookmark( 40);
273 QList<uint> bookmarkList;
274 bookmarkList << 30 << 50 << 45;
275 ProgressSlider::instance()->addBookmarks( bookmarkList );
278 void
279 ProgressWidget::engineTrackLengthChanged( long length )
281 m_slider->setMinimum( 0 );
282 m_slider->setMaximum( length * 1000 );
283 m_slider->setEnabled( length > 0 );
284 m_timeLength = MetaBundle::prettyTime( length ).length()+1; // account for - in remaining time
287 #include "progressslider.moc"