Qwt User's Guide: qwt_counter.cpp Source File

Qwt User's Guide 6.2.0

qwt_counter.cpp
1 /******************************************************************************
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
21 class QwtCounter::PrivateData
22 {
23 public:
24 PrivateData()
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
37 QwtArrowButton* buttonDown[ButtonCnt];
38 QwtArrowButton* buttonUp[ButtonCnt];
39 QLineEdit* valueEdit;
40
41 int increment[ButtonCnt];
42 int numButtons;
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
71 void QwtCounter::initCounter()
72 {
73 m_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 m_data->buttonDown[i] = btn;
90 }
91
92 m_data->valueEdit = new QLineEdit( this );
93 m_data->valueEdit->setReadOnly( false );
94 m_data->valueEdit->setValidator( new QDoubleValidator( m_data->valueEdit ) );
95 layout->addWidget( m_data->valueEdit );
96
97 connect( m_data->valueEdit, SIGNAL(editingFinished()), SLOT(textChanged()) );
98
99 layout->setStretchFactor( m_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 m_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( m_data->valueEdit );
123 setFocusPolicy( Qt::StrongFocus );
124 }
125
127 QwtCounter::~QwtCounter()
128 {
129 delete m_data;
130 }
131
142 void QwtCounter::setValid( bool on )
143 {
144 if ( on != m_data->isValid )
145 {
146 m_data->isValid = on;
147
148 updateButtons();
149
150 if ( m_data->isValid )
151 {
152 showNumber( value() );
153 Q_EMIT valueChanged( value() );
154 }
155 else
156 {
157 m_data->valueEdit->setText( QString() );
158 }
159 }
160 }
161
166 bool QwtCounter::isValid() const
167 {
168 return m_data->isValid;
169 }
170
177 void QwtCounter::setReadOnly( bool on )
178 {
179 m_data->valueEdit->setReadOnly( on );
180 }
181
186 bool QwtCounter::isReadOnly() const
187 {
188 return m_data->valueEdit->isReadOnly();
189 }
190
202 void QwtCounter::setValue( double value )
203 {
204 const double vmin = qwtMinF( m_data->minimum, m_data->maximum );
205 const double vmax = qwtMaxF( m_data->minimum, m_data->maximum );
206
207 value = qBound( vmin, value, vmax );
208
209 if ( !m_data->isValid || value != m_data->value )
210 {
211 m_data->isValid = true;
212 m_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 m_data->value;
228 }
229
241 void QwtCounter::setRange( double min, double max )
242 {
243 max = qwtMaxF( min, max );
244
245 if ( m_data->maximum == max && m_data->minimum == min )
246 return;
247
248 m_data->minimum = min;
249 m_data->maximum = max;
250
251 setSingleStep( singleStep() );
252
253 const double value = qBound( min, m_data->value, max );
254
255 if ( value != m_data->value )
256 {
257 m_data->value = value;
258
259 if ( m_data->isValid )
260 {
261 showNumber( value );
262 Q_EMIT valueChanged( value );
263 }
264 }
265
266 updateButtons();
267 }
268
277 void QwtCounter::setMinimum( double value )
278 {
279 setRange( value, maximum() );
280 }
281
286 double QwtCounter::minimum() const
287 {
288 return m_data->minimum;
289 }
290
297 void QwtCounter::setMaximum( double value )
298 {
299 setRange( minimum(), value );
300 }
301
306 double QwtCounter::maximum() const
307 {
308 return m_data->maximum;
309 }
310
319 void QwtCounter::setSingleStep( double stepSize )
320 {
321 m_data->singleStep = qwtMaxF( stepSize, 0.0 );
322 }
323
328 double QwtCounter::singleStep() const
329 {
330 return m_data->singleStep;
331 }
332
342 void QwtCounter::setWrapping( bool on )
343 {
344 m_data->wrapping = on;
345 }
346
351 bool QwtCounter::wrapping() const
352 {
353 return m_data->wrapping;
354 }
355
362 void QwtCounter::setNumButtons( int numButtons )
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 m_data->buttonDown[i]->show();
372 m_data->buttonUp[i]->show();
373 }
374 else
375 {
376 m_data->buttonDown[i]->hide();
377 m_data->buttonUp[i]->hide();
378 }
379 }
380
381 m_data->numButtons = numButtons;
382 }
383
388 int QwtCounter::numButtons() const
389 {
390 return m_data->numButtons;
391 }
392
403 void QwtCounter::setIncSteps( QwtCounter::Button button, int numSteps )
404 {
405 if ( button >= 0 && button < QwtCounter::ButtonCnt )
406 m_data->increment[ button ] = numSteps;
407 }
408
416 int QwtCounter::incSteps( QwtCounter::Button button ) const
417 {
418 if ( button >= 0 && button < QwtCounter::ButtonCnt )
419 return m_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
471 void QwtCounter::textChanged()
472 {
473 bool converted = false;
474
475 const double value = m_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 = m_data->valueEdit->fontMetrics();
490
491 const int w = QwtPainter::horizontalAdvance( fm, "W" ) + 8;
492 for ( int i = 0; i < ButtonCnt; i++ )
493 {
494 m_data->buttonDown[i]->setMinimumWidth( w );
495 m_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 {
548 incrementValue( m_data->increment[0] );
549 break;
550 }
551 case Qt::Key_Down:
552 {
553 incrementValue( -m_data->increment[0] );
554 break;
555 }
556 case Qt::Key_PageUp:
557 case Qt::Key_PageDown:
558 {
559 int increment = m_data->increment[0];
560 if ( m_data->numButtons >= 2 )
561 increment = m_data->increment[1];
562 if ( m_data->numButtons >= 3 )
563 {
564 if ( event->modifiers() & Qt::ShiftModifier )
565 increment = m_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 ( m_data->numButtons <= 0 )
596 return;
597
598 int increment = m_data->increment[0];
599 if ( m_data->numButtons >= 2 )
600 {
601 if ( event->modifiers() & Qt::ControlModifier )
602 increment = m_data->increment[1];
603 }
604 if ( m_data->numButtons >= 3 )
605 {
606 if ( event->modifiers() & Qt::ShiftModifier )
607 increment = m_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 < m_data->numButtons; i++ )
622 {
623 if ( m_data->buttonDown[i]->geometry().contains( wheelPos ) ||
624 m_data->buttonUp[i]->geometry().contains( wheelPos ) )
625 {
626 increment = m_data->increment[i];
627 }
628 }
629
630 incrementValue( wheelDelta / 120 * increment );
631 }
632
633 void QwtCounter::incrementValue( int numSteps )
634 {
635 const double min = m_data->minimum;
636 const double max = m_data->maximum;
637 double stepSize = m_data->singleStep;
638
639 if ( !m_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 = m_data->value + numSteps * stepSize;
648
649 if ( m_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 != m_data->value )
684 {
685 m_data->value = value;
686 showNumber( m_data->value );
687 updateButtons();
688
689 Q_EMIT valueChanged( m_data->value );
690 }
691 }
692
693
702 void QwtCounter::updateButtons()
703 {
704 if ( m_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 m_data->buttonDown[i]->setEnabled( value() > minimum() );
712 m_data->buttonUp[i]->setEnabled( value() < maximum() );
713 }
714 }
715 else
716 {
717 for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
718 {
719 m_data->buttonDown[i]->setEnabled( false );
720 m_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 = m_data->valueEdit->cursorPosition();
735 m_data->valueEdit->setText( text );
736 m_data->valueEdit->setCursorPosition( cursorPos );
737 }
738
740 void QwtCounter::btnClicked()
741 {
742 for ( int i = 0; i < ButtonCnt; i++ )
743 {
744 if ( m_data->buttonUp[i] == sender() )
745 incrementValue( m_data->increment[i] );
746
747 if ( m_data->buttonDown[i] == sender() )
748 incrementValue( -m_data->increment[i] );
749 }
750 }
751
753 void QwtCounter::btnReleased()
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( m_data->valueEdit->fontMetrics(), tmp ) + 2;
777
778 if ( m_data->valueEdit->hasFrame() )
779 w += 2 * style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
780
781 // Now we replace default sizeHint contribution of m_data->valueEdit by
782 // what we really need.
783
784 w += QWidget::sizeHint().width() - m_data->valueEdit->sizeHint().width();
785
786 const int h = qMin( QWidget::sizeHint().height(),
787 m_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
QwtArrowButton
Arrow Button.
Definition: qwt_arrow_button.h:24
QwtCounter::Button
Button
Button index.
Definition: qwt_counter.h:68
QwtCounter::Button1
@ Button1
Button intended for minor steps.
Definition: qwt_counter.h:70
QwtCounter::Button3
@ Button3
Button intended for large steps.
Definition: qwt_counter.h:76
QwtCounter::Button2
@ Button2
Button intended for medium steps.
Definition: qwt_counter.h:73
QwtCounter::ButtonCnt
@ ButtonCnt
Number of buttons.
Definition: qwt_counter.h:79
QwtCounter::setStepButton2
void setStepButton2(int nSteps)
Definition: qwt_counter.cpp:444
QwtCounter::minimum
double minimum() const
Definition: qwt_counter.cpp:286
QwtCounter::value
double value() const
Definition: qwt_counter.cpp:225
QwtCounter::stepButton3
int stepButton3() const
returns the number of increment steps for button 3
Definition: qwt_counter.cpp:465
QwtCounter::setValue
void setValue(double)
Set a new value without adjusting to the step raster.
Definition: qwt_counter.cpp:202
QwtCounter::setMinimum
void setMinimum(double)
Definition: qwt_counter.cpp:277
QwtCounter::sizeHint
virtual QSize sizeHint() const override
A size hint.
Definition: qwt_counter.cpp:759
QwtCounter::isReadOnly
bool isReadOnly() const
Definition: qwt_counter.cpp:186
QwtCounter::wrapping
bool wrapping() const
Definition: qwt_counter.cpp:351
QwtCounter::isValid
bool isValid() const
Definition: qwt_counter.cpp:166
QwtCounter::~QwtCounter
virtual ~QwtCounter()
Destructor.
Definition: qwt_counter.cpp:127
QwtCounter::buttonReleased
void buttonReleased(double value)
QwtCounter::setStepButton3
void setStepButton3(int nSteps)
Definition: qwt_counter.cpp:459
QwtCounter::maximum
double maximum() const
Definition: qwt_counter.cpp:306
QwtCounter::singleStep
double singleStep() const
Definition: qwt_counter.cpp:328
QwtCounter::setWrapping
void setWrapping(bool)
En/Disable wrapping.
Definition: qwt_counter.cpp:342
QwtCounter::setNumButtons
void setNumButtons(int)
Definition: qwt_counter.cpp:362
QwtCounter::incSteps
int incSteps(QwtCounter::Button) const
Definition: qwt_counter.cpp:416
QwtCounter::event
virtual bool event(QEvent *) override
Definition: qwt_counter.cpp:485
QwtCounter::setValid
void setValid(bool)
Definition: qwt_counter.cpp:142
QwtCounter::numButtons
int numButtons() const
Definition: qwt_counter.cpp:388
QwtCounter::keyPressEvent
virtual void keyPressEvent(QKeyEvent *) override
Definition: qwt_counter.cpp:524
QwtCounter::setIncSteps
void setIncSteps(QwtCounter::Button, int numSteps)
Definition: qwt_counter.cpp:403
QwtCounter::stepButton2
int stepButton2() const
returns the number of increment steps for button 2
Definition: qwt_counter.cpp:450
QwtCounter::setReadOnly
void setReadOnly(bool)
Allow/disallow the user to manually edit the value.
Definition: qwt_counter.cpp:177
QwtCounter::setRange
void setRange(double min, double max)
Set the minimum and maximum values.
Definition: qwt_counter.cpp:241
QwtCounter::valueChanged
void valueChanged(double value)
QwtCounter::setStepButton1
void setStepButton1(int nSteps)
Definition: qwt_counter.cpp:429
QwtCounter::QwtCounter
QwtCounter(QWidget *parent=NULL)
Definition: qwt_counter.cpp:65
QwtCounter::setSingleStep
void setSingleStep(double stepSize)
Set the step size of the counter.
Definition: qwt_counter.cpp:319
QwtCounter::setMaximum
void setMaximum(double)
Definition: qwt_counter.cpp:297
QwtCounter::wheelEvent
virtual void wheelEvent(QWheelEvent *) override
Definition: qwt_counter.cpp:591
QwtCounter::stepButton1
int stepButton1() const
returns the number of increment steps for button 1
Definition: qwt_counter.cpp:435
QwtPainter::horizontalAdvance
static int horizontalAdvance(const QFontMetrics &, const QString &)
Definition: qwt_painter.cpp:1379