1 /***************************************************************************
2 * copyright : (C) 2007 Dan Meltzer <hydrogen@notyetimplemented.com> *
3 **************************************************************************/
5 /***************************************************************************
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. *
12 ***************************************************************************/
14 #include "amarokconfig.h"
16 #include "enginecontroller.h"
17 #include "progressslider.h"
18 #include "timeLabel.h"
20 #include <kpassivepopup.h>
23 #include <QHBoxLayout>
28 // Class ProgressSlider
29 ProgressSlider
*ProgressSlider::s_instance
= 0;
30 ProgressSlider::ProgressSlider( QWidget
*parent
) :
31 Amarok::PrettySlider( Qt::Horizontal
, Amarok::PrettySlider::Normal
, parent
)
34 setMouseTracking( true );
37 // Add A bookmark to the slider at given second
39 ProgressSlider::addBookmark( uint second
)
41 if( !m_bookmarks
.contains(second
) )
42 m_bookmarks
<< second
;
48 ProgressSlider::addBookmarks( QList
<uint
> seconds
)
50 foreach( uint it
, seconds
)
55 ProgressSlider::paintEvent( QPaintEvent
*e
)
57 Amarok::PrettySlider::paintEvent( e
);
62 foreach( uint it
, m_bookmarks
)
64 const int pos
= int( double( width() ) / maximum() * ( it
* 1000 ) );
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
);
71 p
.drawConvexPolygon( pa
);
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() ) );
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() )
101 Amarok::PrettySlider::mouseMoveEvent( e
);
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
)
120 EngineObserver( EngineController::instance() )
124 QHBoxLayout
*box
= new QHBoxLayout( this );
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
);
144 // don't overlap the resize handle with the time display
145 box
->addSpacing( 12 );
148 if( !AmarokConfig::leftTimeDisplayEnabled() )
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 )) );
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() )
170 // when the left label shows the remaining time and it's not a stream
171 if( AmarokConfig::leftTimeDisplayRemaining() && trackLength
> 0 )
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 )
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 )
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 ) {
196 // when the right label shows the remaining time and it's not a stream
197 } else if( !AmarokConfig::leftTimeDisplayRemaining() && trackLength
> 0 )
202 while( (int)s1
.length() < m_timeLength
)
205 while( (int)s2
.length() < m_timeLength
)
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 );
224 m_timeLabel
->setEnabled( true );
225 m_timeLabel2
->setEnabled( true );
230 ProgressWidget::engineTrackPositionChanged( long position
, bool /*userSeek*/ )
232 m_slider
->setValue( position
);
234 if ( !m_slider
->isEnabled() )
235 drawTimeDisplay( position
);
239 ProgressWidget::engineStateChanged( Engine::State state
, Engine::State
/*oldState*/ )
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 );
252 case Engine::Playing
:
255 m_timeLabel
->setEnabled( true );
256 m_timeLabel2
->setEnabled( true );
260 ; //just do nothing, idle is temporary and a limbo state
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
);
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"