qwt_abstract_slider.cpp
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2  * Qwt Widget Library
3  * Copyright (C) 1997 Josef Wilgen
4  * Copyright (C) 2002 Uwe Rathmann
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the Qwt License, Version 1.0
8  *****************************************************************************/
9 
10 #include "qwt_abstract_slider.h"
11 #include "qwt_scale_map.h"
12 #include "qwt_scale_div.h"
13 #include "qwt_math.h"
14 
15 #include <qevent.h>
16 
17 static double qwtAlignToScaleDiv(
18  const QwtAbstractSlider *slider, double value )
19 {
20  const QwtScaleDiv &sd = slider->scaleDiv();
21 
22  const int tValue = slider->transform( value );
23 
24  if ( tValue == slider->transform( sd.lowerBound() ) )
25  return sd.lowerBound();
26 
27  if ( tValue == slider->transform( sd.upperBound() ) )
28  return sd.upperBound();
29 
30  for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
31  {
32  const QList<double> ticks = sd.ticks( i );
33  for ( int j = 0; j < ticks.size(); j++ )
34  {
35  if ( slider->transform( ticks[ j ] ) == tValue )
36  return ticks[ j ];
37  }
38  }
39 
40  return value;
41 }
42 
44 {
45 public:
47  isScrolling( false ),
48  isTracking( true ),
49  pendingValueChanged( false ),
50  readOnly( false ),
51  totalSteps( 100 ),
52  singleSteps( 1 ),
53  pageSteps( 10 ),
54  stepAlignment( true ),
55  isValid( false ),
56  value( 0.0 ),
57  wrapping( false ),
58  invertedControls( false )
59  {
60  }
61 
63  bool isTracking;
65 
66  bool readOnly;
67 
68  uint totalSteps;
70  uint pageSteps;
72 
73  bool isValid;
74  double value;
75 
76  bool wrapping;
78 };
79 
92  QwtAbstractScale( parent )
93 {
95 
96  setScale( 0.0, 100.0 );
97  setFocusPolicy( Qt::StrongFocus );
98 }
99 
102 {
103  delete d_data;
104 }
105 
114 {
115  if ( on != d_data->isValid )
116  {
117  d_data->isValid = on;
118  sliderChange();
119 
120  Q_EMIT valueChanged( d_data->value );
121  }
122 }
123 
126 {
127  return d_data->isValid;
128 }
129 
142 {
143  if ( d_data->readOnly != on )
144  {
145  d_data->readOnly = on;
146  setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );
147 
148  update();
149  }
150 }
151 
160 {
161  return d_data->readOnly;
162 }
163 
178 {
179  d_data->isTracking = on;
180 }
181 
187 {
188  return d_data->isTracking;
189 }
190 
195 void QwtAbstractSlider::mousePressEvent( QMouseEvent *event )
196 {
197  if ( isReadOnly() )
198  {
199  event->ignore();
200  return;
201  }
202 
203  if ( !d_data->isValid || lowerBound() == upperBound() )
204  return;
205 
206  d_data->isScrolling = isScrollPosition( event->pos() );
207 
208  if ( d_data->isScrolling )
209  {
210  d_data->pendingValueChanged = false;
211 
212  Q_EMIT sliderPressed();
213  }
214 }
215 
220 void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event )
221 {
222  if ( isReadOnly() )
223  {
224  event->ignore();
225  return;
226  }
227 
228  if ( d_data->isValid && d_data->isScrolling )
229  {
230  double value = scrolledTo( event->pos() );
231  if ( value != d_data->value )
232  {
233  value = boundedValue( value );
234 
235  if ( d_data->stepAlignment )
236  {
237  value = alignedValue( value );
238  }
239  else
240  {
241  value = qwtAlignToScaleDiv( this, value );
242  }
243 
244  if ( value != d_data->value )
245  {
246  d_data->value = value;
247 
248  sliderChange();
249 
250  Q_EMIT sliderMoved( d_data->value );
251 
252  if ( d_data->isTracking )
253  Q_EMIT valueChanged( d_data->value );
254  else
255  d_data->pendingValueChanged = true;
256  }
257  }
258  }
259 }
260 
265 void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event )
266 {
267  if ( isReadOnly() )
268  {
269  event->ignore();
270  return;
271  }
272 
273  if ( d_data->isScrolling && d_data->isValid )
274  {
275  d_data->isScrolling = false;
276 
278  Q_EMIT valueChanged( d_data->value );
279 
280  Q_EMIT sliderReleased();
281  }
282 }
283 
296 void QwtAbstractSlider::wheelEvent( QWheelEvent *event )
297 {
298  if ( isReadOnly() )
299  {
300  event->ignore();
301  return;
302  }
303 
304  if ( !d_data->isValid || d_data->isScrolling )
305  return;
306 
307 #if QT_VERSION < 0x050000
308  const int wheelDelta = event->delta();
309 #else
310  const QPoint delta = event->angleDelta();
311  const int wheelDelta = ( qAbs( delta.x() ) > qAbs( delta.y() ) )
312  ? delta.x() : delta.y();
313 #endif
314 
315  int numSteps = 0;
316 
317  if ( ( event->modifiers() & Qt::ControlModifier) ||
318  ( event->modifiers() & Qt::ShiftModifier ) )
319  {
320  // one page regardless of delta
321  numSteps = d_data->pageSteps;
322  if ( wheelDelta < 0 )
323  numSteps = -numSteps;
324  }
325  else
326  {
327  const int numTurns = ( wheelDelta / 120 );
328  numSteps = numTurns * d_data->singleSteps;
329  }
330 
331  if ( d_data->invertedControls )
332  numSteps = -numSteps;
333 
334  const double value = incrementedValue( d_data->value, numSteps );
335  if ( value != d_data->value )
336  {
337  d_data->value = value;
338  sliderChange();
339 
340  Q_EMIT sliderMoved( d_data->value );
341  Q_EMIT valueChanged( d_data->value );
342  }
343 }
344 
370 void QwtAbstractSlider::keyPressEvent( QKeyEvent *event )
371 {
372  if ( isReadOnly() )
373  {
374  event->ignore();
375  return;
376  }
377 
378  if ( !d_data->isValid || d_data->isScrolling )
379  return;
380 
381  int numSteps = 0;
382  double value = d_data->value;
383 
384  switch ( event->key() )
385  {
386  case Qt::Key_Left:
387  {
388  numSteps = -static_cast<int>( d_data->singleSteps );
389  if ( isInverted() )
390  numSteps = -numSteps;
391 
392  break;
393  }
394  case Qt::Key_Right:
395  {
396  numSteps = d_data->singleSteps;
397  if ( isInverted() )
398  numSteps = -numSteps;
399 
400  break;
401  }
402  case Qt::Key_Down:
403  {
404  numSteps = -static_cast<int>( d_data->singleSteps );
405  if ( d_data->invertedControls )
406  numSteps = -numSteps;
407  break;
408  }
409  case Qt::Key_Up:
410  {
411  numSteps = d_data->singleSteps;
412  if ( d_data->invertedControls )
413  numSteps = -numSteps;
414 
415  break;
416  }
417  case Qt::Key_PageUp:
418  {
419  numSteps = d_data->pageSteps;
420  if ( d_data->invertedControls )
421  numSteps = -numSteps;
422  break;
423  }
424  case Qt::Key_PageDown:
425  {
426  numSteps = -static_cast<int>( d_data->pageSteps );
427  if ( d_data->invertedControls )
428  numSteps = -numSteps;
429  break;
430  }
431  case Qt::Key_Home:
432  {
433  value = minimum();
434  break;
435  }
436  case Qt::Key_End:
437  {
438  value = maximum();
439  break;
440  }
441  default:;
442  {
443  event->ignore();
444  }
445  }
446 
447  if ( numSteps != 0 )
448  {
449  value = incrementedValue( d_data->value, numSteps );
450  }
451 
452  if ( value != d_data->value )
453  {
454  d_data->value = value;
455  sliderChange();
456 
457  Q_EMIT sliderMoved( d_data->value );
458  Q_EMIT valueChanged( d_data->value );
459  }
460 }
461 
474 void QwtAbstractSlider::setTotalSteps( uint stepCount )
475 {
476  d_data->totalSteps = stepCount;
477 }
478 
484 {
485  return d_data->totalSteps;
486 }
487 
499 void QwtAbstractSlider::setSingleSteps( uint stepCount )
500 {
501  d_data->singleSteps = stepCount;
502 }
503 
509 {
510  return d_data->singleSteps;
511 }
512 
524 void QwtAbstractSlider::setPageSteps( uint stepCount )
525 {
526  d_data->pageSteps = stepCount;
527 }
528 
533 uint QwtAbstractSlider::pageSteps() const
534 {
535  return d_data->pageSteps;
536 }
537 
548 {
549  if ( on != d_data->stepAlignment )
550  {
551  d_data->stepAlignment = on;
552  }
553 }
554 
560 {
561  return d_data->stepAlignment;
562 }
563 
571 {
572  value = qBound( minimum(), value, maximum() );
573 
574  const bool changed = ( d_data->value != value ) || !d_data->isValid;
575 
576  d_data->value = value;
577  d_data->isValid = true;
578 
579  if ( changed )
580  {
581  sliderChange();
582  Q_EMIT valueChanged( d_data->value );
583  }
584 }
585 
587 double QwtAbstractSlider::value() const
588 {
589  return d_data->value;
590 }
591 
600 {
601  d_data->wrapping = on;
602 }
603 
608 bool QwtAbstractSlider::wrapping() const
609 {
610  return d_data->wrapping;
611 }
612 
629 {
630  d_data->invertedControls = on;
631 }
632 
638 {
639  return d_data->invertedControls;
640 }
641 
651 {
652  const double value = incrementedValue(
653  d_data->value, stepCount );
654 
655  if ( value != d_data->value )
656  {
657  d_data->value = value;
658  sliderChange();
659  }
660 }
661 
671  double value, int stepCount ) const
672 {
673  if ( d_data->totalSteps == 0 )
674  return value;
675 
676  const QwtTransform *transformation =
678 
679  if ( transformation == NULL )
680  {
681  const double range = maximum() - minimum();
682  value += stepCount * range / d_data->totalSteps;
683  }
684  else
685  {
686  QwtScaleMap map = scaleMap();
688 
689  // we need equidant steps according to
690  // paint device coordinates
691  const double range = transformation->transform( maximum() )
692  - transformation->transform( minimum() );
693 
694  const double stepSize = range / d_data->totalSteps;
695 
696  double v = transformation->transform( value );
697 
698  v = qRound( v / stepSize ) * stepSize;
699  v += stepCount * range / d_data->totalSteps;
700 
701  value = transformation->invTransform( v );
702  }
703 
704  value = boundedValue( value );
705 
706  if ( d_data->stepAlignment )
707  value = alignedValue( value );
708 
709  return value;
710 }
711 
713 {
714  const double vmin = minimum();
715  const double vmax = maximum();
716 
717  if ( d_data->wrapping && vmin != vmax )
718  {
719  const int fullCircle = 360 * 16;
720 
721  const double pd = scaleMap().pDist();
722  if ( int( pd / fullCircle ) * fullCircle == pd )
723  {
724  // full circle scales: min and max are the same
725  const double range = vmax - vmin;
726 
727  if ( value < vmin )
728  {
729  value += std::ceil( ( vmin - value ) / range ) * range;
730  }
731  else if ( value > vmax )
732  {
733  value -= std::ceil( ( value - vmax ) / range ) * range;
734  }
735  }
736  else
737  {
738  if ( value < vmin )
739  value = vmax;
740  else if ( value > vmax )
741  value = vmin;
742  }
743  }
744  else
745  {
746  value = qBound( vmin, value, vmax );
747  }
748 
749  return value;
750 }
751 
753 {
754  if ( d_data->totalSteps == 0 )
755  return value;
756 
757  double stepSize;
758 
759  if ( scaleMap().transformation() == NULL )
760  {
761  stepSize = ( maximum() - minimum() ) / d_data->totalSteps;
762  if ( stepSize > 0.0 )
763  {
764  value = lowerBound() +
765  qRound( ( value - lowerBound() ) / stepSize ) * stepSize;
766  }
767  }
768  else
769  {
770  stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps;
771 
772  if ( stepSize > 0.0 )
773  {
774  double v = scaleMap().transform( value );
775 
776  v = scaleMap().p1() +
777  qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize;
778 
779  value = scaleMap().invTransform( v );
780  }
781  }
782 
783  if ( qAbs( stepSize ) > 1e-12 )
784  {
785  if ( qFuzzyCompare( value + 1.0, 1.0 ) )
786  {
787  // correct rounding error if value = 0
788  value = 0.0;
789  }
790  else
791  {
792  // correct rounding error at the border
793  if ( qFuzzyCompare( value, upperBound() ) )
794  value = upperBound();
795  else if ( qFuzzyCompare( value, lowerBound() ) )
796  value = lowerBound();
797  }
798  }
799 
800  return value;
801 }
802 
807 {
808  const double value = qBound( minimum(), d_data->value, maximum() );
809 
810  const bool changed = ( value != d_data->value );
811  if ( changed )
812  {
813  d_data->value = value;
814  }
815 
816  if ( d_data->isValid || changed )
817  Q_EMIT valueChanged( d_data->value );
818 
819  updateGeometry();
820  update();
821 }
822 
825 {
826  update();
827 }
828 
829 #if QWT_MOC_INCLUDE
830 #include "moc_qwt_abstract_slider.cpp"
831 #endif
double p1() const
Definition: qwt_scale_map.h:99
void setScale(double lowerBound, double upperBound)
Specify a scale.
bool stepAlignment() const
enum MQTTPropertyCodes value
double p2() const
An abstract base class for widgets having a scale.
uint totalSteps() const
virtual double invTransform(double value) const =0
double incrementedValue(double value, int stepCount) const
int transform(double) const
virtual void sliderChange()
Calling update()
virtual void keyPressEvent(QKeyEvent *) QWT_OVERRIDE
void setValue(double value)
void valueChanged(double value)
Notify a change of value.
virtual void scaleChange() QWT_OVERRIDE
const QwtScaleMap & scaleMap() const
virtual void wheelEvent(QWheelEvent *) QWT_OVERRIDE
void setPageSteps(uint)
Set the number of steps for a page increment.
bool wrapping() const
A class representing a scale division.
Definition: qwt_scale_div.h:33
void setTracking(bool)
Enables or disables tracking.
uint singleSteps() const
void sliderMoved(double value)
double upperBound() const
virtual void mouseReleaseEvent(QMouseEvent *) QWT_OVERRIDE
void incrementValue(int stepCount)
An abstract base class for slider widgets with a scale.
double value() const
double minimum() const
virtual void mousePressEvent(QMouseEvent *) QWT_OVERRIDE
uint pageSteps() const
const QwtScaleDiv & scaleDiv() const
void setTotalSteps(uint)
Set the number of steps.
virtual double scrolledTo(const QPoint &pos) const =0
Determine the value for a new position of the movable part of the slider.
double lowerBound() const
A transformation between coordinate systems.
Definition: qwt_transform.h:35
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
bool invertedControls() const
void setStepAlignment(bool)
Enable step alignment.
const QwtTransform * transformation() const
Get the transformation.
A scale map.
Definition: qwt_scale_map.h:26
double invTransform(double p) const
double alignedValue(double) const
virtual bool isScrollPosition(const QPoint &pos) const =0
Determine what to do when the user presses a mouse button.
Number of valid tick types.
Definition: qwt_scale_div.h:52
bool isInverted() const
double pDist() const
virtual void mouseMoveEvent(QMouseEvent *) QWT_OVERRIDE
double lowerBound() const
double boundedValue(double) const
double maximum() const
double transform(double s) const
void setSingleSteps(uint)
Set the number of steps for a single increment.
double upperBound() const
static double qwtAlignToScaleDiv(const QwtAbstractSlider *slider, double value)
QList< double > ticks(int tickType) const
QwtAbstractSlider(QWidget *parent=NULL)
Constructor.
virtual double transform(double value) const =0
virtual ~QwtAbstractSlider()
Destructor.


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10