10#include "qwt_picker.h" 
   11#include "qwt_picker_machine.h" 
   12#include "qwt_painter.h" 
   14#include "qwt_widget_overlay.h" 
   19#include <qpainterpath.h> 
   24static inline QRegion qwtMaskRegion( 
const QRect& r, 
int penWidth )
 
   26    const int pw = qMax( penWidth, 1 );
 
   27    const int pw2 = penWidth / 2;
 
   29    int x1 = r.left() - pw2;
 
   30    int x2 = r.right() + 1 + pw2 + ( pw % 2 );
 
   32    int y1 = r.top() - pw2;
 
   33    int y2 = r.bottom() + 1 + pw2 + ( pw % 2 );
 
   37    region += QRect( x1, y1, x2 - x1, pw );
 
   38    region += QRect( x1, y1, pw, y2 - y1 );
 
   39    region += QRect( x1, y2 - pw, x2 - x1, pw );
 
   40    region += QRect( x2 - pw, y1, pw, y2 - y1 );
 
   45static inline QRegion qwtMaskRegion( 
const QLine& l, 
int penWidth )
 
   47    const int pw = qMax( penWidth, 1 );
 
   48    const int pw2 = penWidth / 2;
 
   52    if ( l.x1() == l.x2() )
 
   54        region += QRect( l.x1() - pw2, l.y1(),
 
   55            pw, l.y2() ).normalized();
 
   57    else if ( l.y1() == l.y2() )
 
   59        region += QRect( l.x1(), l.y1() - pw2,
 
   60            l.x2(), pw ).normalized();
 
   71        Rubberband( 
QwtPicker* picker, QWidget* parent )
 
   79        virtual void drawOverlay( QPainter* painter ) 
const QWT_OVERRIDE
 
   81            painter->setPen( m_picker->rubberBandPen() );
 
   82            m_picker->drawRubberBand( painter );
 
   85        virtual QRegion maskHint() const QWT_OVERRIDE
 
   87            return m_picker->rubberBandMask();
 
   96        Tracker( 
QwtPicker* picker, QWidget* parent )
 
  104        virtual void drawOverlay( QPainter* painter ) 
const QWT_OVERRIDE
 
  106            painter->setPen( m_picker->trackerPen() );
 
  107            m_picker->drawTracker( painter );
 
  110        virtual QRegion maskHint() const QWT_OVERRIDE
 
  112            return m_picker->trackerMask();
 
  119class QwtPicker::PrivateData
 
  124        stateMachine( NULL ),
 
  129        trackerPosition( -1, -1 ),
 
  130        mouseTracking( false ),
 
  148    QPolygon pickedPoints;
 
  150    QPoint trackerPosition;
 
  154    QPointer< Rubberband > rubberBandOverlay;
 
  155    QPointer< Tracker > trackerOverlay;
 
  192    setMouseTracking( 
false );
 
  194    delete m_data->stateMachine;
 
  195    delete m_data->rubberBandOverlay;
 
  196    delete m_data->trackerOverlay;
 
 
  202void QwtPicker::init( QWidget* parent,
 
  203    RubberBand rubberBand, DisplayMode trackerMode )
 
  205    m_data = 
new PrivateData;
 
  211        if ( parent->focusPolicy() == Qt::NoFocus )
 
  212            parent->setFocusPolicy( Qt::WheelFocus );
 
  214        m_data->openGL = parent->inherits( 
"QGLWidget" );
 
  215        m_data->trackerFont = parent->font();
 
  216        m_data->mouseTracking = parent->hasMouseTracking();
 
  236        delete m_data->stateMachine;
 
  239        if ( m_data->stateMachine )
 
  240            m_data->stateMachine->
reset();
 
 
  250    return m_data->stateMachine;
 
 
  259    return m_data->stateMachine;
 
 
  265    QObject* obj = parent();
 
  266    if ( obj && obj->isWidgetType() )
 
  267        return static_cast< QWidget* 
>( obj );
 
 
  275    QObject* obj = parent();
 
  276    if ( obj && obj->isWidgetType() )
 
  277        return static_cast< const QWidget* 
