You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1577 lines
38 KiB
1577 lines
38 KiB
/* -*- 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 |
|
*****************************************************************************/ |
|
|
|
#include "qwt_picker.h" |
|
#include "qwt_picker_machine.h" |
|
#include "qwt_painter.h" |
|
#include "qwt_math.h" |
|
#include "qwt_widget_overlay.h" |
|
#include <qapplication.h> |
|
#include <qevent.h> |
|
#include <qpainter.h> |
|
#include <qframe.h> |
|
#include <qcursor.h> |
|
#include <qbitmap.h> |
|
#include <qpointer.h> |
|
#include <qpaintengine.h> |
|
#include <qmath.h> |
|
|
|
static inline QRegion qwtMaskRegion( const QRect &r, int penWidth ) |
|
{ |
|
const int pw = qMax( penWidth, 1 ); |
|
const int pw2 = penWidth / 2; |
|
|
|
int x1 = r.left() - pw2; |
|
int x2 = r.right() + 1 + pw2 + ( pw % 2 ); |
|
|
|
int y1 = r.top() - pw2; |
|
int y2 = r.bottom() + 1 + pw2 + ( pw % 2 ); |
|
|
|
QRegion region; |
|
|
|
region += QRect( x1, y1, x2 - x1, pw ); |
|
region += QRect( x1, y1, pw, y2 - y1 ); |
|
region += QRect( x1, y2 - pw, x2 - x1, pw ); |
|
region += QRect( x2 - pw, y1, pw, y2 - y1 ); |
|
|
|
return region; |
|
} |
|
|
|
static inline QRegion qwtMaskRegion( const QLine &l, int penWidth ) |
|
{ |
|
const int pw = qMax( penWidth, 1 ); |
|
const int pw2 = penWidth / 2; |
|
|
|
QRegion region; |
|
|
|
if ( l.x1() == l.x2() ) |
|
{ |
|
region += QRect( l.x1() - pw2, l.y1(), |
|
pw, l.y2() ).normalized(); |
|
} |
|
else if ( l.y1() == l.y2() ) |
|
{ |
|
region += QRect( l.x1(), l.y1() - pw2, |
|
l.x2(), pw ).normalized(); |
|
} |
|
|
|
return region; |
|
} |
|
|
|
class QwtPickerRubberband: public QwtWidgetOverlay |
|
{ |
|
public: |
|
QwtPickerRubberband( QwtPicker *, QWidget * ); |
|
|
|
protected: |
|
virtual void drawOverlay( QPainter * ) const; |
|
virtual QRegion maskHint() const; |
|
|
|
QwtPicker *d_picker; |
|
}; |
|
|
|
class QwtPickerTracker: public QwtWidgetOverlay |
|
{ |
|
public: |
|
QwtPickerTracker( QwtPicker *, QWidget * ); |
|
|
|
protected: |
|
virtual void drawOverlay( QPainter * ) const; |
|
virtual QRegion maskHint() const; |
|
|
|
QwtPicker *d_picker; |
|
}; |
|
|
|
|
|
class QwtPicker::PrivateData |
|
{ |
|
public: |
|
PrivateData(): |
|
enabled( false ), |
|
stateMachine( NULL ), |
|
resizeMode( QwtPicker::Stretch ), |
|
rubberBand( QwtPicker::NoRubberBand ), |
|
trackerMode( QwtPicker::AlwaysOff ), |
|
isActive( false ), |
|
trackerPosition( -1, -1 ), |
|
mouseTracking( false ), |
|
openGL( false ) |
|
{ |
|
} |
|
|
|
bool enabled; |
|
|
|
QwtPickerMachine *stateMachine; |
|
|
|
QwtPicker::ResizeMode resizeMode; |
|
|
|
QwtPicker::RubberBand rubberBand; |
|
QPen rubberBandPen; |
|
|
|
QwtPicker::DisplayMode trackerMode; |
|
QPen trackerPen; |
|
QFont trackerFont; |
|
|
|
QPolygon pickedPoints; |
|
bool isActive; |
|
QPoint trackerPosition; |
|
|
|
bool mouseTracking; // used to save previous value |
|
|
|
QPointer< QwtPickerRubberband > rubberBandOverlay; |
|
QPointer< QwtPickerTracker> trackerOverlay; |
|
|
|
bool openGL; |
|
}; |
|
|
|
QwtPickerRubberband::QwtPickerRubberband( |
|
QwtPicker *picker, QWidget *parent ): |
|
QwtWidgetOverlay( parent ), |
|
d_picker( picker ) |
|
{ |
|
setMaskMode( QwtWidgetOverlay::MaskHint ); |
|
} |
|
|
|
QRegion QwtPickerRubberband::maskHint() const |
|
{ |
|
return d_picker->rubberBandMask(); |
|
} |
|
|
|
void QwtPickerRubberband::drawOverlay( QPainter *painter ) const |
|
{ |
|
painter->setPen( d_picker->rubberBandPen() ); |
|
d_picker->drawRubberBand( painter ); |
|
} |
|
|
|
QwtPickerTracker::QwtPickerTracker( |
|
QwtPicker *picker, QWidget *parent ): |
|
QwtWidgetOverlay( parent ), |
|
d_picker( picker ) |
|
{ |
|
setMaskMode( QwtWidgetOverlay::MaskHint ); |
|
} |
|
|
|
QRegion QwtPickerTracker::maskHint() const |
|
{ |
|
return d_picker->trackerRect( font() ); |
|
} |
|
|
|
void QwtPickerTracker::drawOverlay( QPainter *painter ) const |
|
{ |
|
painter->setPen( d_picker->trackerPen() ); |
|
d_picker->drawTracker( painter ); |
|
} |
|
|
|
/*! |
|
Constructor |
|
|
|
Creates an picker that is enabled, but without a state machine. |
|
rubber band and tracker are disabled. |
|
|
|
\param parent Parent widget, that will be observed |
|
*/ |
|
|
|
QwtPicker::QwtPicker( QWidget *parent ): |
|
QObject( parent ) |
|
{ |
|
init( parent, NoRubberBand, AlwaysOff ); |
|
} |
|
|
|
/*! |
|
Constructor |
|
|
|
\param rubberBand Rubber band style |
|
\param trackerMode Tracker mode |
|
\param parent Parent widget, that will be observed |
|
*/ |
|
QwtPicker::QwtPicker( RubberBand rubberBand, |
|
DisplayMode trackerMode, QWidget *parent ): |
|
QObject( parent ) |
|
{ |
|
init( parent, rubberBand, trackerMode ); |
|
} |
|
|
|
//! Destructor |
|
QwtPicker::~QwtPicker() |
|
{ |
|
setMouseTracking( false ); |
|
|
|
delete d_data->stateMachine; |
|
delete d_data->rubberBandOverlay; |
|
delete d_data->trackerOverlay; |
|
|
|
delete d_data; |
|
} |
|
|
|
//! Initialize the picker - used by the constructors |
|
void QwtPicker::init( QWidget *parent, |
|
RubberBand rubberBand, DisplayMode trackerMode ) |
|
{ |
|
d_data = new PrivateData; |
|
|
|
d_data->rubberBand = rubberBand; |
|
|
|
if ( parent ) |
|
{ |
|
if ( parent->focusPolicy() == Qt::NoFocus ) |
|
parent->setFocusPolicy( Qt::WheelFocus ); |
|
|
|
d_data->openGL = parent->inherits( "QGLWidget" ); |
|
d_data->trackerFont = parent->font(); |
|
d_data->mouseTracking = parent->hasMouseTracking(); |
|
|
|
setEnabled( true ); |
|
} |
|
|
|
setTrackerMode( trackerMode ); |
|
} |
|
|
|
/*! |
|
Set a state machine and delete the previous one |
|
|
|
\param stateMachine State machine |
|
\sa stateMachine() |
|
*/ |
|
void QwtPicker::setStateMachine( QwtPickerMachine *stateMachine ) |
|
{ |
|
if ( d_data->stateMachine != stateMachine ) |
|
{ |
|
reset(); |
|
|
|
delete d_data->stateMachine; |
|
d_data->stateMachine = stateMachine; |
|
|
|
if ( d_data->stateMachine ) |
|
d_data->stateMachine->reset(); |
|
} |
|
} |
|
|
|
/*! |
|
\return Assigned state machine |
|
\sa setStateMachine() |
|
*/ |
|
QwtPickerMachine *QwtPicker::stateMachine() |
|
{ |
|
return d_data->stateMachine; |
|
} |
|
|
|
/*! |
|
\return Assigned state machine |
|
\sa setStateMachine() |
|
*/ |
|
const QwtPickerMachine *QwtPicker::stateMachine() const |
|
{ |
|
return d_data->stateMachine; |
|
} |
|
|
|
//! Return the parent widget, where the selection happens |
|
QWidget *QwtPicker::parentWidget() |
|
{ |
|
QObject *obj = parent(); |
|
if ( obj && obj->isWidgetType() ) |
|
return static_cast<QWidget *>( obj ); |
|
|
|
return NULL; |
|
} |
|
|
|
//! Return the parent widget, where the selection happens |
|
const QWidget *QwtPicker::parentWidget() const |
|
{ |
|
QObject *obj = parent(); |
|
if ( obj && obj->isWidgetType() ) |
|
return static_cast< const QWidget *>( obj ); |
|
|
|
return NULL; |
|
} |
|
|
|
/*! |
|
Set the rubber band style |
|
|
|
\param rubberBand Rubber band style |
|
The default value is NoRubberBand. |
|
|
|
\sa rubberBand(), RubberBand, setRubberBandPen() |
|
*/ |
|
void QwtPicker::setRubberBand( RubberBand rubberBand ) |
|
{ |
|
d_data->rubberBand = rubberBand; |
|
} |
|
|
|
/*! |
|
\return Rubber band style |
|
\sa setRubberBand(), RubberBand, rubberBandPen() |
|
*/ |
|
QwtPicker::RubberBand QwtPicker::rubberBand() const |
|
{ |
|
return d_data->rubberBand; |
|
} |
|
|
|
/*! |
|
\brief Set the display mode of the tracker. |
|
|
|
A tracker displays information about current position of |
|
the cursor as a string. The display mode controls |
|
if the tracker has to be displayed whenever the observed |
|
widget has focus and cursor (AlwaysOn), never (AlwaysOff), or |
|
only when the selection is active (ActiveOnly). |
|
|
|
\param mode Tracker display mode |
|
|
|
\warning In case of AlwaysOn, mouseTracking will be enabled |
|
for the observed widget. |
|
\sa trackerMode(), DisplayMode |
|
*/ |
|
|
|
void QwtPicker::setTrackerMode( DisplayMode mode ) |
|
{ |
|
if ( d_data->trackerMode != mode ) |
|
{ |
|
d_data->trackerMode = mode; |
|
setMouseTracking( d_data->trackerMode == AlwaysOn ); |
|
} |
|
} |
|
|
|
/*! |
|
\return Tracker display mode |
|
\sa setTrackerMode(), DisplayMode |
|
*/ |
|
QwtPicker::DisplayMode QwtPicker::trackerMode() const |
|
{ |
|
return d_data->trackerMode; |
|
} |
|
|
|
/*! |
|
\brief Set the resize mode. |
|
|
|
The resize mode controls what to do with the selected points of an active |
|
selection when the observed widget is resized. |
|
|
|
Stretch means the points are scaled according to the new |
|
size, KeepSize means the points remain unchanged. |
|
|
|
The default mode is Stretch. |
|
|
|
\param mode Resize mode |
|
\sa resizeMode(), ResizeMode |
|
*/ |
|
void QwtPicker::setResizeMode( ResizeMode mode ) |
|
{ |
|
d_data->resizeMode = mode; |
|
} |
|
|
|
/*! |
|
\return Resize mode |
|
\sa setResizeMode(), ResizeMode |
|
*/ |
|
|
|
QwtPicker::ResizeMode QwtPicker::resizeMode() const |
|
{ |
|
return d_data->resizeMode; |
|
} |
|
|
|
/*! |
|
\brief En/disable the picker |
|
|
|
When enabled is true an event filter is installed for |
|
the observed widget, otherwise the event filter is removed. |
|
|
|
\param enabled true or false |
|
\sa isEnabled(), eventFilter() |
|
*/ |
|
void QwtPicker::setEnabled( bool enabled ) |
|
{ |
|
if ( d_data->enabled != enabled ) |
|
{ |
|
d_data->enabled = enabled; |
|
|
|
QWidget *w = parentWidget(); |
|
if ( w ) |
|
{ |
|
if ( enabled ) |
|
w->installEventFilter( this ); |
|
else |
|
w->removeEventFilter( this ); |
|
} |
|
|
|
updateDisplay(); |
|
} |
|
} |
|
|
|
/*! |
|
\return true when enabled, false otherwise |
|
\sa setEnabled(), eventFilter() |
|
*/ |
|
|
|
bool QwtPicker::isEnabled() const |
|
{ |
|
return d_data->enabled; |
|
} |
|
|
|
/*! |
|
Set the font for the tracker |
|
|
|
\param font Tracker font |
|
\sa trackerFont(), setTrackerMode(), setTrackerPen() |
|
*/ |
|
void QwtPicker::setTrackerFont( const QFont &font ) |
|
{ |
|
if ( font != d_data->trackerFont ) |
|
{ |
|
d_data->trackerFont = font; |
|
updateDisplay(); |
|
} |
|
} |
|
|
|
/*! |
|
\return Tracker font |
|
\sa setTrackerFont(), trackerMode(), trackerPen() |
|
*/ |
|
|
|
QFont QwtPicker::trackerFont() const |
|
{ |
|
return d_data->trackerFont; |
|
} |
|
|
|
/*! |
|
Set the pen for the tracker |
|
|
|
\param pen Tracker pen |
|
\sa trackerPen(), setTrackerMode(), setTrackerFont() |
|
*/ |
|
void QwtPicker::setTrackerPen( const QPen &pen ) |
|
{ |
|
if ( pen != d_data->trackerPen ) |
|
{ |
|
d_data->trackerPen = pen; |
|
updateDisplay(); |
|
} |
|
} |
|
|
|
/*! |
|
\return Tracker pen |
|
\sa setTrackerPen(), trackerMode(), trackerFont() |
|
*/ |
|
QPen QwtPicker::trackerPen() const |
|
{ |
|
return d_data->trackerPen; |
|
} |
|
|
|
/*! |
|
Set the pen for the rubberband |
|
|
|
\param pen Rubber band pen |
|
\sa rubberBandPen(), setRubberBand() |
|
*/ |
|
void QwtPicker::setRubberBandPen( const QPen &pen ) |
|
{ |
|
if ( pen != d_data->rubberBandPen ) |
|
{ |
|
d_data->rubberBandPen = pen; |
|
updateDisplay(); |
|
} |
|
} |
|
|
|
/*! |
|
\return Rubber band pen |
|
\sa setRubberBandPen(), rubberBand() |
|
*/ |
|
QPen QwtPicker::rubberBandPen() const |
|
{ |
|
return d_data->rubberBandPen; |
|
} |
|
|
|
/*! |
|
\brief Return the label for a position |
|
|
|
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 string conversion is "%d". |
|
|
|
\param pos Position |
|
\return Converted position as string |
|
*/ |
|
|
|
QwtText QwtPicker::trackerText( const QPoint &pos ) const |
|
{ |
|
QString label; |
|
|
|
switch ( rubberBand() ) |
|
{ |
|
case HLineRubberBand: |
|
label.sprintf( "%d", pos.y() ); |
|
break; |
|
case VLineRubberBand: |
|
label.sprintf( "%d", pos.x() ); |
|
break; |
|
default: |
|
label.sprintf( "%d, %d", pos.x(), pos.y() ); |
|
} |
|
return label; |
|
} |
|
|
|
/*! |
|
Calculate the mask for the rubber band overlay |
|
|
|
\return Region for the mask |
|
\sa QWidget::setMask() |
|
*/ |
|
QRegion QwtPicker::rubberBandMask() const |
|
{ |
|
QRegion mask; |
|
|
|
if ( !isActive() || rubberBand() == NoRubberBand || |
|
rubberBandPen().style() == Qt::NoPen ) |
|
{ |
|
return mask; |
|
} |
|
|
|
const QPolygon pa = adjustedPoints( d_data->pickedPoints ); |
|
|
|
QwtPickerMachine::SelectionType selectionType = |
|
QwtPickerMachine::NoSelection; |
|
|
|
if ( d_data->stateMachine ) |
|
selectionType = d_data->stateMachine->selectionType(); |
|
|
|
switch ( selectionType ) |
|
{ |
|
case QwtPickerMachine::NoSelection: |
|
case QwtPickerMachine::PointSelection: |
|
{ |
|
if ( pa.count() < 1 ) |
|
return mask; |
|
|
|
const QPoint pos = pa[0]; |
|
const int pw = rubberBandPen().width(); |
|
|
|
const QRect pRect = pickArea().boundingRect().toRect(); |
|
switch ( rubberBand() ) |
|
{ |
|
case VLineRubberBand: |
|
{ |
|
mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), |
|
pos.x(), pRect.bottom() ), pw ); |
|
break; |
|
} |
|
case HLineRubberBand: |
|
{ |
|
mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), |
|
pRect.right(), pos.y() ), pw ); |
|
break; |
|
} |
|
case CrossRubberBand: |
|
{ |
|
mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), |
|
pos.x(), pRect.bottom() ), pw ); |
|
mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), |
|
pRect.right(), pos.y() ), pw ); |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
break; |
|
} |
|
case QwtPickerMachine::RectSelection: |
|
{ |
|
if ( pa.count() < 2 ) |
|
return mask; |
|
|
|
const int pw = rubberBandPen().width(); |
|
|
|
switch ( rubberBand() ) |
|
{ |
|
case RectRubberBand: |
|
{ |
|
const QRect r = QRect( pa.first(), pa.last() ); |
|
mask = qwtMaskRegion( r.normalized(), pw ); |
|
break; |
|
} |
|
case EllipseRubberBand: |
|
{ |
|
const QRect r = QRect( pa.first(), pa.last() ); |
|
mask += r.adjusted( -pw, -pw, pw, pw ); |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
break; |
|
} |
|
case QwtPickerMachine::PolygonSelection: |
|
{ |
|
const int pw = rubberBandPen().width(); |
|
if ( pw <= 1 ) |
|
{ |
|
// because of the join style we better |
|
// return a mask for a pen width <= 1 only |
|
|
|
const int off = 2 * pw; |
|
const QRect r = pa.boundingRect(); |
|
mask += r.adjusted( -off, -off, off, off ); |
|
} |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
|
|
return mask; |
|
} |
|
|
|
/*! |
|
Draw a rubber band, depending on rubberBand() |
|
|
|
\param painter Painter, initialized with a clip region |
|
|
|
\sa rubberBand(), RubberBand |
|
*/ |
|
|
|
void QwtPicker::drawRubberBand( QPainter *painter ) const |
|
{ |
|
if ( !isActive() || rubberBand() == NoRubberBand || |
|
rubberBandPen().style() == Qt::NoPen ) |
|
{ |
|
return; |
|
} |
|
|
|
const QPolygon pa = adjustedPoints( d_data->pickedPoints ); |
|
|
|
QwtPickerMachine::SelectionType selectionType = |
|
QwtPickerMachine::NoSelection; |
|
|
|
if ( d_data->stateMachine ) |
|
selectionType = d_data->stateMachine->selectionType(); |
|
|
|
switch ( selectionType ) |
|
{ |
|
case QwtPickerMachine::NoSelection: |
|
case QwtPickerMachine::PointSelection: |
|
{ |
|
if ( pa.count() < 1 ) |
|
return; |
|
|
|
const QPoint pos = pa[0]; |
|
|
|
const QRect pRect = pickArea().boundingRect().toRect(); |
|
switch ( rubberBand() ) |
|
{ |
|
case VLineRubberBand: |
|
{ |
|
QwtPainter::drawLine( painter, pos.x(), |
|
pRect.top(), pos.x(), pRect.bottom() ); |
|
break; |
|
} |
|
case HLineRubberBand: |
|
{ |
|
QwtPainter::drawLine( painter, pRect.left(), |
|
pos.y(), pRect.right(), pos.y() ); |
|
break; |
|
} |
|
case CrossRubberBand: |
|
{ |
|
QwtPainter::drawLine( painter, pos.x(), |
|
pRect.top(), pos.x(), pRect.bottom() ); |
|
QwtPainter::drawLine( painter, pRect.left(), |
|
pos.y(), pRect.right(), pos.y() ); |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
break; |
|
} |
|
case QwtPickerMachine::RectSelection: |
|
{ |
|
if ( pa.count() < 2 ) |
|
return; |
|
|
|
const QRect rect = QRect( pa.first(), pa.last() ).normalized(); |
|
switch ( rubberBand() ) |
|
{ |
|
case EllipseRubberBand: |
|
{ |
|
QwtPainter::drawEllipse( painter, rect ); |
|
break; |
|
} |
|
case RectRubberBand: |
|
{ |
|
QwtPainter::drawRect( painter, rect ); |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
break; |
|
} |
|
case QwtPickerMachine::PolygonSelection: |
|
{ |
|
if ( rubberBand() == PolygonRubberBand ) |
|
painter->drawPolyline( pa ); |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
/*! |
|
Draw the tracker |
|
|
|
\param painter Painter |
|
\sa trackerRect(), trackerText() |
|
*/ |
|
|
|
void QwtPicker::drawTracker( QPainter *painter ) const |
|
{ |
|
const QRect textRect = trackerRect( painter->font() ); |
|
if ( !textRect.isEmpty() ) |
|
{ |
|
const QwtText label = trackerText( d_data->trackerPosition ); |
|
if ( !label.isEmpty() ) |
|
label.draw( painter, textRect ); |
|
} |
|
} |
|
|
|
/*! |
|
\brief Map the pickedPoints() into a selection() |
|
|
|
adjustedPoints() maps the points, that have been collected on |
|
the parentWidget() into a selection(). The default implementation |
|
simply returns the points unmodified. |
|
|
|
The reason, why a selection() differs from the picked points |
|
depends on the application requirements. F.e. : |
|
|
|
- A rectangular selection might need to have a specific aspect ratio only.\n |
|
- A selection could accept non intersecting polygons only.\n |
|
- ...\n |
|
|
|
The example below is for a rectangular selection, where the first |
|
point is the center of the selected rectangle. |
|
\par Example |
|
\verbatim QPolygon MyPicker::adjustedPoints(const QPolygon &points) const |
|
{ |
|
QPolygon adjusted; |
|
if ( points.size() == 2 ) |
|
{ |
|
const int width = qAbs(points[1].x() - points[0].x()); |
|
const int height = qAbs(points[1].y() - points[0].y()); |
|
|
|
QRect rect(0, 0, 2 * width, 2 * height); |
|
rect.moveCenter(points[0]); |
|
|
|
adjusted += rect.topLeft(); |
|
adjusted += rect.bottomRight(); |
|
} |
|
return adjusted; |
|
}\endverbatim\n |
|
|
|
\param points Selected points |
|
\return Selected points unmodified |
|
*/ |
|
QPolygon QwtPicker::adjustedPoints( const QPolygon &points ) const |
|
{ |
|
return points; |
|
} |
|
|
|
/*! |
|
\return Selected points |
|
\sa pickedPoints(), adjustedPoints() |
|
*/ |
|
QPolygon QwtPicker::selection() const |
|
{ |
|
return adjustedPoints( d_data->pickedPoints ); |
|
} |
|
|
|
//! \return Current position of the tracker |
|
QPoint QwtPicker::trackerPosition() const |
|
{ |
|
return d_data->trackerPosition; |
|
} |
|
|
|
/*! |
|
Calculate the bounding rectangle for the tracker text |
|
from the current position of the tracker |
|
|
|
\param font Font of the tracker text |
|
\return Bounding rectangle of the tracker text |
|
|
|
\sa trackerPosition() |
|
*/ |
|
QRect QwtPicker::trackerRect( const QFont &font ) const |
|
{ |
|
if ( trackerMode() == AlwaysOff || |
|
( trackerMode() == ActiveOnly && !isActive() ) ) |
|
{ |
|
return QRect(); |
|
} |
|
|
|
if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) |
|
return QRect(); |
|
|
|
QwtText text = trackerText( d_data->trackerPosition ); |
|
if ( text.isEmpty() ) |
|
return QRect(); |
|
|
|
const QSizeF textSize = text.textSize( font ); |
|
QRect textRect( 0, 0, qCeil( textSize.width() ), qCeil( textSize.height() ) ); |
|
|
|
const QPoint &pos = d_data->trackerPosition; |
|
|
|
int alignment = 0; |
|
if ( isActive() && d_data->pickedPoints.count() > 1 |
|
&& rubberBand() != NoRubberBand ) |
|
{ |
|
const QPoint last = |
|
d_data->pickedPoints[int( d_data->pickedPoints.count() ) - 2]; |
|
|
|
alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft; |
|
alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop; |
|
} |
|
else |
|
alignment = Qt::AlignTop | Qt::AlignRight; |
|
|
|
const int margin = 5; |
|
|
|
int x = pos.x(); |
|
if ( alignment & Qt::AlignLeft ) |
|
x -= textRect.width() + margin; |
|
else if ( alignment & Qt::AlignRight ) |
|
x += margin; |
|
|
|
int y = pos.y(); |
|
if ( alignment & Qt::AlignBottom ) |
|
y += margin; |
|
else if ( alignment & Qt::AlignTop ) |
|
y -= textRect.height() + margin; |
|
|
|
textRect.moveTopLeft( QPoint( x, y ) ); |
|
|
|
const QRect pickRect = pickArea().boundingRect().toRect(); |
|
|
|
int right = qMin( textRect.right(), pickRect.right() - margin ); |
|
int bottom = qMin( textRect.bottom(), pickRect.bottom() - margin ); |
|
textRect.moveBottomRight( QPoint( right, bottom ) ); |
|
|
|
int left = qMax( textRect.left(), pickRect.left() + margin ); |
|
int top = qMax( textRect.top(), pickRect.top() + margin ); |
|
textRect.moveTopLeft( QPoint( left, top ) ); |
|
|
|
return textRect; |
|
} |
|
|
|
/*! |
|
\brief Event filter |
|
|
|
When isEnabled() is true all events of the observed widget are filtered. |
|
Mouse and keyboard events are translated into widgetMouse- and widgetKey- |
|
and widgetWheel-events. Paint and Resize events are handled to keep |
|
rubber band and tracker up to date. |
|
|
|
\param object Object to be filtered |
|
\param event Event |
|
|
|
\return Always false. |
|
|
|
\sa widgetEnterEvent(), widgetLeaveEvent(), |
|
widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent(), |
|
QObject::installEventFilter(), QObject::event() |
|
*/ |
|
bool QwtPicker::eventFilter( QObject *object, QEvent *event ) |
|
{ |
|
if ( object && object == parentWidget() ) |
|
{ |
|
switch ( event->type() ) |
|
{ |
|
case QEvent::Resize: |
|
{ |
|
const QResizeEvent *re = static_cast<QResizeEvent *>( event ); |
|
if ( d_data->resizeMode == Stretch ) |
|
stretchSelection( re->oldSize(), re->size() ); |
|
|
|
break; |
|
} |
|
case QEvent::Enter: |
|
{ |
|
widgetEnterEvent( event ); |
|
break; |
|
} |
|
case QEvent::Leave: |
|
{ |
|
widgetLeaveEvent( event ); |
|
break; |
|
} |
|
case QEvent::MouseButtonPress: |
|
{ |
|
widgetMousePressEvent( static_cast<QMouseEvent *>( event ) ); |
|
break; |
|
} |
|
case QEvent::MouseButtonRelease: |
|
{ |
|
widgetMouseReleaseEvent( static_cast<QMouseEvent *>( event ) ); |
|
break; |
|
} |
|
case QEvent::MouseButtonDblClick: |
|
{ |
|
widgetMouseDoubleClickEvent( static_cast<QMouseEvent *>( event ) ); |
|
break; |
|
} |
|
case QEvent::MouseMove: |
|
{ |
|
widgetMouseMoveEvent( static_cast<QMouseEvent *>( event ) ); |
|
break; |
|
} |
|
case QEvent::KeyPress: |
|
{ |
|
widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) ); |
|
break; |
|
} |
|
case QEvent::KeyRelease: |
|
{ |
|
widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) ); |
|
break; |
|
} |
|
case QEvent::Wheel: |
|
{ |
|
widgetWheelEvent( static_cast<QWheelEvent *>( event ) ); |
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/*! |
|
Handle a mouse press event for the observed widget. |
|
|
|
\param mouseEvent Mouse event |
|
|
|
\sa eventFilter(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() |
|
*/ |
|
void QwtPicker::widgetMousePressEvent( QMouseEvent *mouseEvent ) |
|
{ |
|
transition( mouseEvent ); |
|
} |
|
|
|
/*! |
|
Handle a mouse move event for the observed widget. |
|
|
|
\param mouseEvent Mouse event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() |
|
*/ |
|
void QwtPicker::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) |
|
{ |
|
if ( pickArea().contains( mouseEvent->pos() ) ) |
|
d_data->trackerPosition = mouseEvent->pos(); |
|
else |
|
d_data->trackerPosition = QPoint( -1, -1 ); |
|
|
|
if ( !isActive() ) |
|
updateDisplay(); |
|
|
|
transition( mouseEvent ); |
|
} |
|
|
|
/*! |
|
Handle a enter event for the observed widget. |
|
|
|
\param event Qt event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() |
|
*/ |
|
void QwtPicker::widgetEnterEvent( QEvent *event ) |
|
{ |
|
transition( event ); |
|
} |
|
|
|
/*! |
|
Handle a leave event for the observed widget. |
|
|
|
\param event Qt event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() |
|
*/ |
|
void QwtPicker::widgetLeaveEvent( QEvent *event ) |
|
{ |
|
transition( event ); |
|
|
|
d_data->trackerPosition = QPoint( -1, -1 ); |
|
if ( !isActive() ) |
|
updateDisplay(); |
|
} |
|
|
|
/*! |
|
Handle a mouse release event for the observed widget. |
|
|
|
\param mouseEvent Mouse event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), |
|
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() |
|
*/ |
|
void QwtPicker::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) |
|
{ |
|
transition( mouseEvent ); |
|
} |
|
|
|
/*! |
|
Handle mouse double click event for the observed widget. |
|
|
|
\param mouseEvent Mouse event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseMoveEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() |
|
*/ |
|
void QwtPicker::widgetMouseDoubleClickEvent( QMouseEvent *mouseEvent ) |
|
{ |
|
transition( mouseEvent ); |
|
} |
|
|
|
|
|
/*! |
|
Handle a wheel event for the observed widget. |
|
|
|
Move the last point of the selection in case of isActive() == true |
|
|
|
\param wheelEvent Wheel event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), |
|
widgetKeyPressEvent(), widgetKeyReleaseEvent() |
|
*/ |
|
void QwtPicker::widgetWheelEvent( QWheelEvent *wheelEvent ) |
|
{ |
|
if ( pickArea().contains( wheelEvent->pos() ) ) |
|
d_data->trackerPosition = wheelEvent->pos(); |
|
else |
|
d_data->trackerPosition = QPoint( -1, -1 ); |
|
|
|
updateDisplay(); |
|
|
|
transition( wheelEvent ); |
|
} |
|
|
|
/*! |
|
Handle a key press event for the observed widget. |
|
|
|
Selections can be completely done by the keyboard. The arrow keys |
|
move the cursor, the abort key aborts a selection. All other keys |
|
are handled by the current state machine. |
|
|
|
\param keyEvent Key event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), |
|
widgetWheelEvent(), widgetKeyReleaseEvent(), stateMachine(), |
|
QwtEventPattern::KeyPatternCode |
|
*/ |
|
void QwtPicker::widgetKeyPressEvent( QKeyEvent *keyEvent ) |
|
{ |
|
int dx = 0; |
|
int dy = 0; |
|
|
|
int offset = 1; |
|
if ( keyEvent->isAutoRepeat() ) |
|
offset = 5; |
|
|
|
if ( keyMatch( KeyLeft, keyEvent ) ) |
|
dx = -offset; |
|
else if ( keyMatch( KeyRight, keyEvent ) ) |
|
dx = offset; |
|
else if ( keyMatch( KeyUp, keyEvent ) ) |
|
dy = -offset; |
|
else if ( keyMatch( KeyDown, keyEvent ) ) |
|
dy = offset; |
|
else if ( keyMatch( KeyAbort, keyEvent ) ) |
|
{ |
|
reset(); |
|
} |
|
else |
|
transition( keyEvent ); |
|
|
|
if ( dx != 0 || dy != 0 ) |
|
{ |
|
const QRect rect = pickArea().boundingRect().toRect(); |
|
const QPoint pos = parentWidget()->mapFromGlobal( QCursor::pos() ); |
|
|
|
int x = pos.x() + dx; |
|
x = qMax( rect.left(), x ); |
|
x = qMin( rect.right(), x ); |
|
|
|
int y = pos.y() + dy; |
|
y = qMax( rect.top(), y ); |
|
y = qMin( rect.bottom(), y ); |
|
|
|
QCursor::setPos( parentWidget()->mapToGlobal( QPoint( x, y ) ) ); |
|
} |
|
} |
|
|
|
/*! |
|
Handle a key release event for the observed widget. |
|
|
|
Passes the event to the state machine. |
|
|
|
\param keyEvent Key event |
|
|
|
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), |
|
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), |
|
widgetWheelEvent(), widgetKeyPressEvent(), stateMachine() |
|
*/ |
|
void QwtPicker::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) |
|
{ |
|
transition( keyEvent ); |
|
} |
|
|
|
/*! |
|
Passes an event to the state machine and executes the resulting |
|
commands. Append and Move commands use the current position |
|
of the cursor ( QCursor::pos() ). |
|
|
|
\param event Event |
|
*/ |
|
void QwtPicker::transition( const QEvent *event ) |
|
{ |
|
if ( !d_data->stateMachine ) |
|
return; |
|
|
|
const QList<QwtPickerMachine::Command> commandList = |
|
d_data->stateMachine->transition( *this, event ); |
|
|
|
QPoint pos; |
|
switch ( event->type() ) |
|
{ |
|
case QEvent::MouseButtonDblClick: |
|
case QEvent::MouseButtonPress: |
|
case QEvent::MouseButtonRelease: |
|
case QEvent::MouseMove: |
|
{ |
|
const QMouseEvent *me = |
|
static_cast< const QMouseEvent * >( event ); |
|
pos = me->pos(); |
|
break; |
|
} |
|
default: |
|
pos = parentWidget()->mapFromGlobal( QCursor::pos() ); |
|
} |
|
|
|
for ( int i = 0; i < commandList.count(); i++ ) |
|
{ |
|
switch ( commandList[i] ) |
|
{ |
|
case QwtPickerMachine::Begin: |
|
{ |
|
begin(); |
|
break; |
|
} |
|
case QwtPickerMachine::Append: |
|
{ |
|
append( pos ); |
|
break; |
|
} |
|
case QwtPickerMachine::Move: |
|
{ |
|
move( pos ); |
|
break; |
|
} |
|
case QwtPickerMachine::Remove: |
|
{ |
|
remove(); |
|
break; |
|
} |
|
case QwtPickerMachine::End: |
|
{ |
|
end(); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/*! |
|
Open a selection setting the state to active |
|
|
|
\sa isActive(), end(), append(), move() |
|
*/ |
|
void QwtPicker::begin() |
|
{ |
|
if ( d_data->isActive ) |
|
return; |
|
|
|
d_data->pickedPoints.resize( 0 ); |
|
d_data->isActive = true; |
|
Q_EMIT activated( true ); |
|
|
|
if ( trackerMode() != AlwaysOff ) |
|
{ |
|
if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) |
|
{ |
|
QWidget *w = parentWidget(); |
|
if ( w ) |
|
d_data->trackerPosition = w->mapFromGlobal( QCursor::pos() ); |
|
} |
|
} |
|
|
|
updateDisplay(); |
|
setMouseTracking( true ); |
|
} |
|
|
|
/*! |
|
\brief Close a selection setting the state to inactive. |
|
|
|
The selection is validated and maybe fixed by accept(). |
|
|
|
\param ok If true, complete the selection and emit a selected signal |
|
otherwise discard the selection. |
|
\return true if the selection is accepted, false otherwise |
|
\sa isActive(), begin(), append(), move(), selected(), accept() |
|
*/ |
|
bool QwtPicker::end( bool ok ) |
|
{ |
|
if ( d_data->isActive ) |
|
{ |
|
setMouseTracking( false ); |
|
|
|
d_data->isActive = false; |
|
Q_EMIT activated( false ); |
|
|
|
if ( trackerMode() == ActiveOnly ) |
|
d_data->trackerPosition = QPoint( -1, -1 ); |
|
|
|
if ( ok ) |
|
ok = accept( d_data->pickedPoints ); |
|
|
|
if ( ok ) |
|
Q_EMIT selected( d_data->pickedPoints ); |
|
else |
|
d_data->pickedPoints.resize( 0 ); |
|
|
|
updateDisplay(); |
|
} |
|
else |
|
ok = false; |
|
|
|
return ok; |
|
} |
|
|
|
/*! |
|
Reset the state machine and terminate ( end(false) ) the selection |
|
*/ |
|
void QwtPicker::reset() |
|
{ |
|
if ( d_data->stateMachine ) |
|
d_data->stateMachine->reset(); |
|
|
|
if ( isActive() ) |
|
end( false ); |
|
} |
|
|
|
/*! |
|
Append a point to the selection and update rubber band and tracker. |
|
The appended() signal is emitted. |
|
|
|
\param pos Additional point |
|
|
|
\sa isActive(), begin(), end(), move(), appended() |
|
*/ |
|
void QwtPicker::append( const QPoint &pos ) |
|
{ |
|
if ( d_data->isActive ) |
|
{ |
|
const int idx = d_data->pickedPoints.count(); |
|
d_data->pickedPoints.resize( idx + 1 ); |
|
d_data->pickedPoints[idx] = pos; |
|
|
|
updateDisplay(); |
|
Q_EMIT appended( pos ); |
|
} |
|
} |
|
|
|
/*! |
|
Move the last point of the selection |
|
The moved() signal is emitted. |
|
|
|
\param pos New position |
|
\sa isActive(), begin(), end(), append() |
|
*/ |
|
void QwtPicker::move( const QPoint &pos ) |
|
{ |
|
if ( d_data->isActive ) |
|
{ |
|
const int idx = d_data->pickedPoints.count() - 1; |
|
if ( idx >= 0 ) |
|
{ |
|
if ( d_data->pickedPoints[idx] != pos ) |
|
{ |
|
d_data->pickedPoints[idx] = pos; |
|
|
|
updateDisplay(); |
|
Q_EMIT moved( pos ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
/*! |
|
Remove the last point of the selection |
|
The removed() signal is emitted. |
|
|
|
\sa isActive(), begin(), end(), append(), move() |
|
*/ |
|
void QwtPicker::remove() |
|
{ |
|
if ( d_data->isActive ) |
|
{ |
|
const int idx = d_data->pickedPoints.count() - 1; |
|
if ( idx > 0 ) |
|
{ |
|
const int idx = d_data->pickedPoints.count(); |
|
|
|
const QPoint pos = d_data->pickedPoints[idx - 1]; |
|
d_data->pickedPoints.resize( idx - 1 ); |
|
|
|
updateDisplay(); |
|
Q_EMIT removed( pos ); |
|
} |
|
} |
|
} |
|
|
|
/*! |
|
\brief Validate and fix up the selection |
|
|
|
Accepts all selections unmodified |
|
|
|
\param selection Selection to validate and fix up |
|
\return true, when accepted, false otherwise |
|
*/ |
|
bool QwtPicker::accept( QPolygon &selection ) const |
|
{ |
|
Q_UNUSED( selection ); |
|
return true; |
|
} |
|
|
|
/*! |
|
A picker is active between begin() and end(). |
|
\return true if the selection is active. |
|
*/ |
|
bool QwtPicker::isActive() const |
|
{ |
|
return d_data->isActive; |
|
} |
|
|
|
/*! |
|
Return the points, that have been collected so far. The selection() |
|
is calculated from the pickedPoints() in adjustedPoints(). |
|
\return Picked points |
|
*/ |
|
const QPolygon &QwtPicker::pickedPoints() const |
|
{ |
|
return d_data->pickedPoints; |
|
} |
|
|
|
/*! |
|
Scale the selection by the ratios of oldSize and newSize |
|
The changed() signal is emitted. |
|
|
|
\param oldSize Previous size |
|
\param newSize Current size |
|
|
|
\sa ResizeMode, setResizeMode(), resizeMode() |
|
*/ |
|
void QwtPicker::stretchSelection( const QSize &oldSize, const QSize &newSize ) |
|
{ |
|
if ( oldSize.isEmpty() ) |
|
{ |
|
// avoid division by zero. But scaling for small sizes also |
|
// doesn't make much sense, because of rounding losses. TODO ... |
|
return; |
|
} |
|
|
|
const double xRatio = |
|
double( newSize.width() ) / double( oldSize.width() ); |
|
const double yRatio = |
|
double( newSize.height() ) / double( oldSize.height() ); |
|
|
|
for ( int i = 0; i < int( d_data->pickedPoints.count() ); i++ ) |
|
{ |
|
QPoint &p = d_data->pickedPoints[i]; |
|
p.setX( qRound( p.x() * xRatio ) ); |
|
p.setY( qRound( p.y() * yRatio ) ); |
|
|
|
Q_EMIT changed( d_data->pickedPoints ); |
|
} |
|
} |
|
|
|
/*! |
|
Set mouse tracking for the observed widget. |
|
|
|
In case of enable is true, the previous value |
|
is saved, that is restored when enable is false. |
|
|
|
\warning Even when enable is false, mouse tracking might be restored |
|
to true. When mouseTracking for the observed widget |
|
has been changed directly by QWidget::setMouseTracking |
|
while mouse tracking has been set to true, this value can't |
|
be restored. |
|
*/ |
|
|
|
void QwtPicker::setMouseTracking( bool enable ) |
|
{ |
|
QWidget *widget = parentWidget(); |
|
if ( !widget ) |
|
return; |
|
|
|
if ( enable ) |
|
{ |
|
d_data->mouseTracking = widget->hasMouseTracking(); |
|
widget->setMouseTracking( true ); |
|
} |
|
else |
|
{ |
|
widget->setMouseTracking( d_data->mouseTracking ); |
|
} |
|
} |
|
|
|
/*! |
|
Find the area of the observed widget, where selection might happen. |
|
|
|
\return parentWidget()->contentsRect() |
|
*/ |
|
QPainterPath QwtPicker::pickArea() const |
|
{ |
|
QPainterPath path; |
|
|
|
const QWidget *widget = parentWidget(); |
|
if ( widget ) |
|
path.addRect( widget->contentsRect() ); |
|
|
|
return path; |
|
} |
|
|
|
//! Update the state of rubber band and tracker label |
|
void QwtPicker::updateDisplay() |
|
{ |
|
QWidget *w = parentWidget(); |
|
|
|
bool showRubberband = false; |
|
bool showTracker = false; |
|
|
|
if ( w && w->isVisible() && d_data->enabled ) |
|
{ |
|
if ( rubberBand() != NoRubberBand && isActive() && |
|
rubberBandPen().style() != Qt::NoPen ) |
|
{ |
|
showRubberband = true; |
|
} |
|
|
|
if ( trackerMode() == AlwaysOn || |
|
( trackerMode() == ActiveOnly && isActive() ) ) |
|
{ |
|
if ( trackerPen() != Qt::NoPen |
|
&& !trackerRect( QFont() ).isEmpty() ) |
|
{ |
|
showTracker = true; |
|
} |
|
} |
|
} |
|
|
|
QPointer< QwtPickerRubberband > &rw = d_data->rubberBandOverlay; |
|
if ( showRubberband ) |
|
{ |
|
if ( rw.isNull() ) |
|
{ |
|
rw = new QwtPickerRubberband( this, w ); |
|
rw->setObjectName( "PickerRubberBand" ); |
|
rw->resize( w->size() ); |
|
} |
|
|
|
if ( d_data->rubberBand <= RectRubberBand ) |
|
rw->setMaskMode( QwtWidgetOverlay::MaskHint ); |
|
else |
|
rw->setMaskMode( QwtWidgetOverlay::AlphaMask ); |
|
|
|
rw->updateOverlay(); |
|
} |
|
else |
|
{ |
|
if ( d_data->openGL ) |
|
{ |
|
// Qt 4.8 crashes for a delete |
|
if ( !rw.isNull() ) |
|
{ |
|
rw->hide(); |
|
rw->deleteLater(); |
|
rw = NULL; |
|
} |
|
} |
|
else |
|
{ |
|
delete rw; |
|
} |
|
} |
|
|
|
QPointer< QwtPickerTracker > &tw = d_data->trackerOverlay; |
|
if ( showTracker ) |
|
{ |
|
if ( tw.isNull() ) |
|
{ |
|
tw = new QwtPickerTracker( this, w ); |
|
tw->setObjectName( "PickerTracker" ); |
|
tw->resize( w->size() ); |
|
} |
|
tw->setFont( d_data->trackerFont ); |
|
tw->updateOverlay(); |
|
} |
|
else |
|
{ |
|
if ( d_data->openGL ) |
|
{ |
|
// Qt 4.8 crashes for a delete |
|
if ( !tw.isNull() ) |
|
{ |
|
tw->hide(); |
|
tw->deleteLater(); |
|
tw = NULL; |
|
} |
|
} |
|
else |
|
{ |
|
delete tw; |
|
} |
|
} |
|
} |
|
|
|
//! \return Overlay displaying the rubber band |
|
const QwtWidgetOverlay *QwtPicker::rubberBandOverlay() const |
|
{ |
|
return d_data->rubberBandOverlay; |
|
} |
|
|
|
//! \return Overlay displaying the tracker text |
|
const QwtWidgetOverlay *QwtPicker::trackerOverlay() const |
|
{ |
|
return d_data->trackerOverlay; |
|
} |
|
|
|
|