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


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:17