>( obj );
 
 
  301    return m_data->rubberBand;
 
 
  322    if ( m_data->trackerMode != mode )
 
  324        m_data->trackerMode = mode;
 
  325        setMouseTracking( m_data->trackerMode == 
AlwaysOn );
 
 
  335    return m_data->trackerMode;
 
 
  354    m_data->resizeMode = mode;
 
 
  364    return m_data->resizeMode;
 
 
  378    if ( m_data->enabled != enabled )
 
  380        m_data->enabled = enabled;
 
  386                w->installEventFilter( 
this );
 
  388                w->removeEventFilter( 
this );
 
 
  402    return m_data->enabled;
 
 
  413    if ( font != m_data->trackerFont )
 
  415        m_data->trackerFont = font;
 
 
  427    return m_data->trackerFont;
 
 
  438    if ( pen != m_data->trackerPen )
 
  440        m_data->trackerPen = pen;
 
 
  451    return m_data->trackerPen;
 
 
  462    if ( pen != m_data->rubberBandPen )
 
  464        m_data->rubberBandPen = pen;
 
 
  475    return m_data->rubberBandPen;
 
 
  498            label = QString::number( pos.y() );
 
  501            label = QString::number( pos.x() );
 
  504            label = QString::number( pos.x() ) + 
", " + QString::number( pos.y() );
 
 
  541    if ( m_data->stateMachine )
 
  547    switch ( selectionType )
 
  552            if ( pa.count() < 1 )
 
  555            const QPoint pos = pa[0];
 
  557            const QRect pRect = 
pickArea().boundingRect().toRect();
 
  562                    mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
 
  563                        pos.x(), pRect.bottom() ), pw );
 
  568                    mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
 
  569                        pRect.right(), pos.y() ), pw );
 
  574                    mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
 
  575                        pos.x(), pRect.bottom() ), pw );
 
  576                    mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
 
  577                        pRect.right(), pos.y() ), pw );
 
  587            if ( pa.count() < 2 )
 
  594                    const QRect r = QRect( pa.first(), pa.last() );
 
  595                    mask = qwtMaskRegion( r.normalized(), pw );
 
  600                    const QRect r = QRect( pa.first(), pa.last() );
 
  601                    mask += r.adjusted( -pw, -pw, pw, pw );
 
  616                const int off = 2 * pw;
 
  617                const QRect r = pa.boundingRect();
 
  618                mask += r.adjusted( -off, -off, off, off );
 
 
  650    if ( m_data->stateMachine )
 
  653    switch ( selectionType )
 
  658            if ( pa.count() < 1 )
 
  661            const QPoint pos = pa[0];
 
  663            const QRect pRect = 
pickArea().boundingRect().toRect();
 
  669                        pRect.top(), pos.x(), pRect.bottom() );
 
  675                        pos.y(), pRect.right(), pos.y() );
 
  681                        pRect.top(), pos.x(), pRect.bottom() );
 
  683                        pos.y(), pRect.right(), pos.y() );
 
  693            if ( pa.count() < 2 )
 
  696            const QRect rect = QRect( pa.first(), pa.last() ).normalized();
 
  717                painter->drawPolyline( pa );
 
 
  734    const QRect textRect = 
trackerRect( painter->font() );
 
  735    if ( !textRect.isEmpty() )
 
  739            label.
draw( painter, textRect );
 
 
  800    return m_data->trackerPosition;
 
 
  820    if ( m_data->trackerPosition.x() < 0 || m_data->trackerPosition.y() < 0 )
 
  827    const QSizeF textSize = text.
