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"
12 #include "qwt_math.h"
13 #include "qwt_scale_map.h"
14 #include <qevent.h>
15 
16 #if QT_VERSION < 0x040601
17 #define qFabs(x) ::fabs(x)
18 #endif
19 
20 static double qwtAlignToScaleDiv(
21  const QwtAbstractSlider *slider, double value )
22 {
23  const QwtScaleDiv &sd = slider->scaleDiv();
24 
25  const int tValue = slider->transform( value );
26 
27  if ( tValue == slider->transform( sd.lowerBound() ) )
28  return sd.lowerBound();
29 
30  if ( tValue == slider->transform( sd.upperBound() ) )
31  return sd.upperBound();
32 
33  for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
34  {
35  const QList<double> ticks = sd.ticks( i );
36  for ( int j = 0; j < ticks.size(); j++ )
37  {
38  if ( slider->transform( ticks[ j ] ) == tValue )
39  return ticks[ j ];
40  }
41  }
42 
43  return value;
44 }
45 
47 {
48 public:
50  isScrolling( false ),
51  isTracking( true ),
52  pendingValueChanged( false ),
53  readOnly( false ),
54  totalSteps( 100 ),
55  singleSteps( 1 ),
56  pageSteps( 10 ),
57  stepAlignment( true ),
58  isValid( false ),
59  value( 0.0 ),
60  wrapping( false ),
61  invertedControls( false )
62  {
63  }
64 
66  bool isTracking;
68 
69  bool readOnly;
70 
71  uint totalSteps;
73  uint pageSteps;
75 
76  bool isValid;
77  double value;
78 
79  bool wrapping;
81 };
82 
95  QwtAbstractScale( parent )
96 {
98 
99  setScale( 0.0, 100.0 );
100  setFocusPolicy( Qt::StrongFocus );
101 }
102 
105 {
106  delete d_data;
107 }
108 
117 {
118  if ( on != d_data->isValid )
119  {
120  d_data->isValid = on;
121  sliderChange();
122 
123  Q_EMIT valueChanged( d_data->value );
124  }
125 }
126 
129 {
130  return d_data->isValid;
131 }
132 
145 {
146  if ( d_data->readOnly != on )
147  {
148  d_data->readOnly = on;
149  setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );
150 
151  update();
152  }
153 }
154 
163 {
164  return d_data->readOnly;
165 }
166 
181 {
182  d_data->isTracking = on;
183 }
184 
190 {
191  return d_data->isTracking;
192 }
193 
198 void QwtAbstractSlider::mousePressEvent( QMouseEvent *event )
199 {
200  if ( isReadOnly() )
201  {
202  event->ignore();
203  return;
204  }
205 
206  if ( !d_data->isValid || lowerBound() == upperBound() )
207  return;
208 
209  d_data->isScrolling = isScrollPosition( event->pos() );
210 
211  if ( d_data->isScrolling )
212  {
213  d_data->pendingValueChanged = false;
214 
215  Q_EMIT sliderPressed();
216  }
217 }
218 
223 void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event )
224 {
225  if ( isReadOnly() )
226  {
227  event->ignore();
228  return;
229  }
230 
231  if ( d_data->isValid && d_data->isScrolling )
232  {
233  double value = scrolledTo( event->pos() );
234  if ( value != d_data->value )
235  {
236  value = boundedValue( value );
237 
238  if ( d_data->stepAlignment )
239  {
240  value = alignedValue( value );
241  }
242  else
243  {
244  value = qwtAlignToScaleDiv( this, value );
245  }
246 
247  if ( value != d_data->value )
248  {
249  d_data->value = value;
250 
251  sliderChange();
252 
253  Q_EMIT sliderMoved( d_data->value );
254 
255  if ( d_data->isTracking )
256  Q_EMIT valueChanged( d_data->value );
257  else
258  d_data->pendingValueChanged = true;
259  }
260  }
261  }
262 }
263 
268 void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event )
269 {
270  if ( isReadOnly() )
271  {
272  event->ignore();
273  return;
274  }
275 
276  if ( d_data->isScrolling && d_data->isValid )
277  {
278  d_data->isScrolling = false;
279 
281  Q_EMIT valueChanged( d_data->value );
282 
283  Q_EMIT sliderReleased();
284  }
285 }
286 
299 void QwtAbstractSlider::wheelEvent( QWheelEvent *event )
300 {
301  if ( isReadOnly() )
302  {
303  event->ignore();
304  return;
305  }
306 
307  if ( !d_data->isValid || d_data->isScrolling )
308  return;
309 
310  int numSteps = 0;
311 
312  if ( ( event->modifiers() & Qt::ControlModifier) ||
313  ( event->modifiers() & Qt::ShiftModifier ) )
314  {
315  // one page regardless of delta
316  numSteps = d_data->pageSteps;
317  if ( event->delta() < 0 )
318  numSteps = -numSteps;
319  }
320  else
321  {
322  const int numTurns = ( event->delta() / 120 );
323  numSteps = numTurns * d_data->singleSteps;
324  }
325 
326  if ( d_data->invertedControls )
327  numSteps = -numSteps;
328 
329  const double value = incrementedValue( d_data->value, numSteps );
330  if ( value != d_data->value )
331  {
332  d_data->value = value;
333  sliderChange();
334 
335  Q_EMIT sliderMoved( d_data->value );
336  Q_EMIT valueChanged( d_data->value );
337  }
338 }
339 
365 void QwtAbstractSlider::keyPressEvent( QKeyEvent *event )
366 {
367  if ( isReadOnly() )
368  {
369  event->ignore();
370  return;
371  }
372 
373  if ( !d_data->isValid || d_data->isScrolling )
374  return;
375 
376  int numSteps = 0;
377  double value = d_data->value;
378 
379  switch ( event->key() )
380  {
381  case Qt::Key_Left:
382  {
383  numSteps = -static_cast<int>( d_data->singleSteps );
384  if ( isInverted() )
385  numSteps = -numSteps;
386 
387  break;
388  }
389  case Qt::Key_Right:
390  {
391  numSteps = d_data->singleSteps;
392  if ( isInverted() )
393  numSteps = -numSteps;
394 
395  break;
396  }
397  case Qt::Key_Down:
398  {
399  numSteps = -static_cast<int>( d_data->singleSteps );
400  if ( d_data->invertedControls )
401  numSteps = -numSteps;
402  break;
403  }
404  case Qt::Key_Up:
405  {
406  numSteps = d_data->singleSteps;
407  if ( d_data->invertedControls )
408  numSteps = -numSteps;
409 
410  break;
411  }
412  case Qt::Key_PageUp:
413  {
414  numSteps = d_data->pageSteps;
415  if ( d_data->invertedControls )
416  numSteps = -numSteps;
417  break;
418  }
419  case Qt::Key_PageDown:
420  {
421  numSteps = -static_cast<int>( d_data->pageSteps );
422  if ( d_data->invertedControls )
423  numSteps = -numSteps;
424  break;
425  }
426  case Qt::Key_Home:
427  {
428  value = minimum();
429  break;
430  }
431  case Qt::Key_End:
432  {
433  value = maximum();
434  break;
435  }
436  default:;
437  {
438  event->ignore();
439  }
440  }
441 
442  if ( numSteps != 0 )
443  {
444  value = incrementedValue( d_data->value, numSteps );
445  }
446 
447  if ( value != d_data->value )
448  {
449  d_data->value = value;
450  sliderChange();
451 
452  Q_EMIT sliderMoved( d_data->value );
453  Q_EMIT valueChanged( d_data->value );
454  }
455 }
456 
469 void QwtAbstractSlider::setTotalSteps( uint stepCount )
470 {
471  d_data->totalSteps = stepCount;
472 }
473 
479 {
480  return d_data->totalSteps;
481 }
482 
494 void QwtAbstractSlider::setSingleSteps( uint stepCount )
495 {
496  d_data->singleSteps = stepCount;
497 }
498 
504 {
505  return d_data->singleSteps;
506 }
507 
519 void QwtAbstractSlider::setPageSteps( uint stepCount )
520 {
521  d_data->pageSteps = stepCount;
522 }
523 
528 uint QwtAbstractSlider::pageSteps() const
529 {
530  return d_data->pageSteps;
531 }
532 
543 {
544  if ( on != d_data->stepAlignment )
545  {
546  d_data->stepAlignment = on;
547  }
548 }
549 
555 {
556  return d_data->stepAlignment;
557 }
558 
566 {
567  value = qBound( minimum(), value, maximum() );
568 
569  const bool changed = ( d_data->value != value ) || !d_data->isValid;
570 
571  d_data->value = value;
572  d_data->isValid = true;
573 
574  if ( changed )
575  {
576  sliderChange();
577  Q_EMIT valueChanged( d_data->value );
578  }
579 }
580 
582 double QwtAbstractSlider::value() const
583 {
584  return d_data->value;
585 }
586 
595 {
596  d_data->wrapping = on;
597 }
598 
603 bool QwtAbstractSlider::wrapping() const
604 {
605  return d_data->wrapping;
606 }
607 
624 {
625  d_data->invertedControls = on;
626 }
627 
633 {
634  return d_data->invertedControls;
635 }
636 
646 {
647  const double value = incrementedValue(
648  d_data->value, stepCount );
649 
650  if ( value != d_data->value )
651  {
652  d_data->value = value;
653  sliderChange();
654  }
655 }
656 
666  double value, int stepCount ) const
667 {
668  if ( d_data->totalSteps == 0 )
669  return value;
670 
671  const QwtTransform *transformation =
673 
674  if ( transformation == NULL )
675  {
676  const double range = maximum() - minimum();
677  value += stepCount * range / d_data->totalSteps;
678  }
679  else
680  {
681  QwtScaleMap map = scaleMap();
683 
684  // we need equidant steps according to
685  // paint device coordinates
686  const double range = transformation->transform( maximum() )
687  - transformation->transform( minimum() );
688 
689  const double stepSize = range / d_data->totalSteps;
690 
691  double v = transformation->transform( value );
692 
693  v = qRound( v / stepSize ) * stepSize;
694  v += stepCount * range / d_data->totalSteps;
695 
696  value = transformation->invTransform( v );
697  }
698 
699  value = boundedValue( value );
700 
701  if ( d_data->stepAlignment )
702  value = alignedValue( value );
703 
704  return value;
705 }
706 
708 {
709  const double vmin = minimum();
710  const double vmax = maximum();
711 
712  if ( d_data->wrapping && vmin != vmax )
713  {
714  const int fullCircle = 360 * 16;
715 
716  const double pd = scaleMap().pDist();
717  if ( int( pd / fullCircle ) * fullCircle == pd )
718  {
719  // full circle scales: min and max are the same
720  const double range = vmax - vmin;
721 
722  if ( value < vmin )
723  {
724  value += ::ceil( ( vmin - value ) / range ) * range;
725  }
726  else if ( value > vmax )
727  {
728  value -= ::ceil( ( value - vmax ) / range ) * range;
729  }
730  }
731  else
732  {
733  if ( value < vmin )
734  value = vmax;
735  else if ( value > vmax )
736  value = vmin;
737  }
738  }
739  else
740  {
741  value = qBound( vmin, value, vmax );
742  }
743 
744  return value;
745 }
746 
748 {
749  if ( d_data->totalSteps == 0 )
750  return value;
751 
752  double stepSize;
753 
754  if ( scaleMap().transformation() == NULL )
755  {
756  stepSize = ( maximum() - minimum() ) / d_data->totalSteps;
757  if ( stepSize > 0.0 )
758  {
759  value = lowerBound() +
760  qRound( ( value - lowerBound() ) / stepSize ) * stepSize;
761  }
762  }
763  else
764  {
765  stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps;
766 
767  if ( stepSize > 0.0 )
768  {
769  double v = scaleMap().transform( value );
770 
771  v = scaleMap().p1() +
772  qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize;
773 
774  value = scaleMap().invTransform( v );
775  }
776  }
777 
778  if ( qAbs( stepSize ) > 1e-12 )
779  {
780  if ( qFuzzyCompare( value + 1.0, 1.0 ) )
781  {
782  // correct rounding error if value = 0
783  value = 0.0;
784  }
785  else
786  {
787  // correct rounding error at the border
788  if ( qFuzzyCompare( value, upperBound() ) )
789  value = upperBound();
790  else if ( qFuzzyCompare( value, lowerBound() ) )
791  value = lowerBound();
792  }
793  }
794 
795  return value;
796 }
797 
802 {
803  const double value = qBound( minimum(), d_data->value, maximum() );
804 
805  const bool changed = ( value != d_data->value );
806  if ( changed )
807  {
808  d_data->value = value;
809  }
810 
811  if ( d_data->isValid || changed )
812  Q_EMIT valueChanged( d_data->value );
813 
814  updateGeometry();
815  update();
816 }
817 
820 {
821  update();
822 }
int v
double p1() const
void setScale(double lowerBound, double upperBound)
Specify a scale.
bool stepAlignment() const
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()
void setValue(double val)
void valueChanged(double value)
Notify a change of value.
const QwtScaleMap & scaleMap() const
virtual void wheelEvent(QWheelEvent *)
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:36
void setTracking(bool)
Enables or disables tracking.
virtual void scaleChange()
uint singleSteps() const
void sliderMoved(double value)
double upperBound() const
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
An abstract base class for slider widgets with a scale.
virtual void keyPressEvent(QKeyEvent *)
double value() const
double minimum() const
uint pageSteps() const
virtual void mouseMoveEvent(QMouseEvent *)
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:30
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:55
bool isInverted() const
double pDist() const
double lowerBound() const
double boundedValue(double) const
virtual void mouseReleaseEvent(QMouseEvent *)
double maximum() const
void incrementValue(int numSteps)
virtual void mousePressEvent(QMouseEvent *)
double transform(double s) const
void setSingleSteps(uint)
Set the number of steps for a single increment.
int i
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 Sat Jul 6 2019 03:44:17