qwt_abstract_slider.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_abstract_slider.h"
00011 #include "qwt_abstract_scale_draw.h"
00012 #include "qwt_math.h"
00013 #include "qwt_scale_map.h"
00014 #include <qevent.h>
00015 
00016 #if QT_VERSION < 0x040601
00017 #define qFabs(x) ::fabs(x)
00018 #endif
00019 
00020 static double qwtAlignToScaleDiv( 
00021     const QwtAbstractSlider *slider, double value )
00022 {
00023     const QwtScaleDiv &sd = slider->scaleDiv();
00024 
00025     const int tValue = slider->transform( value );
00026 
00027     if ( tValue == slider->transform( sd.lowerBound() ) )
00028         return sd.lowerBound();
00029 
00030     if ( tValue == slider->transform( sd.lowerBound() ) )
00031         return sd.upperBound();
00032 
00033     for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
00034     {
00035         const QList<double> ticks = sd.ticks( i );
00036         for ( int j = 0; j < ticks.size(); j++ )
00037         {
00038             if ( slider->transform( ticks[ j ] ) == tValue )
00039                 return ticks[ j ];
00040         }
00041     }
00042 
00043     return value;
00044 }
00045 
00046 class QwtAbstractSlider::PrivateData
00047 {
00048 public:
00049     PrivateData():
00050         isScrolling( false ),
00051         isTracking( true ),
00052         pendingValueChanged( false ),
00053         readOnly( false ),
00054         totalSteps( 100 ),
00055         singleSteps( 1 ),
00056         pageSteps( 10 ),
00057         stepAlignment( true ),
00058         isValid( false ),
00059         value( 0.0 ),
00060         wrapping( false ),
00061         invertedControls( false )
00062     {
00063     }
00064 
00065     bool isScrolling;
00066     bool isTracking;
00067     bool pendingValueChanged;
00068 
00069     bool readOnly;
00070 
00071     uint totalSteps;
00072     uint singleSteps;
00073     uint pageSteps;
00074     bool stepAlignment;
00075 
00076     bool isValid;
00077     double value;
00078 
00079     bool wrapping;
00080     bool invertedControls;
00081 };
00082 
00094 QwtAbstractSlider::QwtAbstractSlider( QWidget *parent ):
00095     QwtAbstractScale( parent )
00096 {
00097     d_data = new QwtAbstractSlider::PrivateData;
00098 
00099     setScale( 0.0, 100.0 );
00100     setFocusPolicy( Qt::StrongFocus );
00101 }
00102 
00104 QwtAbstractSlider::~QwtAbstractSlider()
00105 {
00106     delete d_data;
00107 }
00108 
00116 void QwtAbstractSlider::setValid( bool on )
00117 {
00118     if ( on != d_data->isValid )
00119     {
00120         d_data->isValid = on;
00121         sliderChange();
00122 
00123         Q_EMIT valueChanged( d_data->value );
00124     }   
00125 }   
00126 
00128 bool QwtAbstractSlider::isValid() const
00129 {
00130     return d_data->isValid;
00131 }   
00132 
00144 void QwtAbstractSlider::setReadOnly( bool on )
00145 {
00146     if ( d_data->readOnly != on )
00147     {
00148         d_data->readOnly = on;
00149         setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );
00150 
00151         update();
00152     }
00153 }
00154 
00162 bool QwtAbstractSlider::isReadOnly() const
00163 {
00164     return d_data->readOnly;
00165 }
00166 
00180 void QwtAbstractSlider::setTracking( bool on )
00181 {
00182     d_data->isTracking = on;
00183 }
00184 
00189 bool QwtAbstractSlider::isTracking() const
00190 {
00191     return d_data->isTracking;
00192 }
00193 
00198 void QwtAbstractSlider::mousePressEvent( QMouseEvent *event )
00199 {
00200     if ( isReadOnly() )
00201     {
00202         event->ignore();
00203         return;
00204     }
00205 
00206     if ( !d_data->isValid || lowerBound() == upperBound() )
00207         return;
00208 
00209     d_data->isScrolling = isScrollPosition( event->pos() );
00210 
00211     if ( d_data->isScrolling )
00212     {
00213         d_data->pendingValueChanged = false;
00214 
00215         Q_EMIT sliderPressed();
00216     }
00217 }
00218 
00223 void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event )
00224 {
00225     if ( isReadOnly() )
00226     {
00227         event->ignore();
00228         return;
00229     }
00230 
00231     if ( d_data->isValid && d_data->isScrolling )
00232     {
00233         double value = scrolledTo( event->pos() );
00234         if ( value != d_data->value )
00235         {
00236             value = boundedValue( value );
00237 
00238             if ( d_data->stepAlignment )
00239             {
00240                 value = alignedValue( value );
00241             }
00242             else
00243             {
00244                 value = qwtAlignToScaleDiv( this, value );
00245             }
00246 
00247             if ( value != d_data->value )
00248             {
00249                 d_data->value = value;
00250 
00251                 sliderChange();
00252 
00253                 Q_EMIT sliderMoved( d_data->value );
00254 
00255                 if ( d_data->isTracking )
00256                     Q_EMIT valueChanged( d_data->value );
00257                 else
00258                     d_data->pendingValueChanged = true;
00259             }
00260         }
00261     }
00262 }
00263 
00268 void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event )
00269 {
00270     if ( isReadOnly() )
00271     {
00272         event->ignore();
00273         return;
00274     }
00275 
00276     if ( d_data->isScrolling && d_data->isValid )
00277     {
00278         d_data->isScrolling = false;
00279 
00280         if ( d_data->pendingValueChanged )
00281             Q_EMIT valueChanged( d_data->value );
00282 
00283         Q_EMIT sliderReleased();
00284     }
00285 }
00286 
00299 void QwtAbstractSlider::wheelEvent( QWheelEvent *event )
00300 {
00301     if ( isReadOnly() )
00302     {
00303         event->ignore();
00304         return;
00305     }
00306 
00307     if ( !d_data->isValid || d_data->isScrolling )
00308         return;
00309 
00310     int numSteps = 0;
00311 
00312     if ( ( event->modifiers() & Qt::ControlModifier) ||
00313         ( event->modifiers() & Qt::ShiftModifier ) )
00314     {
00315         // one page regardless of delta
00316         numSteps = d_data->pageSteps;
00317         if ( event->delta() < 0 )
00318             numSteps = -numSteps;
00319     }
00320     else
00321     {
00322         const int numTurns = ( event->delta() / 120 );
00323         numSteps = numTurns * d_data->singleSteps;
00324     }
00325 
00326     if ( d_data->invertedControls )
00327         numSteps = -numSteps;
00328 
00329     const double value = incrementedValue( d_data->value, numSteps );
00330     if ( value != d_data->value )
00331     {
00332         d_data->value = value;
00333         sliderChange();
00334 
00335         Q_EMIT sliderMoved( d_data->value );
00336         Q_EMIT valueChanged( d_data->value );
00337     }
00338 }
00339 
00365 void QwtAbstractSlider::keyPressEvent( QKeyEvent *event )
00366 {
00367     if ( isReadOnly() )
00368     {
00369         event->ignore();
00370         return;
00371     }
00372 
00373     if ( !d_data->isValid || d_data->isScrolling )
00374         return;
00375 
00376     int numSteps = 0;
00377     double value = d_data->value;
00378 
00379     switch ( event->key() )
00380     {
00381         case Qt::Key_Left:
00382         {
00383             numSteps = -static_cast<int>( d_data->singleSteps );
00384             if ( isInverted() )
00385                 numSteps = -numSteps;
00386 
00387             break;
00388         }
00389         case Qt::Key_Right:
00390         {
00391             numSteps = d_data->singleSteps;
00392             if ( isInverted() )
00393                 numSteps = -numSteps;
00394 
00395             break;
00396         }
00397         case Qt::Key_Down:
00398         {
00399             numSteps = -static_cast<int>( d_data->singleSteps );
00400             if ( d_data->invertedControls )
00401                 numSteps = -numSteps;
00402             break;
00403         }
00404         case Qt::Key_Up:
00405         {
00406             numSteps = d_data->singleSteps;
00407             if ( d_data->invertedControls )
00408                 numSteps = -numSteps;
00409 
00410             break;
00411         }
00412         case Qt::Key_PageUp:
00413         {
00414             numSteps = d_data->pageSteps;
00415             if ( d_data->invertedControls )
00416                 numSteps = -numSteps;
00417             break;
00418         }
00419         case Qt::Key_PageDown:
00420         {
00421             numSteps = -static_cast<int>( d_data->pageSteps );
00422             if ( d_data->invertedControls )
00423                 numSteps = -numSteps;
00424             break;
00425         }
00426         case Qt::Key_Home:
00427         {
00428             value = minimum();
00429             break;
00430         }
00431         case Qt::Key_End:
00432         {
00433             value = maximum();
00434             break;
00435         }
00436         default:;
00437         {
00438             event->ignore();
00439         }
00440     }
00441 
00442     if ( numSteps != 0 )
00443     {
00444         value = incrementedValue( d_data->value, numSteps );
00445     }
00446 
00447     if ( value != d_data->value )
00448     {
00449         d_data->value = value;
00450         sliderChange();
00451 
00452         Q_EMIT sliderMoved( d_data->value );
00453         Q_EMIT valueChanged( d_data->value );
00454     }
00455 }
00456 
00469 void QwtAbstractSlider::setTotalSteps( uint stepCount )
00470 {
00471     d_data->totalSteps = stepCount;
00472 }
00473 
00478 uint QwtAbstractSlider::totalSteps() const
00479 {
00480     return d_data->totalSteps;
00481 }
00482 
00494 void QwtAbstractSlider::setSingleSteps( uint stepCount )
00495 {
00496     d_data->singleSteps = stepCount;
00497 }   
00498 
00503 uint QwtAbstractSlider::singleSteps() const
00504 {
00505     return d_data->singleSteps;
00506 }   
00507 
00519 void QwtAbstractSlider::setPageSteps( uint stepCount )
00520 {
00521     d_data->pageSteps = stepCount;
00522 }
00523 
00528 uint QwtAbstractSlider::pageSteps() const
00529 {
00530     return d_data->pageSteps;
00531 }
00532 
00542 void QwtAbstractSlider::setStepAlignment( bool on )
00543 {   
00544     if ( on != d_data->stepAlignment )
00545     {
00546         d_data->stepAlignment = on;
00547     }
00548 }   
00549     
00554 bool QwtAbstractSlider::stepAlignment() const
00555 {
00556     return d_data->stepAlignment;
00557 }
00558 
00565 void QwtAbstractSlider::setValue( double value )
00566 {
00567     value = qBound( minimum(), value, maximum() );
00568 
00569     const bool changed = ( d_data->value != value ) || !d_data->isValid;
00570 
00571     d_data->value = value;
00572     d_data->isValid = true;
00573 
00574     if ( changed )
00575     {
00576         sliderChange();
00577         Q_EMIT valueChanged( d_data->value );
00578     }
00579 }
00580 
00582 double QwtAbstractSlider::value() const
00583 {
00584     return d_data->value;
00585 }
00586 
00594 void QwtAbstractSlider::setWrapping( bool on )
00595 {
00596     d_data->wrapping = on;
00597 }   
00598 
00603 bool QwtAbstractSlider::wrapping() const
00604 {
00605     return d_data->wrapping;
00606 }
00607 
00623 void QwtAbstractSlider::setInvertedControls( bool on )
00624 {
00625     d_data->invertedControls = on;
00626 }
00627 
00632 bool QwtAbstractSlider::invertedControls() const
00633 {
00634     return d_data->invertedControls;
00635 }
00636 
00645 void QwtAbstractSlider::incrementValue( int stepCount )
00646 {
00647     const double value = incrementedValue( 
00648         d_data->value, stepCount );
00649 
00650     if ( value != d_data->value )
00651     {
00652         d_data->value = value;
00653         sliderChange();
00654     }
00655 }
00656 
00665 double QwtAbstractSlider::incrementedValue( 
00666     double value, int stepCount ) const
00667 {
00668     if ( d_data->totalSteps == 0 )
00669         return value;
00670 
00671     const QwtTransform *transformation =
00672         scaleMap().transformation();
00673 
00674     if ( transformation == NULL )
00675     {
00676         const double range = maximum() - minimum();
00677         value += stepCount * range / d_data->totalSteps;
00678     }
00679     else
00680     {
00681         QwtScaleMap map = scaleMap();
00682         map.setPaintInterval( 0, d_data->totalSteps );
00683 
00684         // we need equidant steps according to
00685         // paint device coordinates
00686         const double range = transformation->transform( maximum() ) 
00687             - transformation->transform( minimum() );
00688 
00689         const double stepSize = range / d_data->totalSteps;
00690 
00691         double v = transformation->transform( value );
00692 
00693         v = qRound( v / stepSize ) * stepSize; 
00694         v += stepCount * range / d_data->totalSteps;
00695 
00696         value = transformation->invTransform( v );
00697     }
00698 
00699     value = boundedValue( value );
00700 
00701     if ( d_data->stepAlignment )
00702         value = alignedValue( value );
00703 
00704     return value;
00705 }
00706 
00707 double QwtAbstractSlider::boundedValue( double value ) const
00708 {
00709     const double vmin = minimum();
00710     const double vmax = maximum();
00711 
00712     if ( d_data->wrapping && vmin != vmax )
00713     {
00714         const int fullCircle = 360 * 16;
00715 
00716         const double pd = scaleMap().pDist();
00717         if ( int( pd / fullCircle ) * fullCircle == pd )
00718         {
00719             // full circle scales: min and max are the same
00720             const double range = vmax - vmin;
00721 
00722             if ( value < vmin )
00723             {
00724                 value += ::ceil( ( vmin - value ) / range ) * range;
00725             }
00726             else if ( value > vmax )
00727             {
00728                 value -= ::ceil( ( value - vmax ) / range ) * range;
00729             }
00730         }
00731         else
00732         {
00733             if ( value < vmin )
00734                 value = vmax;
00735             else if ( value > vmax )
00736                 value = vmin;
00737         }
00738     }
00739     else
00740     {
00741         value = qBound( vmin, value, vmax );
00742     }
00743 
00744     return value;
00745 }
00746 
00747 double QwtAbstractSlider::alignedValue( double value ) const
00748 {
00749     if ( d_data->totalSteps == 0 )
00750         return value;
00751 
00752     double stepSize;
00753 
00754     if ( scaleMap().transformation() == NULL )
00755     {
00756         stepSize = ( maximum() - minimum() ) / d_data->totalSteps;
00757         if ( stepSize > 0.0 )
00758         {
00759             value = lowerBound() + 
00760                 qRound( ( value - lowerBound() ) / stepSize ) * stepSize;
00761         }
00762     }
00763     else
00764     {
00765         stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps;
00766 
00767         if ( stepSize > 0.0 )
00768         {
00769             double v = scaleMap().transform( value );
00770 
00771             v = scaleMap().p1() +
00772                 qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize;
00773 
00774             value = scaleMap().invTransform( v );
00775         }
00776     }
00777 
00778     if ( qAbs( stepSize ) > 1e-12 )
00779     {
00780         if ( qFuzzyCompare( value + 1.0, 1.0 ) )
00781         {
00782             // correct rounding error if value = 0
00783             value = 0.0;
00784         }
00785         else
00786         {
00787             // correct rounding error at the border
00788             if ( qFuzzyCompare( value, upperBound() ) )
00789                 value = upperBound();
00790             else if ( qFuzzyCompare( value, lowerBound() ) )
00791                 value = lowerBound();
00792         }
00793     }
00794 
00795     return value;
00796 }
00797 
00801 void QwtAbstractSlider::scaleChange()
00802 {
00803     const double value = qBound( minimum(), d_data->value, maximum() );
00804 
00805     const bool changed = ( value != d_data->value );
00806     if ( changed )
00807     {
00808         d_data->value = value;
00809     }
00810 
00811     if ( d_data->isValid || changed )
00812         Q_EMIT valueChanged( d_data->value );
00813 
00814     updateGeometry();
00815     update();
00816 }
00817 
00819 void QwtAbstractSlider::sliderChange()
00820 {
00821     update();
00822 }


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