textSize( font );
 
  829    const int w = qwtCeil( textSize.width() );
 
  830    const int h = qwtCeil( textSize.height() );
 
 
  846    const QPoint& pos = m_data->trackerPosition;
 
  847    QRect infoRect( 0, 0, size.width(), size.height() );
 
  850    if ( 
isActive() && m_data->pickedPoints.count() > 1
 
  854            m_data->pickedPoints[ m_data->pickedPoints.count() - 2 ];
 
  856        alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft;
 
  857        alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop;
 
  861        alignment = Qt::AlignTop | Qt::AlignRight;
 
  864    const int margin = 5;
 
  867    if ( alignment & Qt::AlignLeft )
 
  868        x -= infoRect.width() + margin;
 
  869    else if ( alignment & Qt::AlignRight )
 
  873    if ( alignment & Qt::AlignBottom )
 
  875    else if ( alignment & Qt::AlignTop )
 
  876        y -= infoRect.height() + margin;
 
  878    infoRect.moveTopLeft( QPoint( x, y ) );
 
  880    const QRect pickRect = 
pickArea().boundingRect().toRect();
 
  882    int right = qMin( infoRect.right(), pickRect.right() - margin );
 
  883    int bottom = qMin( infoRect.bottom(), pickRect.bottom() - margin );
 
  884    infoRect.moveBottomRight( QPoint( right, bottom ) );
 
  886    int left = qMax( infoRect.left(), pickRect.left() + margin );
 
  887    int top = qMax( infoRect.top(), pickRect.top() + margin );
 
  888    infoRect.moveTopLeft( QPoint( left, top ) );
 
 
  916        switch ( event->type() )
 
  920                const QResizeEvent* re = 
static_cast< QResizeEvent* 
>( event );
 
  928                if ( m_data->trackerOverlay )
 
  929                    m_data->trackerOverlay->resize( re->size() );
 
  931                if ( m_data->rubberBandOverlay )
 
  932                    m_data->rubberBandOverlay->resize( re->size() );
 
  934                if ( m_data->resizeMode == 
Stretch )
 
  950            case QEvent::MouseButtonPress:
 
  955            case QEvent::MouseButtonRelease:
 
  960            case QEvent::MouseButtonDblClick:
 
  965            case QEvent::MouseMove:
 
  970            case QEvent::KeyPress:
 
  975            case QEvent::KeyRelease:
 
 
 1017    if ( 
pickArea().contains( mouseEvent->pos() ) )
 
 1018        m_data->trackerPosition = mouseEvent->pos();
 
 1020        m_data->trackerPosition = QPoint( -1, -1 );
 
 
 1055    m_data->trackerPosition = QPoint( -1, -1 );
 
 
 1102#if QT_VERSION < 0x050e00 
 1103    const QPoint wheelPos = wheelEvent->pos();
 
 1105    const QPoint wheelPos = wheelEvent->position().toPoint();
 
 1107    if ( 
pickArea().contains( wheelPos ) )
 
 1108        m_data->trackerPosition = wheelPos;
 
 1110        m_data->trackerPosition = QPoint( -1, -1 );
 
 
 1137    if ( keyEvent->isAutoRepeat() )
 
 1155    if ( dx != 0 || dy != 0 )
 
 1157        const QRect rect = 
pickArea().boundingRect().toRect();
 
 1158        const QPoint pos = 
parentWidget()->mapFromGlobal( QCursor::pos() );
 
 1160        int x = pos.x() + dx;
 
 1161        x = qMax( rect.left(), x );
 
 1162        x = qMin( rect.right(), x );
 
 1164        int y = pos.y() + dy;
 
 1165        y = qMax( rect.top(), y );
 
 1166        y = qMin( rect.bottom(), y );
 
 1168        QCursor::setPos( 
parentWidget()->mapToGlobal( QPoint( x, y ) ) );
 
 
 1197    if ( !m_data->stateMachine )
 
 1201        m_data->stateMachine->
transition( *
this, event );
 
 1204    switch ( event->type() )
 
 1206        case QEvent::MouseButtonDblClick:
 
 1207        case QEvent::MouseButtonPress:
 
 1208        case QEvent::MouseButtonRelease:
 
 1209        case QEvent::MouseMove:
 
 1211            const QMouseEvent* me =
 
 1212                static_cast< const QMouseEvent* 
>( event );
 
 1220    for ( 
int i = 0; i < commandList.count(); i++ )
 
 1222        switch ( commandList[i] )
 
 1224            case QwtPickerMachine::Begin:
 
 1229            case QwtPickerMachine::Append:
 
 1234            case QwtPickerMachine::Move:
 
 1239            case QwtPickerMachine::Remove:
 
 1244            case QwtPickerMachine::End:
 
 
 1260    if ( m_data->isActive )
 
 1263    m_data->pickedPoints.clear();
 
 1264    m_data->isActive = 
true;
 
 1269        if ( m_data->trackerPosition.x() < 0 || m_data->trackerPosition.y() < 0 )
 
 1273                m_data->trackerPosition = w->mapFromGlobal( QCursor::pos() );
 
 1278    setMouseTracking( 
true );
 
 
 1293    if ( m_data->isActive )
 
 1295        setMouseTracking( 
false );
 
 1297        m_data->isActive = 
false;
 
 1301            m_data->trackerPosition = QPoint( -1, -1 );
 
 1304            ok = 
accept( m_data->pickedPoints );
 
 1307            Q_EMIT 
selected( m_data->pickedPoints );
 
 1309            m_data->pickedPoints.clear();
 
 
 1324    if ( m_data->stateMachine )
 
 1325        m_data->stateMachine->
reset();
 
 
 1341    if ( m_data->isActive )
 
 1343        m_data->pickedPoints += pos;
 
 
 1359    if ( m_data->isActive && !m_data->pickedPoints.isEmpty() )
 
 1361        QPoint& point = m_data->pickedPoints.last();
 
 1367            Q_EMIT 
moved( pos );
 
 
 1380    if ( m_data->isActive && !m_data->pickedPoints.isEmpty() )
 
 1382#if QT_VERSION >= 0x050100 
 1383        const QPoint pos = m_data->pickedPoints.takeLast();
 
 1385        const QPoint pos = m_data->pickedPoints.last();
 
 1386        m_data->pickedPoints.resize( m_data->pickedPoints.count() - 1 );
 
 
 1414    return m_data->isActive;
 
 
 1424    return m_data->pickedPoints;
 
 
 1438    if ( oldSize.isEmpty() )
 
 1445    const double xRatio = double( newSize.width() ) / double( oldSize.width() );
 
 1446    const double yRatio = double( newSize.height() ) / double( oldSize.height() );
 
 1448    for ( 
int i = 0; i < m_data->pickedPoints.count(); i++ )
 
 1450        QPoint& p = m_data->pickedPoints[i];
 
 1451        p.setX( qRound( p.x() * xRatio ) );
 
 1452        p.setY( qRound( p.y() * yRatio ) );
 
 1454        Q_EMIT 
changed( m_data->pickedPoints );
 
 
 1471void QwtPicker::setMouseTracking( 
bool enable )
 
 1479        m_data->mouseTracking = widget->hasMouseTracking();
 
 1480        widget->setMouseTracking( 
true );
 
 1484        widget->setMouseTracking( m_data->mouseTracking );
 
 1499        path.addRect( widget->contentsRect() );
 
 
 1509    bool showRubberband = 
false;
 
 1510    bool showTracker = 
false;
 
 1512    if ( w && w->isVisible() && m_data->enabled )
 
 1517            showRubberband = 
true;
 
 1531    QPointer< Rubberband >& rw = m_data->rubberBandOverlay;
 
 1532    if ( showRubberband )
 
 1536            rw = 
new Rubberband( 
this, NULL ); 
 
 1537            rw->setObjectName( 
"PickerRubberBand" );
 
 1539            rw->resize( w->size() );
 
 1547        rw->updateOverlay();
 
 1551        if ( m_data->openGL )
 
 1567    QPointer< Tracker >& tw = m_data->trackerOverlay;
 
 1572            tw = 
new Tracker( 
this, NULL ); 
 
 1573            tw->setObjectName( 
"PickerTracker" );
 
 1575            tw->resize( w->size() );
 
 1577        tw->setFont( m_data->trackerFont );
 
 1578        tw->updateOverlay();
 
 1582        if ( m_data->openGL )
 
 
 1602    return m_data->rubberBandOverlay;
 
 
 1608    return m_data->trackerOverlay;
 
 
 1611#include "moc_qwt_picker.cpp" 
bool keyMatch(KeyPatternCode, const QKeyEvent *) const
Compare a key event with an event pattern.
@ KeyAbort
Qt::Key_Escape.
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
static qreal devicePixelRatio(const QPaintDevice *)
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
QwtPicker provides selections on a widget.
@ AlwaysOn
Display always.
@ AlwaysOff
Display never.
@ ActiveOnly
Display only when the selection is active.
virtual void updateDisplay()
Update the state of rubber band and tracker label.
QFont trackerFont() const
ResizeMode resizeMode() const
virtual void drawRubberBand(QPainter *) const
RubberBand rubberBand() const
void setRubberBandPen(const QPen &)
virtual QRegion trackerMask() const
virtual void stretchSelection(const QSize &oldSize, const QSize &newSize)
virtual bool eventFilter(QObject *, QEvent *) override
Event filter.
void selected(const QPolygon &polygon)
QPen rubberBandPen() const
const QwtWidgetOverlay * rubberBandOverlay() const
virtual void widgetMousePressEvent(QMouseEvent *)
virtual void move(const QPoint &)
virtual ~QwtPicker()
Destructor.
virtual void append(const QPoint &)
void setStateMachine(QwtPickerMachine *)
virtual void drawTracker(QPainter *) const
virtual QRegion rubberBandMask() const
QPoint trackerPosition() const
virtual void widgetEnterEvent(QEvent *)
void setRubberBand(RubberBand)
const QwtWidgetOverlay * trackerOverlay() const
virtual void widgetMouseMoveEvent(QMouseEvent *)
virtual void widgetLeaveEvent(QEvent *)
virtual void transition(const QEvent *)
virtual bool accept(QPolygon &) const
Validate and fix up the selection.
void setTrackerMode(DisplayMode)
Set the display mode of the tracker.
virtual QPainterPath pickArea() const
virtual void widgetKeyReleaseEvent(QKeyEvent *)
void setTrackerFont(const QFont &)
void setEnabled(bool)
En/disable the picker.
DisplayMode trackerMode() const
virtual QPolygon adjustedPoints(const QPolygon &) const
Map the pickedPoints() into a selection()
@ VLineRubberBand
A vertical line ( only for QwtPickerMachine::PointSelection )
@ CrossRubberBand
A crosshair ( only for QwtPickerMachine::PointSelection )
@ EllipseRubberBand
An ellipse ( only for QwtPickerMachine::RectSelection )
@ PolygonRubberBand
A polygon ( only for QwtPickerMachine::PolygonSelection )
@ HLineRubberBand
A horizontal line ( only for QwtPickerMachine::PointSelection )
@ NoRubberBand
No rubberband.
@ RectRubberBand
A rectangle ( only for QwtPickerMachine::RectSelection )
@ Stretch
All points are scaled according to the new size,.
virtual QwtText trackerText(const QPoint &pos) const
Return the label for a position.
virtual void widgetMouseReleaseEvent(QMouseEvent *)
virtual bool end(bool ok=true)
Close a selection setting the state to inactive.
void appended(const QPoint &pos)
QWidget * parentWidget()
Return the parent widget, where the selection happens.
void moved(const QPoint &pos)
const QPolygon & pickedPoints() const
const QwtPickerMachine * stateMachine() const
void removed(const QPoint &pos)
void changed(const QPolygon &selection)
virtual QRect trackerRect(const QFont &) const
virtual void widgetMouseDoubleClickEvent(QMouseEvent *)
virtual void widgetKeyPressEvent(QKeyEvent *)
void setTrackerPen(const QPen &)
void setResizeMode(ResizeMode)
Set the resize mode.
virtual void widgetWheelEvent(QWheelEvent *)
QwtPicker(QWidget *parent)
QPolygon selection() const
A state machine for QwtPicker selections.
@ NoSelection
The state machine not usable for any type of selection.
@ RectSelection
The state machine is for selecting a rectangle (2 points).
@ PolygonSelection
The state machine is for selecting a polygon (many points).
@ PointSelection
The state machine is for selecting a single point.
SelectionType selectionType() const
Return the selection type.
virtual QList< Command > transition(const QwtEventPattern &, const QEvent *)=0
Transition.
void reset()
Set the current state to 0.
A class representing a text.
void draw(QPainter *painter, const QRectF &rect) const