1
/***************************************************************************
2
kpoti.cpp - potentiometer widget
4
begin : Wed Apr 28 23:05:05 MEST 1999
6
copyright : (C) 1999 by Martin Lorenz
7
email : lorenz@ch.tum.de
8
***************************************************************************/
10
/***************************************************************************
12
* This program is free software; you can redistribute it and/or modify *
13
* it under the terms of the GNU General Public License as published by *
14
* the Free Software Foundation; either version 2 of the License, or *
15
* (at your option) any later version. *
17
***************************************************************************/
32
static const int motifBorder = 2;
33
static const int motifLength = 30;
34
static const int winLength = 9; // Must be odd
35
static const int thresholdTime = 500;
36
static const int repeatTime = 100;
37
static const float maxAngle = PI*135/180; // 140 degrees to both sides
38
static const float tickLength = 0.25;
39
static const int fontSize=8;
44
The \e parent and \e name arguments are sent to the QWidget constructor.
46
KPoti::KPoti( QWidget *parent, const char *name )
47
: QWidget( parent, name )
57
\arg \e minValue is the minimum slider value.
58
\arg \e maxValue is the maximum slider value.
59
\arg \e step is the page step value.
60
\arg \e value is the initial value.
62
The \e parent and \e name arguments are sent to the QWidget constructor.
65
KPoti::KPoti( int minValue, int maxValue, int step,
66
int value, QWidget *parent, const char *name )
67
: QWidget( parent, name ),
68
QRangeControl( minValue, maxValue, 1, step, value )
74
void KPoti::init(int value)
76
color.setNamedColor("red");
79
potiPos = positionFromValue(value);
86
fontHeight=fontMetrics().height();
88
space = QMIN( height(), width() );
89
center.setX(space/2); center.setY(space/2);
90
setBackgroundMode( PaletteMid );
92
setFocusPolicy( TabFocus );
98
Does what's needed when someone changes the tickmark status
101
void KPoti::initTicks()
104
space = QMIN( height(), width() );
105
center.setX(width()/2);
107
space -= fontSize -2;
111
double spaced = space;
112
spaced /= 1.0+tickLength/2;
117
buttonRadius = (space-1)/2 ; center.setY(height()-buttonRadius-1);
123
Enables slider tracking if \e enable is TRUE, or disables tracking
124
if \e enable is FALSE.
126
If tracking is enabled (default), the slider emits the
127
valueChanged() signal whenever the slider is being dragged. If
128
tracking is disabled, the slider emits the valueChanged() signal
129
when the user releases the mouse button (unless the value happens to
130
be the same as before).
135
void KPoti::setTracking( bool enable )
142
\fn bool KPoti::tracking() const
143
Returns TRUE if tracking is enabled, or FALSE if tracking is disabled.
145
Tracking is initially enabled.
152
\fn void KPoti::valueChanged( int value )
153
This signal is emitted when the slider value is changed, with the
154
new slider value as an argument.
158
\fn void KPoti::sliderPressed()
159
This signal is emitted when the user presses the slider with the mouse.
163
\fn void KPoti::sliderMoved( int value )
164
This signal is emitted when the slider is dragged, with the
165
new slider value as an argument.
169
\fn void KPoti::sliderReleased()
170
This signal is emitted when the user releases the slider with the mouse.
174
Calculates slider position corresponding to value \a v. Does not perform
178
float KPoti::positionFromValue( int v ) const
181
int range = maxValue() - minValue();
182
return ( (v - minValue() ) *2* maxAngle) / range - maxAngle;
187
Calculates value corresponding to poti position \a p. Performs rounding.
190
int KPoti::valueFromPosition( float p ) const
192
int range = maxValue() - minValue();
193
return (int) (minValue() + ((p+maxAngle)*range)/(2*maxAngle));
197
Implements the virtual QRangeControl function.
200
void KPoti::rangeChange()
202
float newPos = positionFromValue( value() );
203
if ( newPos != potiPos ) {
204
reallyMovePoti( newPos );
209
Changes the value (slot)
212
void KPoti::valueChange()
214
if ( potiVal != value() ) {
215
float newPos = positionFromValue( value() );
217
reallyMovePoti( newPos );
219
emit valueChanged(value());
224
Handles resize events for the poti.
227
void KPoti::resizeEvent( QResizeEvent * )
235
Reimplements the virtual function QWidget::setPalette().
239
void KPoti::setPalette( const QPalette &p )
242
setBackgroundMode( PaletteMid );
243
QWidget::setPalette( p );
247
void KPoti::setLabel(bool s)
254
Sets the color of the button
256
void KPoti::setColor( const QColor &c )
263
void KPoti::paintPoti( QPainter *p)
265
QColorGroup g = colorGroup();
266
p->setBrush( color );
267
QCOORD x=center.x(), y=center.y();
270
//qDrawShadePanel( p, r, g, FALSE, 2, &fill );
271
p->drawEllipse(x-buttonRadius+5,y-buttonRadius+5,
272
(buttonRadius-5)*2, (buttonRadius-5)*2);
273
//p->drawLine((int)( x+s*buttonRadius),(int)( y-c*buttonRadius),
274
// (int)(x+s*buttonRadius*0.3),(int)( y-c*buttonRadius*0.3));
276
p->rotate(potiPos*180/PI);
277
int end=((buttonRadius -5)*4)/10;
279
qDrawShadeLine (p, 0, -buttonRadius+6,0 ,-end ,
284
Performs the actual moving of the slider.
287
void KPoti::reallyMovePoti( float newPos )
301
Handles paint events for the slider.
304
void KPoti::paintEvent( QPaintEvent *e )
310
QRect paintRect = e->rect();
311
p.setClipRect( paintRect );
313
QColorGroup g = colorGroup();
314
if(backgroundMode() == FixedPixmap)
316
p.drawTiledPixmap( 0, 0, width(), height(), *backgroundPixmap() );
320
p.fillRect( 0, 0, width(), height(), g.background() );
323
const QColor c0 = black;
324
const QColor c4 = g.light();
327
font=p.font(); font.setPointSize(8); p.setFont(font);
328
p.drawText(0,fontSize,name());
330
int interval = tickInt;
331
if ( interval <= 0 ) {
335
drawTicks( &p, buttonRadius+2, (int)(buttonRadius*(1+tickLength)), interval );
338
p.setBrush(darkGray);
339
p.drawEllipse(center.x()-buttonRadius,center.y()-buttonRadius,
340
2*(buttonRadius),2*(buttonRadius));
342
p.drawArc(center.x()-buttonRadius,center.y()-buttonRadius,
343
2*buttonRadius,2*buttonRadius, 45*16,180*16);
347
p.drawArc(center.x()-buttonRadius+3,center.y()-buttonRadius+3,
348
2*(buttonRadius-3),2*(buttonRadius-3), 45*16,-180*16);
351
p.drawArc(center.x()-buttonRadius,center.y()-buttonRadius,
352
2*buttonRadius,2*buttonRadius, 45*16,-180*16);
356
p.drawArc(center.x()-buttonRadius+3,center.y()-buttonRadius+3,
357
2*(buttonRadius-3),2*(buttonRadius-3), 45*16,180*16);
360
p.setPen( black ); p.setBrush(NoBrush);
361
p.drawRect( 0,0, width(), height() );
373
Handles mouse press events for the slider.
376
void KPoti::mousePressEvent( QMouseEvent *e )
380
if ( e->button() == MidButton ) {
381
float pos = atan2( e->pos().x()-center.x(),- e->pos().y() + center.y() );
385
if ( e->button() != LeftButton )
389
int dx=e->pos().x()-center.x(), dy=e->pos().y()-center.y();
391
if ( dx*dx+dy*dy < buttonRadius*buttonRadius ) {
393
clickOffset = potiVal + (e->pos().y() ) ;
395
} else if ( e->pos().x() < width()/2 ) {
399
timer = new QTimer( this );
400
connect( timer, SIGNAL(timeout()), SLOT(repeatTimeout()) );
401
timer->start( thresholdTime, TRUE );
406
timer = new QTimer( this );
407
connect( timer, SIGNAL(timeout()), SLOT(repeatTimeout()) );
408
timer->start( thresholdTime, TRUE );
413
Handles mouse move events for the slider.
415
void KPoti::mouseMoveEvent( QMouseEvent *e )
418
if ( (e->state() & MidButton) ) { // middle button wins
419
float pos = atan2( e->pos().x()-center.x(),- e->pos().y()+center.y() );
423
if ( !(e->state() & LeftButton) )
424
return; // left mouse button is up
425
if ( state != Dragging )
429
movePoti( positionFromValue(- e->pos().y() + clickOffset ));
434
Handles mouse release events for the slider.
437
void KPoti::mouseReleaseEvent( QMouseEvent *e )
439
if ( !(e->button() & LeftButton) )
445
Handles focus in events for the slider.
448
void KPoti::focusInEvent( QFocusEvent * )
455
Handles mouse entering events.
458
void KPoti::enterEvent( QEvent * )
460
emit mouseEntered( potiVal );
465
Moves the left (or top) edge of the slider to position
466
\a pos. Performs snapping.
469
void KPoti::movePoti( float pos )
471
float newPos = QMIN( maxAngle, QMAX( -maxAngle, pos ) );
472
int newVal = valueFromPosition( newPos );
473
if ( potiVal != newVal ) {
475
emit potiMoved( potiVal );
477
if ( tracking() && potiVal != value() ) {
478
directSetValue( potiVal );
479
emit valueChanged( potiVal );
483
if ( potiPos != newPos )
484
reallyMovePoti( newPos );
489
Resets all state information and stops my timer.
492
void KPoti::resetState()
503
setValue( valueFromPosition( potiPos ) );
510
kdWarning() << "KPoti: in wrong state" << endl;
517
Handles key press events for the slider.
520
void KPoti::keyPressEvent( QKeyEvent *e )
523
switch ( e->key() ) {
543
setValue( minValue() );
546
setValue( maxValue() );
560
Makes QRangeControl::setValue() available as a slot.
563
void KPoti::setValue( int value )
565
QRangeControl::setValue( value );
570
Moves the slider one pageStep() upwards.
573
void KPoti::addStep()
580
Moves the slider one pageStep() downwards.
583
void KPoti::subtractStep()
590
Waits for autorepeat.
593
void KPoti::repeatTimeout()
597
if ( state == TimingDown )
598
connect( timer, SIGNAL(timeout()), SLOT(subtractStep()) );
599
else if ( state == TimingUp )
600
connect( timer, SIGNAL(timeout()), SLOT(addStep()) );
601
timer->start( repeatTime, FALSE );
608
Using \a p, draws tickmarks at a distance of \a d from the edge
609
of the widget, using \a w pixels and \a i intervals.
612
void KPoti::drawTicks( QPainter *p, int d, int w, int i ) const
614
p->setPen( colorGroup().foreground() );
616
for (int v=0; v<=i; v++) {
617
angle=-maxAngle+2*maxAngle*v/i;
618
s=sin(angle); c=cos(angle);
620
p->drawLine( (int)(center.x()-s*d), (int)(center.y()-c*d),
621
(int)(center.x()-s*w), (int)(center.y()-c*w) );
625
void KPoti::wheelEvent(QWheelEvent *e)
627
setValue(value()+e->delta()/120*8);
632
Sets the way tickmarks are displayed by the slider. \a s can take
633
the following values:
642
The initial value is \c NoMarks.
643
\sa tickmarks(), setTickInterval()
646
void KPoti::setTickmarks( bool s )
656
Sets the interval between tickmarks to \a i. This is a value interval,
657
not a pixel interval. If \a i is 0, the slider
658
will choose between lineStep() and pageStep(). The initial value of
660
\sa tickInterval(), QRangeControl::lineStep(), QRangeControl::pageStep()
663
void KPoti::setTickInterval( int i )
665
tickInt = QMAX( 0, i );
671
\fn int KPoti::tickInterval() const
672
Returns the interval between tickmarks. Returns 0 if the slider
673
chooses between pageStep() and lineStep().
674
\sa setTickInterval()