qwt_counter.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_arrow_button.h"
11 #include "qwt_counter.h"
12 #include "qwt_painter.h"
13 #include "qwt_math.h"
14 
15 #include <qlayout.h>
16 #include <qlineedit.h>
17 #include <qvalidator.h>
18 #include <qevent.h>
19 #include <qstyle.h>
20 
22 {
23 public:
25  minimum( 0.0 ),
26  maximum( 0.0 ),
27  singleStep( 1.0 ),
28  isValid( false ),
29  value( 0.0 ),
30  wrapping( false )
31  {
32  increment[Button1] = 1;
33  increment[Button2] = 10;
34  increment[Button3] = 100;
35  }
36 
39  QLineEdit *valueEdit;
40 
43 
44  double minimum;
45  double maximum;
46  double singleStep;
47 
48  bool isValid;
49  double value;
50 
51  bool wrapping;
52 };
53 
65 QwtCounter::QwtCounter( QWidget *parent ):
66  QWidget( parent )
67 {
68  initCounter();
69 }
70 
72 {
73  d_data = new PrivateData;
74 
75  QHBoxLayout *layout = new QHBoxLayout( this );
76  layout->setSpacing( 0 );
77  layout->setContentsMargins( QMargins() );
78 
79  for ( int i = ButtonCnt - 1; i >= 0; i-- )
80  {
81  QwtArrowButton *btn =
82  new QwtArrowButton( i + 1, Qt::DownArrow, this );
83  btn->setFocusPolicy( Qt::NoFocus );
84  layout->addWidget( btn );
85 
86  connect( btn, SIGNAL(released()), SLOT(btnReleased()) );
87  connect( btn, SIGNAL(clicked()), SLOT(btnClicked()) );
88 
89  d_data->buttonDown[i] = btn;
90  }
91 
92  d_data->valueEdit = new QLineEdit( this );
93  d_data->valueEdit->setReadOnly( false );
94  d_data->valueEdit->setValidator( new QDoubleValidator( d_data->valueEdit ) );
95  layout->addWidget( d_data->valueEdit );
96 
97  connect( d_data->valueEdit, SIGNAL(editingFinished()), SLOT(textChanged()) );
98 
99  layout->setStretchFactor( d_data->valueEdit, 10 );
100 
101  for ( int i = 0; i < ButtonCnt; i++ )
102  {
103  QwtArrowButton *btn =
104  new QwtArrowButton( i + 1, Qt::UpArrow, this );
105  btn->setFocusPolicy( Qt::NoFocus );
106  layout->addWidget( btn );
107 
108  connect( btn, SIGNAL(released()), SLOT(btnReleased()) );
109  connect( btn, SIGNAL(clicked()), SLOT(btnClicked()) );
110 
111  d_data->buttonUp[i] = btn;
112  }
113 
114  setNumButtons( 2 );
115  setRange( 0.0, 1.0 );
116  setSingleStep( 0.001 );
117  setValue( 0.0 );
118 
119  setSizePolicy(
120  QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
121 
122  setFocusProxy( d_data->valueEdit );
123  setFocusPolicy( Qt::StrongFocus );
124 }
125 
128 {
129  delete d_data;
130 }
131 
142 void QwtCounter::setValid( bool on )
143 {
144  if ( on != d_data->isValid )
145  {
146  d_data->isValid = on;
147 
148  updateButtons();
149 
150  if ( d_data->isValid )
151  {
152  showNumber( value() );
153  Q_EMIT valueChanged( value() );
154  }
155  else
156  {
157  d_data->valueEdit->setText( QString() );
158  }
159  }
160 }
161 
167 {
168  return d_data->isValid;
169 }
170 
177 void QwtCounter::setReadOnly( bool on )
178 {
179  d_data->valueEdit->setReadOnly( on );
180 }
181 
187 {
188  return d_data->valueEdit->isReadOnly();
189 }
190 
203 {
204  const double vmin = qwtMinF( d_data->minimum, d_data->maximum );
205  const double vmax = qwtMaxF( d_data->minimum, d_data->maximum );
206 
207  value = qBound( vmin, value, vmax );
208 
209  if ( !d_data->isValid || value != d_data->value )
210  {
211  d_data->isValid = true;
212  d_data->value = value;
213 
214  showNumber( value );
215  updateButtons();
216 
217  Q_EMIT valueChanged( value );
218  }
219 }
220 
225 double QwtCounter::value() const
226 {
227  return d_data->value;
228 }
229 
241 void QwtCounter::setRange( double min, double max )
242 {
243  max = qwtMaxF( min, max );
244 
245  if ( d_data->maximum == max && d_data->minimum == min )
246  return;
247 
248  d_data->minimum = min;
249  d_data->maximum = max;
250 
252 
253  const double value = qBound( min, d_data->value, max );
254 
255  if ( value != d_data->value )
256  {
257  d_data->value = value;
258 
259  if ( d_data->isValid )
260  {
261  showNumber( value );
262  Q_EMIT valueChanged( value );
263  }
264  }
265 
266  updateButtons();
267 }
268 
278 {
279  setRange( value, maximum() );
280 }
281 
286 double QwtCounter::minimum() const
287 {
288  return d_data->minimum;
289 }
290 
298 {
299  setRange( minimum(), value );
300 }
301 
306 double QwtCounter::maximum() const
307 {
308  return d_data->maximum;
309 }
310 
319 void QwtCounter::setSingleStep( double stepSize )
320 {
321  d_data->singleStep = qwtMaxF( stepSize, 0.0 );
322 }
323 
328 double QwtCounter::singleStep() const
329 {
330  return d_data->singleStep;
331 }
332 
342 void QwtCounter::setWrapping( bool on )
343 {
344  d_data->wrapping = on;
345 }
346 
351 bool QwtCounter::wrapping() const
352 {
353  return d_data->wrapping;
354 }
355 
363 {
364  if ( numButtons < 0 || numButtons > QwtCounter::ButtonCnt )
365  return;
366 
367  for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
368  {
369  if ( i < numButtons )
370  {
371  d_data->buttonDown[i]->show();
372  d_data->buttonUp[i]->show();
373  }
374  else
375  {
376  d_data->buttonDown[i]->hide();
377  d_data->buttonUp[i]->hide();
378  }
379  }
380 
382 }
383 
388 int QwtCounter::numButtons() const
389 {
390  return d_data->numButtons;
391 }
392 
403 void QwtCounter::setIncSteps( QwtCounter::Button button, int numSteps )
404 {
405  if ( button >= 0 && button < QwtCounter::ButtonCnt )
406  d_data->increment[ button ] = numSteps;
407 }
408 
417 {
418  if ( button >= 0 && button < QwtCounter::ButtonCnt )
419  return d_data->increment[ button ];
420 
421  return 0;
422 }
423 
424 
429 void QwtCounter::setStepButton1( int nSteps )
430 {
431  setIncSteps( QwtCounter::Button1, nSteps );
432 }
433 
435 int QwtCounter::stepButton1() const
436 {
437  return incSteps( QwtCounter::Button1 );
438 }
439 
444 void QwtCounter::setStepButton2( int nSteps )
445 {
446  setIncSteps( QwtCounter::Button2, nSteps );
447 }
448 
450 int QwtCounter::stepButton2() const
451 {
452  return incSteps( QwtCounter::Button2 );
453 }
454 
459 void QwtCounter::setStepButton3( int nSteps )
460 {
461  setIncSteps( QwtCounter::Button3, nSteps );
462 }
463 
465 int QwtCounter::stepButton3() const
466 {
467  return incSteps( QwtCounter::Button3 );
468 }
469 
472 {
473  bool converted = false;
474 
475  const double value = d_data->valueEdit->text().toDouble( &converted );
476  if ( converted )
477  setValue( value );
478 }
479 
485 bool QwtCounter::event( QEvent *event )
486 {
487  if ( event->type() == QEvent::PolishRequest )
488  {
489  const QFontMetrics fm = d_data->valueEdit->fontMetrics();
490 
491  const int w = QwtPainter::horizontalAdvance( fm, "W" ) + 8;
492  for ( int i = 0; i < ButtonCnt; i++ )
493  {
494  d_data->buttonDown[i]->setMinimumWidth( w );
495  d_data->buttonUp[i]->setMinimumWidth( w );
496  }
497  }
498 
499  return QWidget::event( event );
500 }
501 
524 void QwtCounter::keyPressEvent ( QKeyEvent *event )
525 {
526  bool accepted = true;
527 
528  switch ( event->key() )
529  {
530  case Qt::Key_Home:
531  {
532  if ( event->modifiers() & Qt::ControlModifier )
533  setValue( minimum() );
534  else
535  accepted = false;
536  break;
537  }
538  case Qt::Key_End:
539  {
540  if ( event->modifiers() & Qt::ControlModifier )
541  setValue( maximum() );
542  else
543  accepted = false;
544  break;
545  }
546  case Qt::Key_Up:
547  {
549  break;
550  }
551  case Qt::Key_Down:
552  {
554  break;
555  }
556  case Qt::Key_PageUp:
557  case Qt::Key_PageDown:
558  {
559  int increment = d_data->increment[0];
560  if ( d_data->numButtons >= 2 )
561  increment = d_data->increment[1];
562  if ( d_data->numButtons >= 3 )
563  {
564  if ( event->modifiers() & Qt::ShiftModifier )
565  increment = d_data->increment[2];
566  }
567  if ( event->key() == Qt::Key_PageDown )
568  increment = -increment;
569  incrementValue( increment );
570  break;
571  }
572  default:
573  {
574  accepted = false;
575  }
576  }
577 
578  if ( accepted )
579  {
580  event->accept();
581  return;
582  }
583 
584  QWidget::keyPressEvent ( event );
585 }
586 
591 void QwtCounter::wheelEvent( QWheelEvent *event )
592 {
593  event->accept();
594 
595  if ( d_data->numButtons <= 0 )
596  return;
597 
598  int increment = d_data->increment[0];
599  if ( d_data->numButtons >= 2 )
600  {
601  if ( event->modifiers() & Qt::ControlModifier )
602  increment = d_data->increment[1];
603  }
604  if ( d_data->numButtons >= 3 )
605  {
606  if ( event->modifiers() & Qt::ShiftModifier )
607  increment = d_data->increment[2];
608  }
609 
610 #if QT_VERSION < 0x050e00
611  const QPoint wheelPos = event->pos();
612  const int wheelDelta = event->delta();
613 #else
614  const QPoint wheelPos = event->position().toPoint();
615 
616  const QPoint delta = event->angleDelta();
617  const int wheelDelta = ( qAbs( delta.x() ) > qAbs( delta.y() ) )
618  ? delta.x() : delta.y();
619 #endif
620 
621  for ( int i = 0; i < d_data->numButtons; i++ )
622  {
623  if ( d_data->buttonDown[i]->geometry().contains( wheelPos ) ||
624  d_data->buttonUp[i]->geometry().contains( wheelPos ) )
625  {
626  increment = d_data->increment[i];
627  }
628  }
629 
630  incrementValue( wheelDelta / 120 * increment );
631 }
632 
633 void QwtCounter::incrementValue( int numSteps )
634 {
635  const double min = d_data->minimum;
636  const double max = d_data->maximum;
637  double stepSize = d_data->singleStep;
638 
639  if ( !d_data->isValid || min >= max || stepSize <= 0.0 )
640  return;
641 
642 
643 #if 1
644  stepSize = qwtMaxF( stepSize, 1.0e-10 * ( max - min ) );
645 #endif
646 
647  double value = d_data->value + numSteps * stepSize;
648 
649  if ( d_data->wrapping )
650  {
651  const double range = max - min;
652 
653  if ( value < min )
654  {
655  value += std::ceil( ( min - value ) / range ) * range;
656  }
657  else if ( value > max )
658  {
659  value -= std::ceil( ( value - max ) / range ) * range;
660  }
661  }
662  else
663  {
664  value = qBound( min, value, max );
665  }
666 
667  value = min + qRound( ( value - min ) / stepSize ) * stepSize;
668 
669  if ( stepSize > 1e-12 )
670  {
671  if ( qFuzzyCompare( value + 1.0, 1.0 ) )
672  {
673  // correct rounding error if value = 0
674  value = 0.0;
675  }
676  else if ( qFuzzyCompare( value, max ) )
677  {
678  // correct rounding error at the border
679  value = max;
680  }
681  }
682 
683  if ( value != d_data->value )
684  {
685  d_data->value = value;
686  showNumber( d_data->value );
687  updateButtons();
688 
689  Q_EMIT valueChanged( d_data->value );
690  }
691 }
692 
693 
703 {
704  if ( d_data->isValid )
705  {
706  // 1. save enabled state of the smallest down- and up-button
707  // 2. change enabled state on under- or over-flow
708 
709  for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
710  {
711  d_data->buttonDown[i]->setEnabled( value() > minimum() );
712  d_data->buttonUp[i]->setEnabled( value() < maximum() );
713  }
714  }
715  else
716  {
717  for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
718  {
719  d_data->buttonDown[i]->setEnabled( false );
720  d_data->buttonUp[i]->setEnabled( false );
721  }
722  }
723 }
729 void QwtCounter::showNumber( double number )
730 {
731  QString text;
732  text.setNum( number );
733 
734  const int cursorPos = d_data->valueEdit->cursorPosition();
735  d_data->valueEdit->setText( text );
736  d_data->valueEdit->setCursorPosition( cursorPos );
737 }
738 
741 {
742  for ( int i = 0; i < ButtonCnt; i++ )
743  {
744  if ( d_data->buttonUp[i] == sender() )
746 
747  if ( d_data->buttonDown[i] == sender() )
749  }
750 }
751 
754 {
755  Q_EMIT buttonReleased( value() );
756 }
757 
759 QSize QwtCounter::sizeHint() const
760 {
761  QString tmp;
762 
763  int w = tmp.setNum( minimum() ).length();
764  int w1 = tmp.setNum( maximum() ).length();
765  if ( w1 > w )
766  w = w1;
767  w1 = tmp.setNum( minimum() + singleStep() ).length();
768  if ( w1 > w )
769  w = w1;
770  w1 = tmp.setNum( maximum() - singleStep() ).length();
771  if ( w1 > w )
772  w = w1;
773 
774  tmp.fill( '9', w );
775 
776  w = QwtPainter::horizontalAdvance( d_data->valueEdit->fontMetrics(), tmp ) + 2;
777 
778  if ( d_data->valueEdit->hasFrame() )
779  w += 2 * style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
780 
781  // Now we replace default sizeHint contribution of d_data->valueEdit by
782  // what we really need.
783 
784  w += QWidget::sizeHint().width() - d_data->valueEdit->sizeHint().width();
785 
786  const int h = qMin( QWidget::sizeHint().height(),
787  d_data->valueEdit->minimumSizeHint().height() );
788 
789  return QSize( w, h );
790 }
791 
792 #if QWT_MOC_INCLUDE
793 #include "moc_qwt_counter.cpp"
794 #endif
double maximum() const
void textChanged()
Set from lineedit.
QwtArrowButton * buttonUp[ButtonCnt]
Definition: qwt_counter.cpp:38
void valueChanged(double value)
void btnClicked()
Button clicked.
virtual ~QwtCounter()
Destructor.
virtual void keyPressEvent(QKeyEvent *) QWT_OVERRIDE
QwtArrowButton * buttonDown[ButtonCnt]
Definition: qwt_counter.cpp:37
void buttonReleased(double value)
QWT_CONSTEXPR float qwtMaxF(float a, float b)
Definition: qwt_math.h:123
void setMinimum(double)
void setStepButton1(int nSteps)
void setWrapping(bool)
En/Disable wrapping.
void setStepButton2(int nSteps)
void incrementValue(int numSteps)
Button intended for medium steps.
Definition: qwt_counter.h:73
Button intended for minor steps.
Definition: qwt_counter.h:70
QWT_CONSTEXPR float qwtMinF(float a, float b)
Definition: qwt_math.h:99
void updateButtons()
Update buttons according to the current value.
Button
Button index.
Definition: qwt_counter.h:67
#define min(A, B)
Definition: Log.c:64
#define max(A, B)
Definition: Socket.h:88
Arrow Button.
virtual QSize sizeHint() const QWT_OVERRIDE
A size hint.
static int horizontalAdvance(const QFontMetrics &, const QString &)
virtual void wheelEvent(QWheelEvent *) QWT_OVERRIDE
Number of buttons.
Definition: qwt_counter.h:79
void setRange(double min, double max)
Set the minimum and maximum values.
PrivateData * d_data
Definition: qwt_counter.h:157
void showNumber(double)
void setIncSteps(QwtCounter::Button, int numSteps)
bool wrapping() const
int numButtons() const
double value() const
int increment[ButtonCnt]
Definition: qwt_counter.cpp:41
int stepButton1() const
int stepButton3() const
Button intended for large steps.
Definition: qwt_counter.h:76
virtual bool event(QEvent *) QWT_OVERRIDE
bool isValid() const
void setValue(double)
Set a new value without adjusting to the step raster.
void setSingleStep(double stepSize)
Set the step size of the counter.
void initCounter()
Definition: qwt_counter.cpp:71
void btnReleased()
Button released.
int incSteps(QwtCounter::Button) const
int stepButton2() const
void setReadOnly(bool)
Allow/disallow the user to manually edit the value.
void setMaximum(double)
double minimum() const
void setStepButton3(int nSteps)
void setValid(bool)
void setNumButtons(int)
double singleStep() const
QwtCounter(QWidget *parent=NULL)
Definition: qwt_counter.cpp:65
bool isReadOnly() const


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