qwt_counter.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
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; // Never saw an abs(delta) < 240
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             // correct rounding error if value = 0
00668             value = 0.0;
00669         }
00670         else if ( qFuzzyCompare( value, max ) )
00671         {
00672             // correct rounding error at the border
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         // 1. save enabled state of the smallest down- and up-button
00701         // 2. change enabled state on under- or over-flow
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     // Now we replace default sizeHint contribution of d_data->valueEdit by
00776     // what we really need.
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 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56