地面站终端 App
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.

1300 lines
29 KiB

15 years ago
/* -*- 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_wheel.h"
#include "qwt_math.h"
#include "qwt_painter.h"
15 years ago
#include <qevent.h>
#include <qdrawutil.h>
#include <qpainter.h>
#include <qstyle.h>
#include <qstyleoption.h>
#include <qapplication.h>
#include <qdatetime.h>
#if QT_VERSION < 0x040601
#define qFabs(x) ::fabs(x)
#define qFastSin(x) ::sin(x)
#define qExp(x) ::exp(x)
#endif
15 years ago
class QwtWheel::PrivateData
{
public:
PrivateData():
orientation( Qt::Horizontal ),
viewAngle( 175.0 ),
totalAngle( 360.0 ),
tickCount( 10 ),
wheelBorderWidth( 2 ),
borderWidth( 2 ),
wheelWidth( 20 ),
isScrolling( false ),
mouseOffset( 0.0 ),
tracking( true ),
pendingValueChanged( false ),
updateInterval( 50 ),
mass( 0.0 ),
timerId( 0 ),
speed( 0.0 ),
mouseValue( 0.0 ),
flyingValue( 0.0 ),
minimum( 0.0 ),
maximum( 100.0 ),
singleStep( 1.0 ),
pageStepCount( 1 ),
stepAlignment( true ),
value( 0.0 ),
inverted( false ),
wrapping( false )
{
15 years ago
};
Qt::Orientation orientation;
15 years ago
double viewAngle;
double totalAngle;
int tickCount;
int wheelBorderWidth;
15 years ago
int borderWidth;
int wheelWidth;
bool isScrolling;
double mouseOffset;
bool tracking;
bool pendingValueChanged; // when not tracking
int updateInterval;
double mass;
// for the flying wheel effect
int timerId;
QTime time;
double speed;
double mouseValue;
double flyingValue;
double minimum;
double maximum;
double singleStep;
int pageStepCount;
bool stepAlignment;
double value;
bool inverted;
bool wrapping;
15 years ago
};
//! Constructor
QwtWheel::QwtWheel( QWidget *parent ):
QWidget( parent )
15 years ago
{
d_data = new PrivateData;
setFocusPolicy( Qt::StrongFocus );
setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
setAttribute( Qt::WA_WState_OwnSizePolicy, false );
15 years ago
}
//! Destructor
QwtWheel::~QwtWheel()
15 years ago
{
delete d_data;
15 years ago
}
/*!
\brief En/Disable tracking
If tracking is enabled (the default), the wheel emits the valueChanged()
signal while the wheel is moving. If tracking is disabled, the wheel
emits the valueChanged() signal only when the wheel movement is terminated.
The wheelMoved() signal is emitted regardless id tracking is enabled or not.
\param enable On/Off
\sa isTracking()
*/
void QwtWheel::setTracking( bool enable )
15 years ago
{
d_data->tracking = enable;
}
15 years ago
/*!
\return True, when tracking is enabled
\sa setTracking(), valueChanged(), wheelMoved()
*/
bool QwtWheel::isTracking() const
{
return d_data->tracking;
}
15 years ago
/*!
\brief Specify the update interval when the wheel is flying
15 years ago
Default and minimum value is 50 ms.
15 years ago
\param interval Interval in milliseconds
\sa updateInterval(), setMass(), setTracking()
*/
void QwtWheel::setUpdateInterval( int interval )
{
d_data->updateInterval = qMax( interval, 50 );
15 years ago
}
/*!
\return Update interval when the wheel is flying
\sa setUpdateInterval(), mass(), isTracking()
*/
int QwtWheel::updateInterval() const
15 years ago
{
return d_data->updateInterval;
}
/*!
\brief Mouse press event handler
Start movement of the wheel.
\param event Mouse event
*/
void QwtWheel::mousePressEvent( QMouseEvent *event )
{
stopFlying();
d_data->isScrolling = wheelRect().contains( event->pos() );
if ( d_data->isScrolling )
{
d_data->time.start();
d_data->speed = 0.0;
d_data->mouseValue = valueAt( event->pos() );
d_data->mouseOffset = d_data->mouseValue - d_data->value;
d_data->pendingValueChanged = false;
Q_EMIT wheelPressed();
}
15 years ago
}
/*!
\brief Mouse Move Event handler
Turn the wheel according to the mouse position
\param event Mouse event
*/
void QwtWheel::mouseMoveEvent( QMouseEvent *event )
15 years ago
{
if ( !d_data->isScrolling )
15 years ago
return;
double mouseValue = valueAt( event->pos() );
if ( d_data->mass > 0.0 )
{
double ms = d_data->time.restart();
15 years ago
// the interval when mouse move events are posted are somehow
// random. To avoid unrealistic speed values we limit ms
15 years ago
ms = qMax( ms, 5.0 );
15 years ago
d_data->speed = ( mouseValue - d_data->mouseValue ) / ms;
}
d_data->mouseValue = mouseValue;
double value = boundedValue( mouseValue - d_data->mouseOffset );
if ( d_data->stepAlignment )
value = alignedValue( value );
if ( value != d_data->value )
{
d_data->value = value;
15 years ago
update();
Q_EMIT wheelMoved( d_data->value );
if ( d_data->tracking )
Q_EMIT valueChanged( d_data->value );
else
d_data->pendingValueChanged = true;
}
}
/*!
\brief Mouse Release Event handler
When the wheel has no mass the movement of the wheel stops, otherwise
it starts flying.
\param event Mouse event
*/
void QwtWheel::mouseReleaseEvent( QMouseEvent *event )
{
Q_UNUSED( event );
if ( !d_data->isScrolling )
return;
d_data->isScrolling = false;
bool startFlying = false;
if ( d_data->mass > 0.0 )
{
const int ms = d_data->time.elapsed();
if ( ( qFabs( d_data->speed ) > 0.0 ) && ( ms < 50 ) )
startFlying = true;
}
if ( startFlying )
{
d_data->flyingValue =
boundedValue( d_data->mouseValue - d_data->mouseOffset );
d_data->timerId = startTimer( d_data->updateInterval );
}
else
{
if ( d_data->pendingValueChanged )
Q_EMIT valueChanged( d_data->value );
}
d_data->pendingValueChanged = false;
d_data->mouseOffset = 0.0;
Q_EMIT wheelReleased();
}
/*!
\brief Qt timer event
15 years ago
The flying wheel effect is implemented using a timer
\param event Timer event
\sa updateInterval()
*/
void QwtWheel::timerEvent( QTimerEvent *event )
{
if ( event->timerId() != d_data->timerId )
{
QWidget::timerEvent( event );
return;
}
d_data->speed *= qExp( -d_data->updateInterval * 0.001 / d_data->mass );
d_data->flyingValue += d_data->speed * d_data->updateInterval;
d_data->flyingValue = boundedValue( d_data->flyingValue );
double value = d_data->flyingValue;
if ( d_data->stepAlignment )
value = alignedValue( value );
if ( qFabs( d_data->speed ) < 0.001 * d_data->singleStep )
{
// stop if d_data->speed < one step per second
stopFlying();
}
if ( value != d_data->value )
{
d_data->value = value;
update();
15 years ago
if ( d_data->tracking || d_data->timerId == 0 )
Q_EMIT valueChanged( d_data->value );
}
}
/*!
\brief Handle wheel events
In/Decrement the value
\param event Wheel event
*/
void QwtWheel::wheelEvent( QWheelEvent *event )
{
if ( !wheelRect().contains( event->pos() ) )
{
event->ignore();
return;
}
if ( d_data->isScrolling )
return;
stopFlying();
double increment = 0.0;
if ( ( event->modifiers() & Qt::ControlModifier) ||
( event->modifiers() & Qt::ShiftModifier ) )
{
// one page regardless of delta
increment = d_data->singleStep * d_data->pageStepCount;
if ( event->delta() < 0 )
increment = -increment;
}
else
{
const int numSteps = event->delta() / 120;
increment = d_data->singleStep * numSteps;
}
if ( d_data->orientation == Qt::Vertical && d_data->inverted )
increment = -increment;
double value = boundedValue( d_data->value + increment );
if ( d_data->stepAlignment )
value = alignedValue( value );
if ( value != d_data->value )
{
d_data->value = value;
update();
Q_EMIT valueChanged( d_data->value );
Q_EMIT wheelMoved( d_data->value );
}
}
/*!
Handle key events
- Qt::Key_Home\n
Step to minimum()
- Qt::Key_End\n
Step to maximum()
- Qt::Key_Up\n
In case of a horizontal or not inverted vertical wheel the value
will be incremented by the step size. For an inverted vertical wheel
the value will be decremented by the step size.
- Qt::Key_Down\n
In case of a horizontal or not inverted vertical wheel the value
will be decremented by the step size. For an inverted vertical wheel
the value will be incremented by the step size.
- Qt::Key_PageUp\n
The value will be incremented by pageStepSize() * singleStepSize().
- Qt::Key_PageDown\n
The value will be decremented by pageStepSize() * singleStepSize().
\param event Key event
*/
void QwtWheel::keyPressEvent( QKeyEvent *event )
{
if ( d_data->isScrolling )
{
// don't interfere mouse scrolling
return;
}
double value = d_data->value;
double increment = 0.0;
switch ( event->key() )
{
case Qt::Key_Down:
{
if ( d_data->orientation == Qt::Vertical && d_data->inverted )
increment = d_data->singleStep;
else
increment = -d_data->singleStep;
break;
15 years ago
}
case Qt::Key_Up:
{
if ( d_data->orientation == Qt::Vertical && d_data->inverted )
increment = -d_data->singleStep;
else
increment = d_data->singleStep;
break;
}
case Qt::Key_Left:
{
if ( d_data->orientation == Qt::Horizontal )
{
if ( d_data->inverted )
increment = d_data->singleStep;
else
increment = -d_data->singleStep;
}
break;
}
case Qt::Key_Right:
{
if ( d_data->orientation == Qt::Horizontal )
{
if ( d_data->inverted )
increment = -d_data->singleStep;
else
increment = d_data->singleStep;
}
break;
}
case Qt::Key_PageUp:
{
increment = d_data->pageStepCount * d_data->singleStep;
break;
}
case Qt::Key_PageDown:
{
increment = -d_data->pageStepCount * d_data->singleStep;
break;
}
case Qt::Key_Home:
{
value = d_data->minimum;
break;
}
case Qt::Key_End:
{
value = d_data->maximum;
break;
}
default:;
{
event->ignore();
}
}
if ( event->isAccepted() )
stopFlying();
if ( increment != 0.0 )
{
value = boundedValue( d_data->value + increment );
if ( d_data->stepAlignment )
value = alignedValue( value );
}
if ( value != d_data->value )
{
d_data->value = value;
update();
Q_EMIT valueChanged( d_data->value );
Q_EMIT wheelMoved( d_data->value );
15 years ago
}
}
/*!
\brief Adjust the number of grooves in the wheel's surface.
The number of grooves is limited to 6 <= count <= 50.
15 years ago
Values outside this range will be clipped.
The default value is 10.
\param count Number of grooves per 360 degrees
\sa tickCount()
15 years ago
*/
void QwtWheel::setTickCount( int count )
15 years ago
{
count = qBound( 6, count, 50 );
15 years ago
if ( count != d_data->tickCount )
{
d_data->tickCount = qBound( 6, count, 50 );
update();
}
15 years ago
}
/*!
\return Number of grooves in the wheel's surface.
\sa setTickCnt()
15 years ago
*/
int QwtWheel::tickCount() const
15 years ago
{
return d_data->tickCount;
15 years ago
}
/*!
\brief Set the wheel border width of the wheel.
15 years ago
The wheel border must not be smaller than 1
15 years ago
and is limited in dependence on the wheel's size.
Values outside the allowed range will be clipped.
The wheel border defaults to 2.
\param borderWidth Border width
\sa internalBorder()
15 years ago
*/
void QwtWheel::setWheelBorderWidth( int borderWidth )
15 years ago
{
const int d = qMin( width(), height() ) / 3;
borderWidth = qMin( borderWidth, d );
d_data->wheelBorderWidth = qMax( borderWidth, 1 );
update();
15 years ago
}
/*!
\return Wheel border width
\sa setWheelBorderWidth()
*/
int QwtWheel::wheelBorderWidth() const
15 years ago
{
return d_data->wheelBorderWidth;
15 years ago
}
/*!
\brief Set the border width
15 years ago
The border defaults to 2.
15 years ago
\param width Border width
\sa borderWidth()
*/
void QwtWheel::setBorderWidth( int width )
{
d_data->borderWidth = qMax( width, 0 );
update();
}
15 years ago
/*!
\return Border width
\sa setBorderWidth()
*/
int QwtWheel::borderWidth() const
{
return d_data->borderWidth;
15 years ago
}
/*!
\return Rectangle of the wheel without the outer border
*/
QRect QwtWheel::wheelRect() const
{
const int bw = d_data->borderWidth;
return contentsRect().adjusted( bw, bw, -bw, -bw );
}
15 years ago
/*!
\brief Set the total angle which the wheel can be turned.
One full turn of the wheel corresponds to an angle of
360 degrees. A total angle of n*360 degrees means
that the wheel has to be turned n times around its axis
to get from the minimum value to the maximum value.
The default setting of the total angle is 360 degrees.
15 years ago
\param angle total angle in degrees
\sa totalAngle()
15 years ago
*/
void QwtWheel::setTotalAngle( double angle )
15 years ago
{
if ( angle < 0.0 )
angle = 0.0;
d_data->totalAngle = angle;
update();
}
/*!
\return Total angle which the wheel can be turned.
\sa setTotalAngle()
*/
double QwtWheel::totalAngle() const
15 years ago
{
return d_data->totalAngle;
}
/*!
\brief Set the wheel's orientation.
The default orientation is Qt::Horizontal.
\param orientation Qt::Horizontal or Qt::Vertical.
\sa orientation()
15 years ago
*/
void QwtWheel::setOrientation( Qt::Orientation orientation )
15 years ago
{
if ( d_data->orientation == orientation )
15 years ago
return;
if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
15 years ago
{
QSizePolicy sp = sizePolicy();
sp.transpose();
setSizePolicy( sp );
15 years ago
setAttribute( Qt::WA_WState_OwnSizePolicy, false );
15 years ago
}
d_data->orientation = orientation;
update();
}
/*!
\return Orientation
\sa setOrientation()
*/
Qt::Orientation QwtWheel::orientation() const
{
return d_data->orientation;
15 years ago
}
/*!
\brief Specify the visible portion of the wheel.
You may use this function for fine-tuning the appearance of
the wheel. The default value is 175 degrees. The value is
limited from 10 to 175 degrees.
15 years ago
\param angle Visible angle in degrees
\sa viewAngle(), setTotalAngle()
15 years ago
*/
void QwtWheel::setViewAngle( double angle )
15 years ago
{
d_data->viewAngle = qBound( 10.0, angle, 175.0 );
15 years ago
update();
}
/*!
\return Visible portion of the wheel
\sa setViewAngle(), totalAngle()
*/
double QwtWheel::viewAngle() const
15 years ago
{
return d_data->viewAngle;
}
/*!
Determine the value corresponding to a specified point
\param pos Position
\return Value corresponding to pos
*/
double QwtWheel::valueAt( const QPoint &pos ) const
{
const QRectF rect = wheelRect();
double w, dx;
if ( d_data->orientation == Qt::Vertical )
{
w = rect.height();
dx = rect.top() - pos.y();
}
else
{
w = rect.width();
dx = pos.x() - rect.left();
}
if ( w == 0.0 )
return 0.0;
if ( d_data->inverted )
{
dx = w - dx;
}
// w pixels is an arc of viewAngle degrees,
// so we convert change in pixels to change in angle
const double ang = dx * d_data->viewAngle / w;
// value range maps to totalAngle degrees,
// so convert the change in angle to a change in value
const double val = ang * ( maximum() - minimum() ) / d_data->totalAngle;
return val;
}
/*!
\brief Qt Paint Event
\param event Paint event
*/
void QwtWheel::paintEvent( QPaintEvent *event )
{
QPainter painter( this );
painter.setClipRegion( event->region() );
QStyleOption opt;
opt.init(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
qDrawShadePanel( &painter,
contentsRect(), palette(), true, d_data->borderWidth );
drawWheelBackground( &painter, wheelRect() );
drawTicks( &painter, wheelRect() );
if ( hasFocus() )
QwtPainter::drawFocusRect( &painter, this );
}
/*!
Draw the Wheel's background gradient
\param painter Painter
\param rect Geometry for the wheel
*/
void QwtWheel::drawWheelBackground(
QPainter *painter, const QRectF &rect )
{
painter->save();
QPalette pal = palette();
// draw shaded background
QLinearGradient gradient( rect.topLeft(),
( d_data->orientation == Qt::Horizontal ) ? rect.topRight() : rect.bottomLeft() );
gradient.setColorAt( 0.0, pal.color( QPalette::Button ) );
gradient.setColorAt( 0.2, pal.color( QPalette::Midlight ) );
gradient.setColorAt( 0.7, pal.color( QPalette::Mid ) );
gradient.setColorAt( 1.0, pal.color( QPalette::Dark ) );
painter->fillRect( rect, gradient );
// draw internal border
const QPen lightPen( palette().color( QPalette::Light ),
d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
const QPen darkPen( pal.color( QPalette::Dark ),
d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
const double bw2 = 0.5 * d_data->wheelBorderWidth;
if ( d_data->orientation == Qt::Horizontal )
{
painter->setPen( lightPen );
painter->drawLine( QPointF( rect.left(), rect.top() + bw2 ),
QPointF( rect.right(), rect.top() + bw2 ) );
painter->setPen( darkPen );
painter->drawLine( QPointF( rect.left(), rect.bottom() - bw2 ),
QPointF( rect.right(), rect.bottom() - bw2 ) );
}
else // Qt::Vertical
{
painter->setPen( lightPen );
painter->drawLine( QPointF( rect.left() + bw2, rect.top() ),
QPointF( rect.left() + bw2, rect.bottom() ) );
painter->setPen( darkPen );
painter->drawLine( QPointF( rect.right() - bw2, rect.top() ),
QPointF( rect.right() - bw2, rect.bottom() ) );
}
painter->restore();
}
15 years ago
/*!
Draw the Wheel's ticks
\param painter Painter
\param rect Geometry for the wheel
15 years ago
*/
void QwtWheel::drawTicks( QPainter *painter, const QRectF &rect )
15 years ago
{
const double range = d_data->maximum - d_data->minimum;
15 years ago
if ( range == 0.0 || d_data->totalAngle == 0.0 )
{
15 years ago
return;
}
15 years ago
const QPen lightPen( palette().color( QPalette::Light ),
0, Qt::SolidLine, Qt::FlatCap );
const QPen darkPen( palette().color( QPalette::Dark ),
0, Qt::SolidLine, Qt::FlatCap );
15 years ago
const double cnvFactor = qAbs( d_data->totalAngle / range );
15 years ago
const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor;
const double loValue = value() - halfIntv;
const double hiValue = value() + halfIntv;
const double tickWidth = 360.0 / double( d_data->tickCount ) / cnvFactor;
const double sinArc = qFastSin( d_data->viewAngle * M_PI / 360.0 );
15 years ago
if ( d_data->orientation == Qt::Horizontal )
{
const double radius = rect.width() * 0.5;
15 years ago
double l1 = rect.top() + d_data->wheelBorderWidth;
double l2 = rect.bottom() - d_data->wheelBorderWidth - 1;
15 years ago
// draw one point over the border if border > 1
if ( d_data->wheelBorderWidth > 1 )
{
l1--;
l2++;
15 years ago
}
const double maxpos = rect.right() - 2;
const double minpos = rect.left() + 2;
15 years ago
// draw tick marks
for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth;
tickValue < hiValue; tickValue += tickWidth )
{
const double angle = qwtRadians( tickValue - value() );
const double s = qFastSin( angle * cnvFactor );
const double off = radius * ( sinArc + s ) / sinArc;
double tickPos;
if ( d_data->inverted )
tickPos = rect.left() + off;
else
tickPos = rect.right() - off;
if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
{
painter->setPen( darkPen );
painter->drawLine( QPointF( tickPos - 1 , l1 ),
QPointF( tickPos - 1, l2 ) );
painter->setPen( lightPen );
painter->drawLine( QPointF( tickPos, l1 ),
QPointF( tickPos, l2 ) );
15 years ago
}
}
}
else // Qt::Vertical
{
const double radius = rect.height() * 0.5;
15 years ago
double l1 = rect.left() + d_data->wheelBorderWidth;
double l2 = rect.right() - d_data->wheelBorderWidth - 1;
15 years ago
if ( d_data->wheelBorderWidth > 1 )
{
15 years ago
l1--;
l2++;
}
const double maxpos = rect.bottom() - 2;
const double minpos = rect.top() + 2;
15 years ago
for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth;
tickValue < hiValue; tickValue += tickWidth )
{
const double angle = qwtRadians( tickValue - value() );
const double s = qFastSin( angle * cnvFactor );
const double off = radius * ( sinArc + s ) / sinArc;
double tickPos;
if ( d_data->inverted )
tickPos = rect.bottom() - off;
else
tickPos = rect.top() + off;
if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
{
painter->setPen( darkPen );
painter->drawLine( QPointF( l1, tickPos - 1 ),
QPointF( l2, tickPos - 1 ) );
painter->setPen( lightPen );
painter->drawLine( QPointF( l1, tickPos ),
QPointF( l2, tickPos ) );
15 years ago
}
}
}
}
/*!
\brief Set the width of the wheel
Corresponds to the wheel height for horizontal orientation,
and the wheel width for vertical orientation.
15 years ago
\param width the wheel's width
\sa wheelWidth()
*/
void QwtWheel::setWheelWidth( int width )
15 years ago
{
d_data->wheelWidth = width;
update();
}
15 years ago
/*!
\return Width of the wheel
\sa setWheelWidth()
*/
int QwtWheel::wheelWidth() const
{
return d_data->wheelWidth;
}
15 years ago
/*!
\return a size hint
*/
QSize QwtWheel::sizeHint() const
{
const QSize hint = minimumSizeHint();
return hint.expandedTo( QApplication::globalStrut() );
}
15 years ago
/*!
\return Minimum size hint
\warning The return value is based on the wheel width.
*/
QSize QwtWheel::minimumSizeHint() const
{
QSize sz( 3 * d_data->wheelWidth + 2 * d_data->borderWidth,
d_data->wheelWidth + 2 * d_data->borderWidth );
if ( d_data->orientation != Qt::Horizontal )
sz.transpose();
return sz;
15 years ago
}
/*!
\brief Set the step size of the counter
A value <= 0.0 disables stepping
\param stepSize Single step size
\sa singleStep(), setPageStepCount()
*/
void QwtWheel::setSingleStep( double stepSize )
15 years ago
{
d_data->singleStep = qMax( stepSize, 0.0 );
15 years ago
}
/*!
\return Single step size
\sa setSingleStep()
*/
double QwtWheel::singleStep() const
15 years ago
{
return d_data->singleStep;
}
15 years ago
/*!
\brief En/Disable step alignment
When step alignment is enabled value changes initiated by
user input ( mouse, keyboard, wheel ) are aligned to
the multiples of the single step.
\param on On/Off
\sa stepAlignment(), setSingleStep()
*/
void QwtWheel::setStepAlignment( bool on )
{
if ( on != d_data->stepAlignment )
{
d_data->stepAlignment = on;
15 years ago
}
}
/*!
\return True, when the step alignment is enabled
\sa setStepAlignment(), singleStep()
*/
bool QwtWheel::stepAlignment() const
15 years ago
{
return d_data->stepAlignment;
15 years ago
}
/*!
\brief Set the page step count
pageStepCount is a multiplicator for the single step size
that typically corresponds to the user pressing PageUp or PageDown.
A value of 0 disables page stepping.
The default value is 1.
\param count Multiplicator for the single step size
\sa pageStepCount(), setSingleStep()
*/
void QwtWheel::setPageStepCount( int count )
15 years ago
{
d_data->pageStepCount = qMax( 0, count );
}
15 years ago
/*!
\return Page step count
\sa setPageStepCount(), singleStep()
*/
int QwtWheel::pageStepCount() const
{
return d_data->pageStepCount;
}
15 years ago
/*!
\brief Set the minimum and maximum values
The maximum is adjusted if necessary to ensure that the range remains valid.
The value might be modified to be inside of the range.
\param min Minimum value
\param max Maximum value
\sa minimum(), maximum()
*/
void QwtWheel::setRange( double min, double max )
{
max = qMax( min, max );
if ( d_data->minimum == min && d_data->maximum == max )
return;
d_data->minimum = min;
d_data->maximum = max;
if ( d_data->value < min || d_data->value > max )
{
d_data->value = qBound( min, d_data->value, max );
update();
Q_EMIT valueChanged( d_data->value );
}
15 years ago
}
/*!
Set the minimum value of the range
15 years ago
\param value Minimum value
\sa setRange(), setMaximum(), minimum()
\note The maximum is adjusted if necessary to ensure that the range remains valid.
*/
void QwtWheel::setMinimum( double value )
15 years ago
{
setRange( value, maximum() );
15 years ago
}
/*!
\return The minimum of the range
\sa setRange(), setMinimum(), maximum()
*/
double QwtWheel::minimum() const
{
return d_data->minimum;
}
15 years ago
/*!
Set the maximum value of the range
\param value Maximum value
\sa setRange(), setMinimum(), maximum()
15 years ago
*/
void QwtWheel::setMaximum( double value )
15 years ago
{
setRange( minimum(), value );
}
15 years ago
/*!
\return The maximum of the range
\sa setRange(), setMaximum(), minimum()
*/
double QwtWheel::maximum() const
{
return d_data->maximum;
15 years ago
}
/*!
\brief Set a new value without adjusting to the step raster
\param value New value
15 years ago
\sa value(), valueChanged()
\warning The value is clipped when it lies outside the range.
15 years ago
*/
void QwtWheel::setValue( double value )
15 years ago
{
stopFlying();
d_data->isScrolling = false;
value = qBound( d_data->minimum, value, d_data->maximum );
if ( d_data->value != value )
{
d_data->value = value;
update();
Q_EMIT valueChanged( d_data->value );
}
15 years ago
}
/*!
\return Current value of the wheel
\sa setValue(), valueChanged()
*/
double QwtWheel::value() const
{
return d_data->value;
}
15 years ago
/*!
\brief En/Disable inverted appearance
An inverted wheel increases its values in the opposite direction.
The direction of an inverted horizontal wheel will be from right to left
an inverted vertical wheel will increase from bottom to top.
\param on En/Disable inverted appearance
\sa isInverted()
*/
void QwtWheel::setInverted( bool on )
15 years ago
{
if ( d_data->inverted != on )
{
d_data->inverted = on;
update();
}
15 years ago
}
/*!
\return True, when the wheel is inverted
\sa setInverted()
*/
bool QwtWheel::isInverted() const
15 years ago
{
return d_data->inverted;
15 years ago
}
/*!
\brief En/Disable wrapping
If wrapping is true stepping up from maximum() value will take
you to the minimum() value and vice versa.
\param on En/Disable wrapping
\sa wrapping()
*/
void QwtWheel::setWrapping( bool on )
{
d_data->wrapping = on;
}
/*!
\return True, when wrapping is set
\sa setWrapping()
*/
bool QwtWheel::wrapping() const
{
return d_data->wrapping;
}
/*!
\brief Set the slider's mass for flywheel effect.
If the slider's mass is greater then 0, it will continue
to move after the mouse button has been released. Its speed
decreases with time at a rate depending on the slider's mass.
A large mass means that it will continue to move for a
long time.
Derived widgets may overload this function to make it public.
\param mass New mass in kg
\bug If the mass is smaller than 1g, it is set to zero.
The maximal mass is limited to 100kg.
\sa mass()
15 years ago
*/
void QwtWheel::setMass( double mass )
15 years ago
{
if ( mass < 0.001 )
{
d_data->mass = 0.0;
}
else
{
d_data->mass = qMin( 100.0, mass );
}
if ( d_data->mass <= 0.0 )
stopFlying();
15 years ago
}
/*!
\return mass
\sa setMass()
15 years ago
*/
double QwtWheel::mass() const
15 years ago
{
return d_data->mass;
}
//! Stop the flying movement of the wheel
void QwtWheel::stopFlying()
{
if ( d_data->timerId != 0 )
{
killTimer( d_data->timerId );
d_data->timerId = 0;
d_data->speed = 0.0;
}
}
double QwtWheel::boundedValue( double value ) const
{
const double range = d_data->maximum - d_data->minimum;
if ( d_data->wrapping && range >= 0.0 )
{
if ( value < d_data->minimum )
{
value += ::ceil( ( d_data->minimum - value ) / range ) * range;
}
else if ( value > d_data->maximum )
{
value -= ::ceil( ( value - d_data->maximum ) / range ) * range;
}
}
else
{
value = qBound( d_data->minimum, value, d_data->maximum );
}
return value;
}
double QwtWheel::alignedValue( double value ) const
{
const double stepSize = d_data->singleStep;
if ( stepSize > 0.0 )
{
value = d_data->minimum +
qRound( ( value - d_data->minimum ) / stepSize ) * stepSize;
if ( stepSize > 1e-12 )
{
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
{
// correct rounding error if value = 0
value = 0.0;
}
else if ( qFuzzyCompare( value, d_data->maximum ) )
{
// correct rounding error at the border
value = d_data->maximum;
}
}
}
return value;
15 years ago
}