qwt_picker.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_picker.h"
00011 #include "qwt_picker_machine.h"
00012 #include "qwt_painter.h"
00013 #include "qwt_math.h"
00014 #include "qwt_widget_overlay.h"
00015 #include <qapplication.h>
00016 #include <qevent.h>
00017 #include <qpainter.h>
00018 #include <qframe.h>
00019 #include <qcursor.h>
00020 #include <qbitmap.h>
00021 #include <qpointer.h>
00022 #include <qpaintengine.h>
00023 #include <qmath.h>
00024 
00025 static inline QRegion qwtMaskRegion( const QRect &r, int penWidth )
00026 {
00027     const int pw = qMax( penWidth, 1 );
00028     const int pw2 = penWidth / 2;
00029 
00030     int x1 = r.left() - pw2;
00031     int x2 = r.right() + 1 + pw2 + ( pw % 2 );
00032 
00033     int y1 = r.top() - pw2;
00034     int y2 = r.bottom() + 1 + pw2 + ( pw % 2 );
00035 
00036     QRegion region;
00037 
00038     region += QRect( x1, y1, x2 - x1, pw );
00039     region += QRect( x1, y1, pw, y2 - y1 );
00040     region += QRect( x1, y2 - pw, x2 - x1, pw );
00041     region += QRect( x2 - pw, y1, pw, y2 - y1 );
00042 
00043     return region;
00044 }
00045 
00046 static inline QRegion qwtMaskRegion( const QLine &l, int penWidth )
00047 {
00048     const int pw = qMax( penWidth, 1 );
00049     const int pw2 = penWidth / 2;
00050 
00051     QRegion region;
00052 
00053     if ( l.x1() == l.x2() )
00054     {
00055         region += QRect( l.x1() - pw2, l.y1(), 
00056             pw, l.y2() ).normalized();
00057     }
00058     else if ( l.y1() == l.y2() )
00059     {
00060         region += QRect( l.x1(), l.y1() - pw2, 
00061             l.x2(), pw ).normalized();
00062     }
00063 
00064     return region;
00065 }
00066 
00067 class QwtPickerRubberband: public QwtWidgetOverlay
00068 {
00069 public:
00070     QwtPickerRubberband( QwtPicker *, QWidget * );
00071 
00072 protected:
00073     virtual void drawOverlay( QPainter * ) const;
00074     virtual QRegion maskHint() const;
00075 
00076     QwtPicker *d_picker;
00077 };
00078 
00079 class QwtPickerTracker: public QwtWidgetOverlay
00080 {                                  
00081 public:
00082     QwtPickerTracker( QwtPicker *, QWidget * );
00083     
00084 protected:
00085     virtual void drawOverlay( QPainter * ) const;
00086     virtual QRegion maskHint() const;
00087     
00088     QwtPicker *d_picker;
00089 };  
00090 
00091 
00092 class QwtPicker::PrivateData
00093 {
00094 public:
00095     PrivateData():
00096         enabled( false ),
00097         stateMachine( NULL ),
00098         resizeMode( QwtPicker::Stretch ),
00099         rubberBand( QwtPicker::NoRubberBand ),
00100         trackerMode( QwtPicker::AlwaysOff ),
00101         isActive( false ),
00102         trackerPosition( -1, -1 ),
00103         mouseTracking( false ),
00104         openGL( false )
00105     {
00106     }
00107         
00108     bool enabled;
00109 
00110     QwtPickerMachine *stateMachine;
00111 
00112     QwtPicker::ResizeMode resizeMode;
00113 
00114     QwtPicker::RubberBand rubberBand;
00115     QPen rubberBandPen;
00116 
00117     QwtPicker::DisplayMode trackerMode;
00118     QPen trackerPen;
00119     QFont trackerFont;
00120 
00121     QPolygon pickedPoints;
00122     bool isActive;
00123     QPoint trackerPosition;
00124 
00125     bool mouseTracking; // used to save previous value
00126 
00127     QPointer< QwtPickerRubberband > rubberBandOverlay;
00128     QPointer< QwtPickerTracker> trackerOverlay;
00129 
00130     bool openGL;
00131 };
00132 
00133 QwtPickerRubberband::QwtPickerRubberband(
00134         QwtPicker *picker, QWidget *parent ):
00135     QwtWidgetOverlay( parent ),
00136     d_picker( picker )
00137 {
00138     setMaskMode( QwtWidgetOverlay::MaskHint );
00139 }
00140 
00141 QRegion QwtPickerRubberband::maskHint() const
00142 {
00143     return d_picker->rubberBandMask();
00144 }
00145 
00146 void QwtPickerRubberband::drawOverlay( QPainter *painter ) const
00147 {
00148     painter->setPen( d_picker->rubberBandPen() );
00149     d_picker->drawRubberBand( painter );
00150 }
00151 
00152 QwtPickerTracker::QwtPickerTracker(
00153         QwtPicker *picker, QWidget *parent ):
00154     QwtWidgetOverlay( parent ),
00155     d_picker( picker )
00156 {
00157     setMaskMode( QwtWidgetOverlay::MaskHint );
00158 }
00159 
00160 QRegion QwtPickerTracker::maskHint() const
00161 {
00162     return d_picker->trackerMask();
00163 }
00164 
00165 void QwtPickerTracker::drawOverlay( QPainter *painter ) const
00166 {
00167     painter->setPen( d_picker->trackerPen() );
00168     d_picker->drawTracker( painter );
00169 }
00170 
00180 QwtPicker::QwtPicker( QWidget *parent ):
00181     QObject( parent )
00182 {
00183     init( parent, NoRubberBand, AlwaysOff );
00184 }
00185 
00193 QwtPicker::QwtPicker( RubberBand rubberBand,
00194         DisplayMode trackerMode, QWidget *parent ):
00195     QObject( parent )
00196 {
00197     init( parent, rubberBand, trackerMode );
00198 }
00199 
00201 QwtPicker::~QwtPicker()
00202 {
00203     setMouseTracking( false );
00204 
00205     delete d_data->stateMachine;
00206     delete d_data->rubberBandOverlay;
00207     delete d_data->trackerOverlay;
00208 
00209     delete d_data;
00210 }
00211 
00213 void QwtPicker::init( QWidget *parent,
00214     RubberBand rubberBand, DisplayMode trackerMode )
00215 {
00216     d_data = new PrivateData;
00217 
00218     d_data->rubberBand = rubberBand;
00219 
00220     if ( parent )
00221     {
00222         if ( parent->focusPolicy() == Qt::NoFocus )
00223             parent->setFocusPolicy( Qt::WheelFocus );
00224 
00225         d_data->openGL = parent->inherits( "QGLWidget" );
00226         d_data->trackerFont = parent->font();
00227         d_data->mouseTracking = parent->hasMouseTracking();
00228 
00229         setEnabled( true );
00230     }
00231 
00232     setTrackerMode( trackerMode );
00233 }
00234 
00241 void QwtPicker::setStateMachine( QwtPickerMachine *stateMachine )
00242 {
00243     if ( d_data->stateMachine != stateMachine )
00244     {
00245         reset();
00246 
00247         delete d_data->stateMachine;
00248         d_data->stateMachine = stateMachine;
00249 
00250         if ( d_data->stateMachine )
00251             d_data->stateMachine->reset();
00252     }
00253 }
00254 
00259 QwtPickerMachine *QwtPicker::stateMachine()
00260 {
00261     return d_data->stateMachine;
00262 }
00263 
00268 const QwtPickerMachine *QwtPicker::stateMachine() const
00269 {
00270     return d_data->stateMachine;
00271 }
00272 
00274 QWidget *QwtPicker::parentWidget()
00275 {
00276     QObject *obj = parent();
00277     if ( obj && obj->isWidgetType() )
00278         return static_cast<QWidget *>( obj );
00279 
00280     return NULL;
00281 }
00282 
00284 const QWidget *QwtPicker::parentWidget() const
00285 {
00286     QObject *obj = parent();
00287     if ( obj && obj->isWidgetType() )
00288         return static_cast< const QWidget *>( obj );
00289 
00290     return NULL;
00291 }
00292 
00301 void QwtPicker::setRubberBand( RubberBand rubberBand )
00302 {
00303     d_data->rubberBand = rubberBand;
00304 }
00305 
00310 QwtPicker::RubberBand QwtPicker::rubberBand() const
00311 {
00312     return d_data->rubberBand;
00313 }
00314 
00331 void QwtPicker::setTrackerMode( DisplayMode mode )
00332 {
00333     if ( d_data->trackerMode != mode )
00334     {
00335         d_data->trackerMode = mode;
00336         setMouseTracking( d_data->trackerMode == AlwaysOn );
00337     }
00338 }
00339 
00344 QwtPicker::DisplayMode QwtPicker::trackerMode() const
00345 {
00346     return d_data->trackerMode;
00347 }
00348 
00363 void QwtPicker::setResizeMode( ResizeMode mode )
00364 {
00365     d_data->resizeMode = mode;
00366 }
00367 
00373 QwtPicker::ResizeMode QwtPicker::resizeMode() const
00374 {
00375     return d_data->resizeMode;
00376 }
00377 
00387 void QwtPicker::setEnabled( bool enabled )
00388 {
00389     if ( d_data->enabled != enabled )
00390     {
00391         d_data->enabled = enabled;
00392 
00393         QWidget *w = parentWidget();
00394         if ( w )
00395         {
00396             if ( enabled )
00397                 w->installEventFilter( this );
00398             else
00399                 w->removeEventFilter( this );
00400         }
00401 
00402         updateDisplay();
00403     }
00404 }
00405 
00411 bool QwtPicker::isEnabled() const
00412 {
00413     return d_data->enabled;
00414 }
00415 
00422 void QwtPicker::setTrackerFont( const QFont &font )
00423 {
00424     if ( font != d_data->trackerFont )
00425     {
00426         d_data->trackerFont = font;
00427         updateDisplay();
00428     }
00429 }
00430 
00436 QFont QwtPicker::trackerFont() const
00437 {
00438     return d_data->trackerFont;
00439 }
00440 
00447 void QwtPicker::setTrackerPen( const QPen &pen )
00448 {
00449     if ( pen != d_data->trackerPen )
00450     {
00451         d_data->trackerPen = pen;
00452         updateDisplay();
00453     }
00454 }
00455 
00460 QPen QwtPicker::trackerPen() const
00461 {
00462     return d_data->trackerPen;
00463 }
00464 
00471 void QwtPicker::setRubberBandPen( const QPen &pen )
00472 {
00473     if ( pen != d_data->rubberBandPen )
00474     {
00475         d_data->rubberBandPen = pen;
00476         updateDisplay();
00477     }
00478 }
00479 
00484 QPen QwtPicker::rubberBandPen() const
00485 {
00486     return d_data->rubberBandPen;
00487 }
00488 
00502 QwtText QwtPicker::trackerText( const QPoint &pos ) const
00503 {
00504     QString label;
00505 
00506     switch ( rubberBand() )
00507     {
00508         case HLineRubberBand:
00509             label.sprintf( "%d", pos.y() );
00510             break;
00511         case VLineRubberBand:
00512             label.sprintf( "%d", pos.x() );
00513             break;
00514         default:
00515             label.sprintf( "%d, %d", pos.x(), pos.y() );
00516     }
00517     return label;
00518 }
00519 
00526 QRegion QwtPicker::trackerMask() const
00527 {
00528     return trackerRect( d_data->trackerFont );
00529 }
00530 
00537 QRegion QwtPicker::rubberBandMask() const
00538 {
00539     QRegion mask;
00540 
00541     if ( !isActive() || rubberBand() == NoRubberBand ||
00542         rubberBandPen().style() == Qt::NoPen )
00543     {
00544         return mask;
00545     }
00546 
00547     const QPolygon pa = adjustedPoints( d_data->pickedPoints );
00548 
00549     QwtPickerMachine::SelectionType selectionType =
00550         QwtPickerMachine::NoSelection;
00551 
00552     if ( d_data->stateMachine )
00553         selectionType = d_data->stateMachine->selectionType();
00554 
00555     switch ( selectionType )
00556     {
00557         case QwtPickerMachine::NoSelection:
00558         case QwtPickerMachine::PointSelection:
00559         {
00560             if ( pa.count() < 1 )
00561                 return mask;
00562 
00563             const QPoint pos = pa[0];
00564             const int pw = rubberBandPen().width();
00565 
00566             const QRect pRect = pickArea().boundingRect().toRect();
00567             switch ( rubberBand() )
00568             {
00569                 case VLineRubberBand:
00570                 {
00571                     mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), 
00572                         pos.x(), pRect.bottom() ), pw );
00573                     break;
00574                 }
00575                 case HLineRubberBand:
00576                 {
00577                     mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), 
00578                         pRect.right(), pos.y() ), pw );
00579                     break;
00580                 }
00581                 case CrossRubberBand:
00582                 {
00583                     mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), 
00584                         pos.x(), pRect.bottom() ), pw );
00585                     mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), 
00586                         pRect.right(), pos.y() ), pw );
00587                     break;
00588                 }
00589                 default:
00590                     break;
00591             }
00592             break;
00593         }
00594         case QwtPickerMachine::RectSelection:
00595         {
00596             if ( pa.count() < 2 )
00597                 return mask;
00598 
00599             const int pw = rubberBandPen().width();
00600 
00601             switch ( rubberBand() )
00602             {
00603                 case RectRubberBand:
00604                 {
00605                     const QRect r = QRect( pa.first(), pa.last() );
00606                     mask = qwtMaskRegion( r.normalized(), pw );
00607                     break;
00608                 }
00609                 case EllipseRubberBand:
00610                 {
00611                     const QRect r = QRect( pa.first(), pa.last() );
00612                     mask += r.adjusted( -pw, -pw, pw, pw );
00613                     break;
00614                 }
00615                 default:
00616                     break;
00617             }
00618             break;
00619         }
00620         case QwtPickerMachine::PolygonSelection:
00621         {
00622             const int pw = rubberBandPen().width();
00623             if ( pw <= 1 )
00624             {
00625                 // because of the join style we better
00626                 // return a mask for a pen width <= 1 only
00627 
00628                 const int off = 2 * pw;
00629                 const QRect r = pa.boundingRect();
00630                 mask += r.adjusted( -off, -off, off, off );
00631             }
00632             break;
00633         }
00634         default:
00635             break;
00636     }
00637 
00638     return mask;
00639 }
00640 
00649 void QwtPicker::drawRubberBand( QPainter *painter ) const
00650 {
00651     if ( !isActive() || rubberBand() == NoRubberBand ||
00652         rubberBandPen().style() == Qt::NoPen )
00653     {
00654         return;
00655     }
00656 
00657     const QPolygon pa = adjustedPoints( d_data->pickedPoints );
00658 
00659     QwtPickerMachine::SelectionType selectionType =
00660         QwtPickerMachine::NoSelection;
00661 
00662     if ( d_data->stateMachine )
00663         selectionType = d_data->stateMachine->selectionType();
00664 
00665     switch ( selectionType )
00666     {
00667         case QwtPickerMachine::NoSelection:
00668         case QwtPickerMachine::PointSelection:
00669         {
00670             if ( pa.count() < 1 )
00671                 return;
00672 
00673             const QPoint pos = pa[0];
00674 
00675             const QRect pRect = pickArea().boundingRect().toRect();
00676             switch ( rubberBand() )
00677             {
00678                 case VLineRubberBand:
00679                 {
00680                     QwtPainter::drawLine( painter, pos.x(),
00681                         pRect.top(), pos.x(), pRect.bottom() );
00682                     break;
00683                 }
00684                 case HLineRubberBand:
00685                 {
00686                     QwtPainter::drawLine( painter, pRect.left(),
00687                         pos.y(), pRect.right(), pos.y() );
00688                     break;
00689                 }
00690                 case CrossRubberBand:
00691                 {
00692                     QwtPainter::drawLine( painter, pos.x(),
00693                         pRect.top(), pos.x(), pRect.bottom() );
00694                     QwtPainter::drawLine( painter, pRect.left(),
00695                         pos.y(), pRect.right(), pos.y() );
00696                     break;
00697                 }
00698                 default:
00699                     break;
00700             }
00701             break;
00702         }
00703         case QwtPickerMachine::RectSelection:
00704         {
00705             if ( pa.count() < 2 )
00706                 return;
00707 
00708             const QRect rect = QRect( pa.first(), pa.last() ).normalized();
00709             switch ( rubberBand() )
00710             {
00711                 case EllipseRubberBand:
00712                 {
00713                     QwtPainter::drawEllipse( painter, rect );
00714                     break;
00715                 }
00716                 case RectRubberBand:
00717                 {
00718                     QwtPainter::drawRect( painter, rect );
00719                     break;
00720                 }
00721                 default:
00722                     break;
00723             }
00724             break;
00725         }
00726         case QwtPickerMachine::PolygonSelection:
00727         {
00728             if ( rubberBand() == PolygonRubberBand )
00729                 painter->drawPolyline( pa );
00730             break;
00731         }
00732         default:
00733             break;
00734     }
00735 }
00736 
00744 void QwtPicker::drawTracker( QPainter *painter ) const
00745 {
00746     const QRect textRect = trackerRect( painter->font() );
00747     if ( !textRect.isEmpty() )
00748     {
00749         const QwtText label = trackerText( d_data->trackerPosition );
00750         if ( !label.isEmpty() )
00751             label.draw( painter, textRect );
00752     }
00753 }
00754 
00792 QPolygon QwtPicker::adjustedPoints( const QPolygon &points ) const
00793 {
00794     return points;
00795 }
00796 
00801 QPolygon QwtPicker::selection() const
00802 {
00803     return adjustedPoints( d_data->pickedPoints );
00804 }
00805 
00807 QPoint QwtPicker::trackerPosition() const
00808 {
00809     return d_data->trackerPosition;
00810 }
00811 
00821 QRect QwtPicker::trackerRect( const QFont &font ) const
00822 {
00823     if ( trackerMode() == AlwaysOff ||
00824         ( trackerMode() == ActiveOnly && !isActive() ) )
00825     {
00826         return QRect();
00827     }
00828 
00829     if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 )
00830         return QRect();
00831 
00832     QwtText text = trackerText( d_data->trackerPosition );
00833     if ( text.isEmpty() )
00834         return QRect();
00835 
00836     const QSizeF textSize = text.textSize( font );
00837     QRect textRect( 0, 0, qCeil( textSize.width() ), qCeil( textSize.height() ) );
00838 
00839     const QPoint &pos = d_data->trackerPosition;
00840 
00841     int alignment = 0;
00842     if ( isActive() && d_data->pickedPoints.count() > 1
00843         && rubberBand() != NoRubberBand )
00844     {
00845         const QPoint last =
00846             d_data->pickedPoints[int( d_data->pickedPoints.count() ) - 2];
00847 
00848         alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft;
00849         alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop;
00850     }
00851     else
00852         alignment = Qt::AlignTop | Qt::AlignRight;
00853 
00854     const int margin = 5;
00855 
00856     int x = pos.x();
00857     if ( alignment & Qt::AlignLeft )
00858         x -= textRect.width() + margin;
00859     else if ( alignment & Qt::AlignRight )
00860         x += margin;
00861 
00862     int y = pos.y();
00863     if ( alignment & Qt::AlignBottom )
00864         y += margin;
00865     else if ( alignment & Qt::AlignTop )
00866         y -= textRect.height() + margin;
00867 
00868     textRect.moveTopLeft( QPoint( x, y ) );
00869 
00870     const QRect pickRect = pickArea().boundingRect().toRect();
00871 
00872     int right = qMin( textRect.right(), pickRect.right() - margin );
00873     int bottom = qMin( textRect.bottom(), pickRect.bottom() - margin );
00874     textRect.moveBottomRight( QPoint( right, bottom ) );
00875 
00876     int left = qMax( textRect.left(), pickRect.left() + margin );
00877     int top = qMax( textRect.top(), pickRect.top() + margin );
00878     textRect.moveTopLeft( QPoint( left, top ) );
00879 
00880     return textRect;
00881 }
00882 
00902 bool QwtPicker::eventFilter( QObject *object, QEvent *event )
00903 {
00904     if ( object && object == parentWidget() )
00905     {
00906         switch ( event->type() )
00907         {
00908             case QEvent::Resize:
00909             {
00910                 const QResizeEvent *re = static_cast<QResizeEvent *>( event );
00911 
00912                 /*
00913                    Adding/deleting additional event filters inside of an event filter
00914                    is not safe dues to the implementation in Qt ( changing alist while iterating ).
00915                    So we create the overlays in a way, that they don't install en event filter
00916                    ( parent set to NULL ) and do the resizing here.
00917                  */
00918                 if ( d_data->trackerOverlay )
00919                     d_data->trackerOverlay->resize( re->size() );
00920 
00921                 if ( d_data->rubberBandOverlay )
00922                     d_data->rubberBandOverlay->resize( re->size() );
00923 
00924                 if ( d_data->resizeMode == Stretch )
00925                     stretchSelection( re->oldSize(), re->size() );
00926 
00927                 updateDisplay();
00928                 break;
00929             }
00930             case QEvent::Enter:
00931             {
00932                 widgetEnterEvent( event );
00933                 break;
00934             }
00935             case QEvent::Leave:
00936             {
00937                 widgetLeaveEvent( event );
00938                 break;
00939             }
00940             case QEvent::MouseButtonPress:
00941             {
00942                 widgetMousePressEvent( static_cast<QMouseEvent *>( event ) );
00943                 break;
00944             }
00945             case QEvent::MouseButtonRelease:
00946             {
00947                 widgetMouseReleaseEvent( static_cast<QMouseEvent *>( event ) );
00948                 break;
00949             }
00950             case QEvent::MouseButtonDblClick:
00951             {
00952                 widgetMouseDoubleClickEvent( static_cast<QMouseEvent *>( event ) );
00953                 break;
00954             }
00955             case QEvent::MouseMove:
00956             {
00957                 widgetMouseMoveEvent( static_cast<QMouseEvent *>( event ) );
00958                 break;
00959             }
00960             case QEvent::KeyPress:
00961             {
00962                 widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) );
00963                 break;
00964             }
00965             case QEvent::KeyRelease:
00966             {
00967                 widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) );
00968                 break;
00969             }
00970             case QEvent::Wheel:
00971             {
00972                 widgetWheelEvent( static_cast<QWheelEvent *>( event ) );
00973                 break;
00974             }
00975             default:
00976                 break;
00977         }
00978     }
00979     return false;
00980 }
00981 
00991 void QwtPicker::widgetMousePressEvent( QMouseEvent *mouseEvent )
00992 {
00993     transition( mouseEvent );
00994 }
00995 
01005 void QwtPicker::widgetMouseMoveEvent( QMouseEvent *mouseEvent )
01006 {
01007     if ( pickArea().contains( mouseEvent->pos() ) )
01008         d_data->trackerPosition = mouseEvent->pos();
01009     else
01010         d_data->trackerPosition = QPoint( -1, -1 );
01011 
01012     if ( !isActive() )
01013         updateDisplay();
01014 
01015     transition( mouseEvent );
01016 }
01017 
01027 void QwtPicker::widgetEnterEvent( QEvent *event )
01028 {
01029     transition( event );
01030 }
01031 
01041 void QwtPicker::widgetLeaveEvent( QEvent *event )
01042 {
01043     transition( event );
01044 
01045     d_data->trackerPosition = QPoint( -1, -1 );
01046     if ( !isActive() )
01047         updateDisplay();
01048 }
01049 
01059 void QwtPicker::widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
01060 {
01061     transition( mouseEvent );
01062 }
01063 
01073 void QwtPicker::widgetMouseDoubleClickEvent( QMouseEvent *mouseEvent )
01074 {
01075     transition( mouseEvent );
01076 }
01077 
01078 
01090 void QwtPicker::widgetWheelEvent( QWheelEvent *wheelEvent )
01091 {
01092     if ( pickArea().contains( wheelEvent->pos() ) )
01093         d_data->trackerPosition = wheelEvent->pos();
01094     else
01095         d_data->trackerPosition = QPoint( -1, -1 );
01096 
01097     updateDisplay();
01098 
01099     transition( wheelEvent );
01100 }
01101 
01116 void QwtPicker::widgetKeyPressEvent( QKeyEvent *keyEvent )
01117 {
01118     int dx = 0;
01119     int dy = 0;
01120 
01121     int offset = 1;
01122     if ( keyEvent->isAutoRepeat() )
01123         offset = 5;
01124 
01125     if ( keyMatch( KeyLeft, keyEvent ) )
01126         dx = -offset;
01127     else if ( keyMatch( KeyRight, keyEvent ) )
01128         dx = offset;
01129     else if ( keyMatch( KeyUp, keyEvent ) )
01130         dy = -offset;
01131     else if ( keyMatch( KeyDown, keyEvent ) )
01132         dy = offset;
01133     else if ( keyMatch( KeyAbort, keyEvent ) )
01134     {
01135         reset();
01136     }
01137     else
01138         transition( keyEvent );
01139 
01140     if ( dx != 0 || dy != 0 )
01141     {
01142         const QRect rect = pickArea().boundingRect().toRect();
01143         const QPoint pos = parentWidget()->mapFromGlobal( QCursor::pos() );
01144 
01145         int x = pos.x() + dx;
01146         x = qMax( rect.left(), x );
01147         x = qMin( rect.right(), x );
01148 
01149         int y = pos.y() + dy;
01150         y = qMax( rect.top(), y );
01151         y = qMin( rect.bottom(), y );
01152 
01153         QCursor::setPos( parentWidget()->mapToGlobal( QPoint( x, y ) ) );
01154     }
01155 }
01156 
01168 void QwtPicker::widgetKeyReleaseEvent( QKeyEvent *keyEvent )
01169 {
01170     transition( keyEvent );
01171 }
01172 
01180 void QwtPicker::transition( const QEvent *event )
01181 {
01182     if ( !d_data->stateMachine )
01183         return;
01184 
01185     const QList<QwtPickerMachine::Command> commandList =
01186         d_data->stateMachine->transition( *this, event );
01187 
01188     QPoint pos;
01189     switch ( event->type() )
01190     {
01191         case QEvent::MouseButtonDblClick:
01192         case QEvent::MouseButtonPress:
01193         case QEvent::MouseButtonRelease:
01194         case QEvent::MouseMove:
01195         {
01196             const QMouseEvent *me = 
01197                 static_cast< const QMouseEvent * >( event );
01198             pos = me->pos();
01199             break;
01200         }
01201         default:
01202             pos = parentWidget()->mapFromGlobal( QCursor::pos() );
01203     }
01204 
01205     for ( int i = 0; i < commandList.count(); i++ )
01206     {
01207         switch ( commandList[i] )
01208         {
01209             case QwtPickerMachine::Begin:
01210             {
01211                 begin();
01212                 break;
01213             }
01214             case QwtPickerMachine::Append:
01215             {
01216                 append( pos );
01217                 break;
01218             }
01219             case QwtPickerMachine::Move:
01220             {
01221                 move( pos );
01222                 break;
01223             }
01224             case QwtPickerMachine::Remove:
01225             {
01226                 remove();
01227                 break;
01228             }
01229             case QwtPickerMachine::End:
01230             {
01231                 end();
01232                 break;
01233             }
01234         }
01235     }
01236 }
01237 
01243 void QwtPicker::begin()
01244 {
01245     if ( d_data->isActive )
01246         return;
01247 
01248     d_data->pickedPoints.resize( 0 );
01249     d_data->isActive = true;
01250     Q_EMIT activated( true );
01251 
01252     if ( trackerMode() != AlwaysOff )
01253     {
01254         if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 )
01255         {
01256             QWidget *w = parentWidget();
01257             if ( w )
01258                 d_data->trackerPosition = w->mapFromGlobal( QCursor::pos() );
01259         }
01260     }
01261 
01262     updateDisplay();
01263     setMouseTracking( true );
01264 }
01265 
01276 bool QwtPicker::end( bool ok )
01277 {
01278     if ( d_data->isActive )
01279     {
01280         setMouseTracking( false );
01281 
01282         d_data->isActive = false;
01283         Q_EMIT activated( false );
01284 
01285         if ( trackerMode() == ActiveOnly )
01286             d_data->trackerPosition = QPoint( -1, -1 );
01287 
01288         if ( ok )
01289             ok = accept( d_data->pickedPoints );
01290 
01291         if ( ok )
01292             Q_EMIT selected( d_data->pickedPoints );
01293         else
01294             d_data->pickedPoints.resize( 0 );
01295 
01296         updateDisplay();
01297     }
01298     else
01299         ok = false;
01300 
01301     return ok;
01302 }
01303 
01307 void QwtPicker::reset()
01308 {
01309     if ( d_data->stateMachine )
01310         d_data->stateMachine->reset();
01311 
01312     if ( isActive() )
01313         end( false );
01314 }
01315 
01324 void QwtPicker::append( const QPoint &pos )
01325 {
01326     if ( d_data->isActive )
01327     {
01328         const int idx = d_data->pickedPoints.count();
01329         d_data->pickedPoints.resize( idx + 1 );
01330         d_data->pickedPoints[idx] = pos;
01331 
01332         updateDisplay();
01333         Q_EMIT appended( pos );
01334     }
01335 }
01336 
01344 void QwtPicker::move( const QPoint &pos )
01345 {
01346     if ( d_data->isActive )
01347     {
01348         const int idx = d_data->pickedPoints.count() - 1;
01349         if ( idx >= 0 )
01350         {
01351             if ( d_data->pickedPoints[idx] != pos )
01352             {
01353                 d_data->pickedPoints[idx] = pos;
01354 
01355                 updateDisplay();
01356                 Q_EMIT moved( pos );
01357             }
01358         }
01359     }
01360 }
01361 
01368 void QwtPicker::remove()
01369 {
01370     if ( d_data->isActive )
01371     {
01372         const int idx = d_data->pickedPoints.count() - 1;
01373         if ( idx > 0 )
01374         {
01375             const int idx = d_data->pickedPoints.count();
01376 
01377             const QPoint pos = d_data->pickedPoints[idx - 1];
01378             d_data->pickedPoints.resize( idx - 1 );
01379 
01380             updateDisplay();
01381             Q_EMIT removed( pos );
01382         }
01383     }
01384 }
01385 
01394 bool QwtPicker::accept( QPolygon &selection ) const
01395 {
01396     Q_UNUSED( selection );
01397     return true;
01398 }
01399 
01404 bool QwtPicker::isActive() const
01405 {
01406     return d_data->isActive;
01407 }
01408 
01414 const QPolygon &QwtPicker::pickedPoints() const
01415 {
01416     return d_data->pickedPoints;
01417 }
01418 
01428 void QwtPicker::stretchSelection( const QSize &oldSize, const QSize &newSize )
01429 {
01430     if ( oldSize.isEmpty() )
01431     {
01432         // avoid division by zero. But scaling for small sizes also
01433         // doesn't make much sense, because of rounding losses. TODO ...
01434         return;
01435     }
01436 
01437     const double xRatio =
01438         double( newSize.width() ) / double( oldSize.width() );
01439     const double yRatio =
01440         double( newSize.height() ) / double( oldSize.height() );
01441 
01442     for ( int i = 0; i < int( d_data->pickedPoints.count() ); i++ )
01443     {
01444         QPoint &p = d_data->pickedPoints[i];
01445         p.setX( qRound( p.x() * xRatio ) );
01446         p.setY( qRound( p.y() * yRatio ) );
01447 
01448         Q_EMIT changed( d_data->pickedPoints );
01449     }
01450 }
01451 
01465 void QwtPicker::setMouseTracking( bool enable )
01466 {
01467     QWidget *widget = parentWidget();
01468     if ( !widget )
01469         return;
01470 
01471     if ( enable )
01472     {
01473         d_data->mouseTracking = widget->hasMouseTracking();
01474         widget->setMouseTracking( true );
01475     }
01476     else
01477     {
01478         widget->setMouseTracking( d_data->mouseTracking );
01479     }
01480 }
01481 
01487 QPainterPath QwtPicker::pickArea() const
01488 {
01489     QPainterPath path;
01490 
01491     const QWidget *widget = parentWidget();
01492     if ( widget )
01493         path.addRect( widget->contentsRect() );
01494 
01495     return path;
01496 }
01497 
01499 void QwtPicker::updateDisplay()
01500 {
01501     QWidget *w = parentWidget();
01502 
01503     bool showRubberband = false;
01504     bool showTracker = false;
01505 
01506     if ( w && w->isVisible() && d_data->enabled )
01507     {
01508         if ( rubberBand() != NoRubberBand && isActive() &&
01509             rubberBandPen().style() != Qt::NoPen )
01510         {
01511             showRubberband = true;
01512         }
01513 
01514         if ( trackerMode() == AlwaysOn ||
01515             ( trackerMode() == ActiveOnly && isActive() ) )
01516         {
01517             if ( trackerPen() != Qt::NoPen 
01518                 && !trackerRect( QFont() ).isEmpty() )
01519             {
01520                 showTracker = true;
01521             }
01522         }
01523     }
01524 
01525     QPointer< QwtPickerRubberband > &rw = d_data->rubberBandOverlay;
01526     if ( showRubberband )
01527     {
01528         if ( rw.isNull() )
01529         {
01530             rw = new QwtPickerRubberband( this, NULL ); // NULL -> no extra event filter
01531             rw->setObjectName( "PickerRubberBand" );
01532             rw->setParent( w );
01533             rw->resize( w->size() );
01534         }
01535 
01536         if ( d_data->rubberBand <= RectRubberBand )
01537             rw->setMaskMode( QwtWidgetOverlay::MaskHint );
01538         else
01539             rw->setMaskMode( QwtWidgetOverlay::AlphaMask );
01540 
01541         rw->updateOverlay();
01542     }
01543     else
01544     {
01545         if ( d_data->openGL )
01546         {
01547             // Qt 4.8 crashes for a delete
01548             if ( !rw.isNull() )
01549             {
01550                 rw->hide();
01551                 rw->deleteLater();
01552                 rw = NULL;
01553             }
01554         }
01555         else
01556         {
01557             delete rw;
01558         }
01559     }
01560 
01561     QPointer< QwtPickerTracker > &tw = d_data->trackerOverlay;
01562     if ( showTracker )
01563     {
01564         if ( tw.isNull() )
01565         {
01566             tw = new QwtPickerTracker( this, NULL ); // NULL -> no extra event filter
01567             tw->setObjectName( "PickerTracker" );
01568             tw->setParent( w );
01569             tw->resize( w->size() );
01570         }
01571         tw->setFont( d_data->trackerFont );
01572         tw->updateOverlay();
01573     }
01574     else
01575     {
01576         if ( d_data->openGL )
01577         {
01578             // Qt 4.8 crashes for a delete
01579             if ( !tw.isNull() )
01580             {
01581                 tw->hide();
01582                 tw->deleteLater();
01583                 tw = NULL;
01584             }
01585         }
01586         else
01587         {
01588             delete tw;
01589         }
01590     }
01591 }
01592 
01594 const QwtWidgetOverlay *QwtPicker::rubberBandOverlay() const
01595 {
01596     return d_data->rubberBandOverlay;
01597 }
01598 
01600 const QwtWidgetOverlay *QwtPicker::trackerOverlay() const
01601 {
01602     return d_data->trackerOverlay;
01603 }
01604 


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