00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_arrow_button.h"
00011 #include "qwt_math.h"
00012 #include "qwt_counter.h"
00013 #include <qlayout.h>
00014 #include <qlineedit.h>
00015 #include <qvalidator.h>
00016 #include <qevent.h>
00017 #include <qstyle.h>
00018
00019 class QwtCounter::PrivateData
00020 {
00021 public:
00022 PrivateData():
00023 minimum( 0.0 ),
00024 maximum( 0.0 ),
00025 singleStep( 1.0 ),
00026 isValid( false ),
00027 value( 0.0 ),
00028 wrapping( false )
00029 {
00030 increment[Button1] = 1;
00031 increment[Button2] = 10;
00032 increment[Button3] = 100;
00033 }
00034
00035 QwtArrowButton *buttonDown[ButtonCnt];
00036 QwtArrowButton *buttonUp[ButtonCnt];
00037 QLineEdit *valueEdit;
00038
00039 int increment[ButtonCnt];
00040 int numButtons;
00041
00042 double minimum;
00043 double maximum;
00044 double singleStep;
00045
00046 bool isValid;
00047 double value;
00048
00049 bool wrapping;
00050 };
00051
00063 QwtCounter::QwtCounter( QWidget *parent ):
00064 QWidget( parent )
00065 {
00066 initCounter();
00067 }
00068
00069 void QwtCounter::initCounter()
00070 {
00071 d_data = new PrivateData;
00072
00073 QHBoxLayout *layout = new QHBoxLayout( this );
00074 layout->setSpacing( 0 );
00075 layout->setMargin( 0 );
00076
00077 for ( int i = ButtonCnt - 1; i >= 0; i-- )
00078 {
00079 QwtArrowButton *btn =
00080 new QwtArrowButton( i + 1, Qt::DownArrow, this );
00081 btn->setFocusPolicy( Qt::NoFocus );
00082 layout->addWidget( btn );
00083
00084 connect( btn, SIGNAL( released() ), SLOT( btnReleased() ) );
00085 connect( btn, SIGNAL( clicked() ), SLOT( btnClicked() ) );
00086
00087 d_data->buttonDown[i] = btn;
00088 }
00089
00090 d_data->valueEdit = new QLineEdit( this );
00091 d_data->valueEdit->setReadOnly( false );
00092 d_data->valueEdit->setValidator( new QDoubleValidator( d_data->valueEdit ) );
00093 layout->addWidget( d_data->valueEdit );
00094
00095 connect( d_data->valueEdit, SIGNAL( editingFinished() ),
00096 SLOT( textChanged() ) );
00097
00098 layout->setStretchFactor( d_data->valueEdit, 10 );
00099
00100 for ( int i = 0; i < ButtonCnt; i++ )
00101 {
00102 QwtArrowButton *btn =
00103 new QwtArrowButton( i + 1, Qt::UpArrow, this );
00104 btn->setFocusPolicy( Qt::NoFocus );
00105 layout->addWidget( btn );
00106
00107 connect( btn, SIGNAL( released() ), SLOT( btnReleased() ) );
00108 connect( btn, SIGNAL( clicked() ), SLOT( btnClicked() ) );
00109
00110 d_data->buttonUp[i] = btn;
00111 }
00112
00113 setNumButtons( 2 );
00114 setRange( 0.0, 1.0 );
00115 setSingleStep( 0.001 );
00116 setValue( 0.0 );
00117
00118 setSizePolicy(
00119 QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
00120
00121 setFocusProxy( d_data->valueEdit );
00122 setFocusPolicy( Qt::StrongFocus );
00123 }
00124
00126 QwtCounter::~QwtCounter()
00127 {
00128 delete d_data;
00129 }
00130
00141 void QwtCounter::setValid( bool on )
00142 {
00143 if ( on != d_data->isValid )
00144 {
00145 d_data->isValid = on;
00146
00147 updateButtons();
00148
00149 if ( d_data->isValid )
00150 {
00151 showNumber( value() );
00152 Q_EMIT valueChanged( value() );
00153 }
00154 else
00155 {
00156 d_data->valueEdit->setText( QString::null );
00157 }
00158 }
00159 }
00160
00165 bool QwtCounter::isValid() const
00166 {
00167 return d_data->isValid;
00168 }
00169
00176 void QwtCounter::setReadOnly( bool on )
00177 {
00178 d_data->valueEdit->setReadOnly( on );
00179 }
00180
00185 bool QwtCounter::isReadOnly() const
00186 {
00187 return d_data->valueEdit->isReadOnly();
00188 }
00189
00201 void QwtCounter::setValue( double value )
00202 {
00203 const double vmin = qMin( d_data->minimum, d_data->maximum );
00204 const double vmax = qMax( d_data->minimum, d_data->maximum );
00205
00206 value = qBound( vmin, value, vmax );
00207
00208 if ( !d_data->isValid || value != d_data->value )
00209 {
00210 d_data->isValid = true;
00211 d_data->value = value;
00212
00213 showNumber( value );
00214 updateButtons();
00215
00216 Q_EMIT valueChanged( value );
00217 }
00218 }
00219
00224 double QwtCounter::value() const
00225 {
00226 return d_data->value;
00227 }
00228
00240 void QwtCounter::setRange( double min, double max )
00241 {
00242 max = qMax( min, max );
00243
00244 if ( d_data->maximum == max && d_data->minimum == min )
00245 return;
00246
00247 d_data->minimum = min;
00248 d_data->maximum = max;
00249
00250 setSingleStep( singleStep() );
00251
00252 const double value = qBound( min, d_data->value, max );
00253
00254 if ( value != d_data->value )
00255 {
00256 d_data->value = value;
00257
00258 if ( d_data->isValid )
00259 {
00260 showNumber( value );
00261 Q_EMIT valueChanged( value );
00262 }
00263 }
00264
00265 updateButtons();
00266 }
00267
00276 void QwtCounter::setMinimum( double value )
00277 {
00278 setRange( value, maximum() );
00279 }
00280
00285 double QwtCounter::minimum() const
00286 {
00287 return d_data->minimum;
00288 }
00289
00296 void QwtCounter::setMaximum( double value )
00297 {
00298 setRange( minimum(), value );
00299 }
00300
00305 double QwtCounter::maximum() const
00306 {
00307 return d_data->maximum;
00308 }
00309
00318 void QwtCounter::setSingleStep( double stepSize )
00319 {
00320 d_data->singleStep = qMax( stepSize, 0.0 );
00321 }
00322
00327 double QwtCounter::singleStep() const
00328 {
00329 return d_data->singleStep;
00330 }
00331
00341 void QwtCounter::setWrapping( bool on )
00342 {
00343 d_data->wrapping = on;
00344 }
00345
00350 bool QwtCounter::wrapping() const
00351 {
00352 return d_data->wrapping;
00353 }
00354
00361 void QwtCounter::setNumButtons( int numButtons )
00362 {
00363 if ( numButtons < 0 || numButtons > QwtCounter::ButtonCnt )
00364 return;
00365
00366 for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
00367 {
00368 if ( i < numButtons )
00369 {
00370 d_data->buttonDown[i]->show();
00371 d_data->buttonUp[i]->show();
00372 }
00373 else
00374 {
00375 d_data->buttonDown[i]->hide();
00376 d_data->buttonUp[i]->hide();
00377 }
00378 }
00379
00380 d_data->numButtons = numButtons;
00381 }
00382
00387 int QwtCounter::numButtons() const
00388 {
00389 return d_data->numButtons;
00390 }
00391
00402 void QwtCounter::setIncSteps( QwtCounter::Button button, int numSteps )
00403 {
00404 if ( button >= 0 && button < QwtCounter::ButtonCnt )
00405 d_data->increment[ button ] = numSteps;
00406 }
00407
00415 int QwtCounter::incSteps( QwtCounter::Button button ) const
00416 {
00417 if ( button >= 0 && button < QwtCounter::ButtonCnt )
00418 return d_data->increment[ button ];
00419
00420 return 0;
00421 }
00422
00423
00428 void QwtCounter::setStepButton1( int nSteps )
00429 {
00430 setIncSteps( QwtCounter::Button1, nSteps );
00431 }
00432
00434 int QwtCounter::stepButton1() const
00435 {
00436 return incSteps( QwtCounter::Button1 );
00437 }
00438
00443 void QwtCounter::setStepButton2( int nSteps )
00444 {
00445 setIncSteps( QwtCounter::Button2, nSteps );
00446 }
00447
00449 int QwtCounter::stepButton2() const
00450 {
00451 return incSteps( QwtCounter::Button2 );
00452 }
00453
00458 void QwtCounter::setStepButton3( int nSteps )
00459 {
00460 setIncSteps( QwtCounter::Button3, nSteps );
00461 }
00462
00464 int QwtCounter::stepButton3() const
00465 {
00466 return incSteps( QwtCounter::Button3 );
00467 }
00468
00470 void QwtCounter::textChanged()
00471 {
00472 bool converted = false;
00473
00474 const double value = d_data->valueEdit->text().toDouble( &converted );
00475 if ( converted )
00476 setValue( value );
00477 }
00478
00484 bool QwtCounter::event( QEvent *event )
00485 {
00486 if ( event->type() == QEvent::PolishRequest )
00487 {
00488 const int w = d_data->valueEdit->fontMetrics().width( "W" ) + 8;
00489 for ( int i = 0; i < ButtonCnt; i++ )
00490 {
00491 d_data->buttonDown[i]->setMinimumWidth( w );
00492 d_data->buttonUp[i]->setMinimumWidth( w );
00493 }
00494 }
00495
00496 return QWidget::event( event );
00497 }
00498
00521 void QwtCounter::keyPressEvent ( QKeyEvent *event )
00522 {
00523 bool accepted = true;
00524
00525 switch ( event->key() )
00526 {
00527 case Qt::Key_Home:
00528 {
00529 if ( event->modifiers() & Qt::ControlModifier )
00530 setValue( minimum() );
00531 else
00532 accepted = false;
00533 break;
00534 }
00535 case Qt::Key_End:
00536 {
00537 if ( event->modifiers() & Qt::ControlModifier )
00538 setValue( maximum() );
00539 else
00540 accepted = false;
00541 break;
00542 }
00543 case Qt::Key_Up:
00544 {
00545 incrementValue( d_data->increment[0] );
00546 break;
00547 }
00548 case Qt::Key_Down:
00549 {
00550 incrementValue( -d_data->increment[0] );
00551 break;
00552 }
00553 case Qt::Key_PageUp:
00554 case Qt::Key_PageDown:
00555 {
00556 int increment = d_data->increment[0];
00557 if ( d_data->numButtons >= 2 )
00558 increment = d_data->increment[1];
00559 if ( d_data->numButtons >= 3 )
00560 {
00561 if ( event->modifiers() & Qt::ShiftModifier )
00562 increment = d_data->increment[2];
00563 }
00564 if ( event->key() == Qt::Key_PageDown )
00565 increment = -increment;
00566 incrementValue( increment );
00567 break;
00568 }
00569 default:
00570 {
00571 accepted = false;
00572 }
00573 }
00574
00575 if ( accepted )
00576 {
00577 event->accept();
00578 return;
00579 }
00580
00581 QWidget::keyPressEvent ( event );
00582 }
00583
00588 void QwtCounter::wheelEvent( QWheelEvent *event )
00589 {
00590 event->accept();
00591
00592 if ( d_data->numButtons <= 0 )
00593 return;
00594
00595 int increment = d_data->increment[0];
00596 if ( d_data->numButtons >= 2 )
00597 {
00598 if ( event->modifiers() & Qt::ControlModifier )
00599 increment = d_data->increment[1];
00600 }
00601 if ( d_data->numButtons >= 3 )
00602 {
00603 if ( event->modifiers() & Qt::ShiftModifier )
00604 increment = d_data->increment[2];
00605 }
00606
00607 for ( int i = 0; i < d_data->numButtons; i++ )
00608 {
00609 if ( d_data->buttonDown[i]->geometry().contains( event->pos() ) ||
00610 d_data->buttonUp[i]->geometry().contains( event->pos() ) )
00611 {
00612 increment = d_data->increment[i];
00613 }
00614 }
00615
00616 const int wheel_delta = 120;
00617
00618 #if 1
00619 int delta = event->delta();
00620 if ( delta >= 2 * wheel_delta )
00621 delta /= 2;
00622 #endif
00623
00624 incrementValue( delta / wheel_delta * increment );
00625 }
00626
00627 void QwtCounter::incrementValue( int numSteps )
00628 {
00629 const double min = d_data->minimum;
00630 const double max = d_data->maximum;
00631 double stepSize = d_data->singleStep;
00632
00633 if ( !d_data->isValid || min >= max || stepSize <= 0.0 )
00634 return;
00635
00636
00637 #if 1
00638 stepSize = qMax( stepSize, 1.0e-10 * ( max - min ) );
00639 #endif
00640
00641 double value = d_data->value + numSteps * stepSize;
00642
00643 if ( d_data->wrapping )
00644 {
00645 const double range = max - min;
00646
00647 if ( value < min )
00648 {
00649 value += ::ceil( ( min - value ) / range ) * range;
00650 }
00651 else if ( value > max )
00652 {
00653 value -= ::ceil( ( value - max ) / range ) * range;
00654 }
00655 }
00656 else
00657 {
00658 value = qBound( min, value, max );
00659 }
00660
00661 value = min + qRound( ( value - min ) / stepSize ) * stepSize;
00662
00663 if ( stepSize > 1e-12 )
00664 {
00665 if ( qFuzzyCompare( value + 1.0, 1.0 ) )
00666 {
00667
00668 value = 0.0;
00669 }
00670 else if ( qFuzzyCompare( value, max ) )
00671 {
00672
00673 value = max;
00674 }
00675 }
00676
00677 if ( value != d_data->value )
00678 {
00679 d_data->value = value;
00680 showNumber( d_data->value );
00681 updateButtons();
00682
00683 Q_EMIT valueChanged( d_data->value );
00684 }
00685 }
00686
00687
00696 void QwtCounter::updateButtons()
00697 {
00698 if ( d_data->isValid )
00699 {
00700
00701
00702
00703 for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
00704 {
00705 d_data->buttonDown[i]->setEnabled( value() > minimum() );
00706 d_data->buttonUp[i]->setEnabled( value() < maximum() );
00707 }
00708 }
00709 else
00710 {
00711 for ( int i = 0; i < QwtCounter::ButtonCnt; i++ )
00712 {
00713 d_data->buttonDown[i]->setEnabled( false );
00714 d_data->buttonUp[i]->setEnabled( false );
00715 }
00716 }
00717 }
00723 void QwtCounter::showNumber( double number )
00724 {
00725 QString text;
00726 text.setNum( number );
00727
00728 const int cursorPos = d_data->valueEdit->cursorPosition();
00729 d_data->valueEdit->setText( text );
00730 d_data->valueEdit->setCursorPosition( cursorPos );
00731 }
00732
00734 void QwtCounter::btnClicked()
00735 {
00736 for ( int i = 0; i < ButtonCnt; i++ )
00737 {
00738 if ( d_data->buttonUp[i] == sender() )
00739 incrementValue( d_data->increment[i] );
00740
00741 if ( d_data->buttonDown[i] == sender() )
00742 incrementValue( -d_data->increment[i] );
00743 }
00744 }
00745
00747 void QwtCounter::btnReleased()
00748 {
00749 Q_EMIT buttonReleased( value() );
00750 }
00751
00753 QSize QwtCounter::sizeHint() const
00754 {
00755 QString tmp;
00756
00757 int w = tmp.setNum( minimum() ).length();
00758 int w1 = tmp.setNum( maximum() ).length();
00759 if ( w1 > w )
00760 w = w1;
00761 w1 = tmp.setNum( minimum() + singleStep() ).length();
00762 if ( w1 > w )
00763 w = w1;
00764 w1 = tmp.setNum( maximum() - singleStep() ).length();
00765 if ( w1 > w )
00766 w = w1;
00767
00768 tmp.fill( '9', w );
00769
00770 QFontMetrics fm( d_data->valueEdit->font() );
00771 w = fm.width( tmp ) + 2;
00772 if ( d_data->valueEdit->hasFrame() )
00773 w += 2 * style()->pixelMetric( QStyle::PM_DefaultFrameWidth );
00774
00775
00776
00777
00778 w += QWidget::sizeHint().width() - d_data->valueEdit->sizeHint().width();
00779
00780 const int h = qMin( QWidget::sizeHint().height(),
00781 d_data->valueEdit->minimumSizeHint().height() );
00782 return QSize( w, h );
00783 }