Skip to content
qwt_plot_picker.cpp 8.92 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

Bryant's avatar
Bryant committed
#include "qwt_plot_picker.h"
pixhawk's avatar
pixhawk committed
#include "qwt_plot.h"
#include "qwt_scale_div.h"
#include "qwt_painter.h"
#include "qwt_scale_map.h"
Bryant's avatar
Bryant committed
#include "qwt_picker_machine.h"
pixhawk's avatar
pixhawk committed

/*!
  \brief Create a plot picker

  The picker is set to those x- and y-axis of the plot
  that are enabled. If both or no x-axis are enabled, the picker
  is set to QwtPlot::xBottom. If both or no y-axis are
  enabled, it is set to QwtPlot::yLeft.

  \param canvas Plot canvas to observe, also the parent object

Bryant's avatar
Bryant committed
  \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QwtPlotPicker::QwtPlotPicker( QWidget *canvas ):
    QwtPicker( canvas ),
    d_xAxis( -1 ),
    d_yAxis( -1 )
pixhawk's avatar
pixhawk committed
{
    if ( !canvas )
        return;

    // attach axes

    int xAxis = QwtPlot::xBottom;

    const QwtPlot *plot = QwtPlotPicker::plot();
Bryant's avatar
Bryant committed
    if ( !plot->axisEnabled( QwtPlot::xBottom ) &&
        plot->axisEnabled( QwtPlot::xTop ) )
    {
pixhawk's avatar
pixhawk committed
        xAxis = QwtPlot::xTop;
    }

    int yAxis = QwtPlot::yLeft;
Bryant's avatar
Bryant committed
    if ( !plot->axisEnabled( QwtPlot::yLeft ) &&
        plot->axisEnabled( QwtPlot::yRight ) )
    {
pixhawk's avatar
pixhawk committed
        yAxis = QwtPlot::yRight;
    }

Bryant's avatar
Bryant committed
    setAxis( xAxis, yAxis );
pixhawk's avatar
pixhawk committed
}

/*!
  Create a plot picker

  \param xAxis Set the x axis of the picker
  \param yAxis Set the y axis of the picker
  \param canvas Plot canvas to observe, also the parent object

Bryant's avatar
Bryant committed
  \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QwtPlotPicker::QwtPlotPicker( int xAxis, int yAxis, QWidget *canvas ):
    QwtPicker( canvas ),
    d_xAxis( xAxis ),
    d_yAxis( yAxis )
pixhawk's avatar
pixhawk committed
{
}

/*!
  Create a plot picker

  \param xAxis X axis of the picker
  \param yAxis Y axis of the picker
Bryant's avatar
Bryant committed
  \param rubberBand Rubber band style
pixhawk's avatar
pixhawk committed
  \param trackerMode Tracker mode
  \param canvas Plot canvas to observe, also the parent object

  \sa QwtPicker, QwtPicker::setSelectionFlags(), QwtPicker::setRubberBand(),
      QwtPicker::setTrackerMode

Bryant's avatar
Bryant committed
  \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QwtPlotPicker::QwtPlotPicker( int xAxis, int yAxis,
        RubberBand rubberBand, DisplayMode trackerMode,
        QWidget *canvas ):
    QwtPicker( rubberBand, trackerMode, canvas ),
    d_xAxis( xAxis ),
    d_yAxis( yAxis )
pixhawk's avatar
pixhawk committed
{
}

Bryant's avatar
Bryant committed
//! Destructor
QwtPlotPicker::~QwtPlotPicker()
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
}
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
//! \return Observed plot canvas
QWidget *QwtPlotPicker::canvas()
{
    return parentWidget();
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
//! \return Observed plot canvas
const QWidget *QwtPlotPicker::canvas() const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    return parentWidget();
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
//! \return Plot widget, containing the observed plot canvas
pixhawk's avatar
pixhawk committed
QwtPlot *QwtPlotPicker::plot()
{
Bryant's avatar
Bryant committed
    QWidget *w = canvas();
    if ( w )
        w = w->parentWidget();
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    return qobject_cast<QwtPlot *>( w );
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
//! \return Plot widget, containing the observed plot canvas
pixhawk's avatar
pixhawk committed
const QwtPlot *QwtPlotPicker::plot() const
{
Bryant's avatar
Bryant committed
    const QWidget *w = canvas();
    if ( w )
        w = w->parentWidget();

    return qobject_cast<const QwtPlot *>( w );
pixhawk's avatar
pixhawk committed
}

/*!
Bryant's avatar
Bryant committed
  \return Normalized bounding rectangle of the axes
pixhawk's avatar
pixhawk committed
  \sa QwtPlot::autoReplot(), QwtPlot::replot().
*/
Bryant's avatar
Bryant committed
QRectF QwtPlotPicker::scaleRect() const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QRectF rect;
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    if ( plot() )
    {
        const QwtScaleDiv &xs = plot()->axisScaleDiv( xAxis() );
        const QwtScaleDiv &ys = plot()->axisScaleDiv( yAxis() );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
        rect = QRectF( xs.lowerBound(), ys.lowerBound(),
            xs.range(), ys.range() );
        rect = rect.normalized();
pixhawk's avatar
pixhawk committed
    }

    return rect;
}

