]> git.sesse.net Git - vlc/blob - modules/gui/qt4/util/input_slider.cpp
Qt: EPG gui self update
[vlc] / modules / gui / qt4 / util / input_slider.cpp
1 /*****************************************************************************
2  * input_manager.cpp : Manage an input and interact with its GUI elements
3  ****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Clément Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include "util/input_slider.hpp"
30
31 #include <QPaintEvent>
32 #include <QPainter>
33 #include <QBitmap>
34
35 InputSlider::InputSlider( QWidget *_parent ) : QSlider( _parent )
36 {
37     InputSlider( Qt::Horizontal, _parent );
38 }
39
40 InputSlider::InputSlider( Qt::Orientation q, QWidget *_parent ) :
41                                  QSlider( q, _parent )
42 {
43     b_isSliding = false;
44
45     /* Timer used to fire intermediate seekTick() when sliding */
46     timer = new QTimer(this);
47     timer->setSingleShot(true);
48
49     /* Properties */
50     setRange( 0, 1000 );
51     setSingleStep( 2 );
52     setPageStep( 10 );
53     setMouseTracking(true);
54     setTracking( true );
55     setFocusPolicy( Qt::NoFocus );
56
57     /* Init to 0 */
58     setPosition( -1.0, 0, 0 );
59     secstotimestr( psz_length, 0 );
60
61     CONNECT( this, sliderMoved(int), this, userDrag( int ) );
62     CONNECT( timer, timeout(), this, seekTick() );
63 }
64
65 void InputSlider::setPosition( float pos, int64_t a, int b )
66 {
67     if( pos == -1.0 )
68     {
69         setEnabled( false );
70         b_isSliding = false;
71     }
72     else
73         setEnabled( true );
74
75     if( !b_isSliding )
76         setValue( (int)(pos * 1000.0 ) );
77
78     inputLength = b;
79 }
80
81 void InputSlider::userDrag( int new_value )
82 {
83     /* Only fire one update, when sliding, every 150ms */
84     if( b_isSliding && !timer->isActive() )
85         timer->start( 150 );
86 }
87
88 void InputSlider::seekTick()
89 {
90     float f_pos = (float)(value())/1000.0;
91     emit sliderDragged( f_pos ); /* Send new position to our video */
92 }
93
94 void InputSlider::mouseReleaseEvent( QMouseEvent *event )
95 {
96     timer->stop(); /* We're not sliding anymore: only last seek on release */
97     b_isSliding = false;
98     event->accept();
99     QSlider::mouseReleaseEvent( event );
100     seekTick();
101 }
102
103 void InputSlider::mousePressEvent(QMouseEvent* event)
104 {
105     b_isSliding = true ;
106     if( event->button() != Qt::LeftButton &&
107         event->button() != Qt::MidButton )
108     {
109         QSlider::mousePressEvent( event );
110         return;
111     }
112
113     QMouseEvent newEvent( event->type(), event->pos(), event->globalPos(),
114         Qt::MouseButton( event->button() ^ Qt::LeftButton ^ Qt::MidButton ),
115         Qt::MouseButtons( event->buttons() ^ Qt::LeftButton ^ Qt::MidButton ),
116         event->modifiers() );
117     QSlider::mousePressEvent( &newEvent );
118 }
119
120 void InputSlider::mouseMoveEvent(QMouseEvent *event)
121 {
122     if( b_isSliding )
123     {
124         QSlider::mouseMoveEvent( event );
125     }
126
127     secstotimestr( psz_length, ( event->x() * inputLength) / size().width() );
128     setToolTip( psz_length );
129     event->accept();
130 }
131
132 void InputSlider::wheelEvent( QWheelEvent *event)
133 {
134     /* Don't do anything if we are for somehow reason sliding */
135     if( !b_isSliding )
136     {
137         setValue( value() + event->delta()/12 ); /* 12 = 8 * 15 / 10
138          Since delta is in 1/8 of ° and mouse have steps of 15 °
139          and that our slider is in 0.1% and we want one step to be a 1%
140          increment of position */
141         emit sliderDragged( value()/1000.0 );
142     }
143     /* We do accept because for we don't want the parent to change the sound
144        vol */
145     event->accept();
146 }
147
148 /* This work is derived from Amarok's work under GPLv2+
149     - Mark Kretschmann
150     - Gábor Lehel
151    */
152 #define WLENGTH   80 // px
153 #define WHEIGHT   22  // px
154 #define SOUNDMIN  0   // %
155 #define SOUNDMAX  200 // % OR 400 ?
156
157 SoundSlider::SoundSlider( QWidget *_parent, int _i_step, bool b_hard,
158                           char *psz_colors )
159                         : QAbstractSlider( _parent )
160 {
161     f_step = ( _i_step * 100 ) / AOUT_VOLUME_MAX ;
162     setRange( SOUNDMIN, b_hard ? (2 * SOUNDMAX) : SOUNDMAX  );
163     setMouseTracking( true );
164     b_isSliding = false;
165     b_mouseOutside = true;
166     b_isMuted = false;
167
168     pixOutside = QPixmap( ":/toolbar/volslide-outside" );
169
170     const QPixmap temp( ":/toolbar/volslide-inside" );
171     const QBitmap mask( temp.createHeuristicMask() );
172
173     setFixedSize( pixOutside.size() );
174
175     pixGradient = QPixmap( mask.size() );
176     pixGradient2 = QPixmap( mask.size() );
177
178     /* Gradient building from the preferences */
179     QLinearGradient gradient( paddingL, 2, WLENGTH + paddingL , 2 );
180     QLinearGradient gradient2( paddingL, 2, WLENGTH + paddingL , 2 );
181
182     QStringList colorList = qfu( psz_colors ).split( ";" );
183     free( psz_colors );
184
185     /* Fill with 255 if the list is too short */
186     if( colorList.size() < 12 )
187         for( int i = colorList.size(); i < 12; i++)
188             colorList.append( "255" );
189
190     /* Regular colors */
191 #define c(i) colorList.at(i).toInt()
192 #define add_color(gradient, range, c1, c2, c3) \
193     gradient.setColorAt( range, QColor( c(c1), c(c2), c(c3) ) );
194
195     /* Desaturated colors */
196 #define desaturate(c) c->setHsvF( c->hueF(), 0.2 , 0.5, 1.0 )
197 #define add_desaturated_color(gradient, range, c1, c2, c3) \
198     foo = new QColor( c(c1), c(c2), c(c3) );\
199     desaturate( foo ); gradient.setColorAt( range, *foo );\
200     delete foo;
201
202     /* combine the two helpers */
203 #define add_colors( gradient1, gradient2, range, c1, c2, c3 )\
204     add_color( gradient1, range, c1, c2, c3 ); \
205     add_desaturated_color( gradient2, range, c1, c2, c3 );
206
207     QColor * foo;
208     add_colors( gradient, gradient2, 0.0, 0, 1, 2 );
209     add_colors( gradient, gradient2, 0.22, 3, 4, 5 );
210     add_colors( gradient, gradient2, 0.5, 6, 7, 8 );
211     add_colors( gradient, gradient2, 1.0, 9, 10, 11 );
212
213     QPainter painter( &pixGradient );
214     painter.setPen( Qt::NoPen );
215     painter.setBrush( gradient );
216     painter.drawRect( pixGradient.rect() );
217     painter.end();
218
219     painter.begin( &pixGradient2 );
220     painter.setPen( Qt::NoPen );
221     painter.setBrush( gradient2 );
222     painter.drawRect( pixGradient2.rect() );
223     painter.end();
224
225     pixGradient.setMask( mask );
226     pixGradient2.setMask( mask );
227 }
228
229 void SoundSlider::wheelEvent( QWheelEvent *event )
230 {
231     int newvalue = value() + event->delta() / ( 8 * 15 ) * f_step;
232     setValue( __MIN( __MAX( minimum(), newvalue ), maximum() ) );
233
234     emit sliderReleased();
235     emit sliderMoved( value() );
236 }
237
238 void SoundSlider::mousePressEvent( QMouseEvent *event )
239 {
240     if( event->button() != Qt::RightButton )
241     {
242         /* We enter the sliding mode */
243         b_isSliding = true;
244         i_oldvalue = value();
245         emit sliderPressed();
246         changeValue( event->x() - paddingL );
247         emit sliderMoved( value() );
248     }
249 }
250
251 void SoundSlider::mouseReleaseEvent( QMouseEvent *event )
252 {
253     if( event->button() != Qt::RightButton )
254     {
255         if( !b_mouseOutside && value() != i_oldvalue )
256         {
257             emit sliderReleased();
258             setValue( value() );
259             emit sliderMoved( value() );
260         }
261         b_isSliding = false;
262         b_mouseOutside = false;
263     }
264 }
265
266 void SoundSlider::mouseMoveEvent( QMouseEvent *event )
267 {
268     if( b_isSliding )
269     {
270         QRect rect( paddingL - 15,    -1,
271                     WLENGTH + 15 * 2 , WHEIGHT + 5 );
272         if( !rect.contains( event->pos() ) )
273         { /* We are outside */
274             if ( !b_mouseOutside )
275                 setValue( i_oldvalue );
276             b_mouseOutside = true;
277         }
278         else
279         { /* We are inside */
280             b_mouseOutside = false;
281             changeValue( event->x() - paddingL );
282             emit sliderMoved( value() );
283         }
284     }
285     else
286     {
287         int i = ( ( event->x() - paddingL ) * maximum() + 40 ) / WLENGTH;
288         i = __MIN( __MAX( 0, i ), maximum() );
289         setToolTip( QString("%1  \%" ).arg( i ) );
290     }
291 }
292
293 void SoundSlider::changeValue( int x )
294 {
295     setValue( (x * maximum() + 40 ) / WLENGTH );
296 }
297
298 void SoundSlider::setMuted( bool m )
299 {
300     b_isMuted = m;
301     update();
302 }
303
304 void SoundSlider::paintEvent( QPaintEvent *e )
305 {
306     QPainter painter( this );
307     QPixmap *pixGradient;
308     if (b_isMuted)
309         pixGradient = &this->pixGradient2;
310     else
311         pixGradient = &this->pixGradient;
312
313     const int offset = int( ( WLENGTH * value() + 100 ) / maximum() ) + paddingL;
314
315     const QRectF boundsG( 0, 0, offset , pixGradient->height() );
316     painter.drawPixmap( boundsG, *pixGradient, boundsG );
317
318     const QRectF boundsO( 0, 0, pixOutside.width(), pixOutside.height() );
319     painter.drawPixmap( boundsO, pixOutside, boundsO );
320
321     painter.setPen( palette().color( QPalette::Active, QPalette::Mid ) );
322     QFont font; font.setPixelSize( 9 );
323     painter.setFont( font );
324     const QRect rect( 0, 0, 34, 15 );
325     painter.drawText( rect, Qt::AlignRight | Qt::AlignVCenter,
326                       QString::number( value() ) + '%' );
327
328     painter.end();
329     e->accept();
330 }
331