/*!
  Set the x and y axes of the picker

  \param xAxis X axis
  \param yAxis Y axis
*/
Bryant's avatar
Bryant committed
void QwtPlotPicker::setAxis( int xAxis, int yAxis )
pixhawk's avatar
pixhawk committed
{
    const QwtPlot *plt = plot();
    if ( !plt )
        return;

Bryant's avatar
Bryant committed
    if ( xAxis != d_xAxis || yAxis != d_yAxis )
    {
pixhawk's avatar
pixhawk committed
        d_xAxis = xAxis;
        d_yAxis = yAxis;
    }
}

//! Return x axis
int QwtPlotPicker::xAxis() const
{
    return d_xAxis;
}

//! Return y axis
int QwtPlotPicker::yAxis() const
{
    return d_yAxis;
}

/*!
  Translate a pixel position into a position string

  \param pos Position in pixel coordinates
  \return Position string
*/
Bryant's avatar
Bryant committed
QwtText QwtPlotPicker::trackerText( const QPoint &pos ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    return trackerTextF( invTransform( pos ) );
pixhawk's avatar
pixhawk committed
}

/*!
  \brief Translate a position into a position string

  In case of HLineRubberBand the label is the value of the
  y position, in case of VLineRubberBand the value of the x position.
  Otherwise the label contains x and y position separated by a ',' .

  The format for the double to string conversion is "%.4f".

  \param pos Position
  \return Position string
*/
Bryant's avatar
Bryant committed
QwtText QwtPlotPicker::trackerTextF( const QPointF &pos ) const
pixhawk's avatar
pixhawk committed
{
    QString text;

Bryant's avatar
Bryant committed
    switch ( rubberBand() )
    {
        case HLineRubberBand:
            text.sprintf( "%.4f", pos.y() );
            break;
        case VLineRubberBand:
            text.sprintf( "%.4f", pos.x() );
            break;
        default:
            text.sprintf( "%.4f, %.4f", pos.x(), pos.y() );
pixhawk's avatar
pixhawk committed
    }
Bryant's avatar
Bryant committed
    return QwtText( text );
pixhawk's avatar
pixhawk committed
}

Bryant's avatar
Bryant committed
  Append a point to the selection and update rubber band and tracker.
pixhawk's avatar
pixhawk committed
  \param pos Additional point
  \sa isActive, begin(), end(), move(), appended()

  \note The appended(const QPoint &), appended(const QDoublePoint &)
pixhawk's avatar
pixhawk committed
        signals are emitted.
*/
Bryant's avatar
Bryant committed
void QwtPlotPicker::append( const QPoint &pos )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QwtPicker::append( pos );
    Q_EMIT appended( invTransform( pos ) );
pixhawk's avatar
pixhawk committed
}

/*!
  Move the last point of the selection

  \param pos New position
  \sa isActive, begin(), end(), append()

  \note The moved(const QPoint &), moved(const QDoublePoint &)
pixhawk's avatar
pixhawk committed
        signals are emitted.
*/
Bryant's avatar
Bryant committed
void QwtPlotPicker::move( const QPoint &pos )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QwtPicker::move( pos );
    Q_EMIT moved( invTransform( pos ) );
pixhawk's avatar
pixhawk committed
}

/*!
  Close a selection setting the state to inactive.

  \param ok If true, complete the selection and emit selected signals
            otherwise discard the selection.
Bryant's avatar
Bryant committed
  \return True if the selection has been accepted, false otherwise
pixhawk's avatar
pixhawk committed
*/

Bryant's avatar
Bryant committed
bool QwtPlotPicker::end( bool ok )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    ok = QwtPicker::end( ok );
pixhawk's avatar
pixhawk committed
    if ( !ok )
        return false;

    QwtPlot *plot = QwtPlotPicker::plot();
    if ( !plot )
        return false;

Bryant's avatar
Bryant committed
    const QPolygon points = selection();
    if ( points.count() == 0 )
pixhawk's avatar
pixhawk committed
        return false;

Bryant's avatar
Bryant committed
    QwtPickerMachine::SelectionType selectionType =
        QwtPickerMachine::NoSelection;

    if ( stateMachine() )
        selectionType = stateMachine()->selectionType();
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    switch ( selectionType )
    {
        case QwtPickerMachine::PointSelection:
        {
            const QPointF pos = invTransform( points.first() );
            Q_EMIT selected( pos );
            break;
        }
        case QwtPickerMachine::RectSelection:
        {
            if ( points.count() >= 2 )
            {
                const QPoint p1 = points.first();
                const QPoint p2 = points.last();

                const QRect rect = QRect( p1, p2 ).normalized();
                Q_EMIT selected( invTransform( rect ) );
            }
            break;
        }
        case QwtPickerMachine::PolygonSelection:
        {
            QVector<QPointF> dpa( points.count() );
            for ( int i = 0; i < points.count(); i++ )
                dpa[i] = invTransform( points[i] );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
            Q_EMIT selected( dpa );
        }
        default:
            break;
pixhawk's avatar
pixhawk committed
    }

    return true;
}

/*!
    Translate a rectangle from pixel into plot coordinates

    \return Rectangle in plot coordinates
Bryant's avatar
Bryant committed
    \sa transform()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QRectF QwtPlotPicker::invTransform( const QRect &rect ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    const QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    const QwtScaleMap yMap = plot()->canvasMap( d_yAxis );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    return QwtScaleMap::invTransform( xMap, yMap, rect );
pixhawk's avatar
pixhawk committed
}

/*!
    Translate a rectangle from plot into pixel coordinates
    \return Rectangle in pixel coordinates
Bryant's avatar
Bryant committed
    \sa invTransform()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QRect QwtPlotPicker::transform( const QRectF &rect ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    const QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    const QwtScaleMap yMap = plot()->canvasMap( d_yAxis );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    return QwtScaleMap::transform( xMap, yMap, rect ).toRect();
pixhawk's avatar
pixhawk committed
}

/*!
    Translate a point from pixel into plot coordinates
    \return Point in plot coordinates
Bryant's avatar
Bryant committed
    \sa transform()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QPointF QwtPlotPicker::invTransform( const QPoint &pos ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    QwtScaleMap yMap = plot()->canvasMap( d_yAxis );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    return QPointF(
        xMap.invTransform( pos.x() ),
        yMap.invTransform( pos.y() )
    );
pixhawk's avatar
pixhawk committed
}

/*!
    Translate a point from plot into pixel coordinates
    \return Point in pixel coordinates
Bryant's avatar
Bryant committed
    \sa invTransform()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QPoint QwtPlotPicker::transform( const QPointF &pos ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    QwtScaleMap yMap = plot()->canvasMap( d_yAxis );

    const QPointF p( xMap.transform( pos.x() ),
        yMap.transform( pos.y() ) );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    return p.toPoint();
pixhawk's avatar
pixhawk committed
}