Released version 6.1.3

This commit is contained in:
Wodann 2018-08-02 11:01:31 -04:00
commit a94503cb82
1885 changed files with 276310 additions and 0 deletions

View file

@ -0,0 +1,27 @@
#include "curvedata.h"
#include "signaldata.h"
const SignalData &CurveData::values() const
{
return SignalData::instance();
}
SignalData &CurveData::values()
{
return SignalData::instance();
}
QPointF CurveData::sample( size_t i ) const
{
return SignalData::instance().value( i );
}
size_t CurveData::size() const
{
return SignalData::instance().size();
}
QRectF CurveData::boundingRect() const
{
return SignalData::instance().boundingRect();
}

View file

@ -0,0 +1,16 @@
#include <qwt_series_data.h>
#include <qpointer.h>
class SignalData;
class CurveData: public QwtSeriesData<QPointF>
{
public:
const SignalData &values() const;
SignalData &values();
virtual QPointF sample( size_t i ) const;
virtual size_t size() const;
virtual QRectF boundingRect() const;
};

View file

@ -0,0 +1,95 @@
#include "knob.h"
#include <qwt_math.h>
#include <qpen.h>
#include <qwt_knob.h>
#include <qwt_round_scale_draw.h>
#include <qwt_scale_engine.h>
#include <qlabel.h>
#include <qevent.h>
Knob::Knob( const QString &title, double min, double max, QWidget *parent ):
QWidget( parent )
{
QFont font( "Helvetica", 10 );
d_knob = new QwtKnob( this );
d_knob->setFont( font );
QwtScaleDiv scaleDiv =
d_knob->scaleEngine()->divideScale( min, max, 5, 3 );
QList<double> ticks = scaleDiv.ticks( QwtScaleDiv::MajorTick );
if ( ticks.size() > 0 && ticks[0] > min )
{
if ( ticks.first() > min )
ticks.prepend( min );
if ( ticks.last() < max )
ticks.append( max );
}
scaleDiv.setTicks( QwtScaleDiv::MajorTick, ticks );
d_knob->setScale( scaleDiv );
d_knob->setKnobWidth( 50 );
font.setBold( true );
d_label = new QLabel( title, this );
d_label->setFont( font );
d_label->setAlignment( Qt::AlignTop | Qt::AlignHCenter );
setSizePolicy( QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding );
connect( d_knob, SIGNAL( valueChanged( double ) ),
this, SIGNAL( valueChanged( double ) ) );
}
QSize Knob::sizeHint() const
{
QSize sz1 = d_knob->sizeHint();
QSize sz2 = d_label->sizeHint();
const int w = qMax( sz1.width(), sz2.width() );
const int h = sz1.height() + sz2.height();
int off = qCeil( d_knob->scaleDraw()->extent( d_knob->font() ) );
off -= 15; // spacing
return QSize( w, h - off );
}
void Knob::setValue( double value )
{
d_knob->setValue( value );
}
double Knob::value() const
{
return d_knob->value();
}
void Knob::setTheme( const QColor &color )
{
d_knob->setPalette( color );
}
QColor Knob::theme() const
{
return d_knob->palette().color( QPalette::Window );
}
void Knob::resizeEvent( QResizeEvent *event )
{
const QSize sz = event->size();
const QSize hint = d_label->sizeHint();
d_label->setGeometry( 0, sz.height() - hint.height(),
sz.width(), hint.height() );
const int knobHeight = d_knob->sizeHint().height();
int off = qCeil( d_knob->scaleDraw()->extent( d_knob->font() ) );
off -= 15; // spacing
d_knob->setGeometry( 0, d_label->pos().y() - knobHeight + off,
sz.width(), knobHeight );
}

View file

@ -0,0 +1,38 @@
#ifndef _KNOB_H_
#define _KNOB_H_
#include <qwidget.h>
class QwtKnob;
class QLabel;
class Knob: public QWidget
{
Q_OBJECT
Q_PROPERTY( QColor theme READ theme WRITE setTheme )
public:
Knob( const QString &title,
double min, double max, QWidget *parent = NULL );
virtual QSize sizeHint() const;
void setValue( double value );
double value() const;
void setTheme( const QColor & );
QColor theme() const;
Q_SIGNALS:
double valueChanged( double );
protected:
virtual void resizeEvent( QResizeEvent * );
private:
QwtKnob *d_knob;
QLabel *d_label;
};
#endif

View file

@ -0,0 +1,36 @@
#include <qapplication.h>
#include "mainwindow.h"
#include "samplingthread.h"
int main( int argc, char **argv )
{
QApplication app( argc, argv );
app.setPalette( Qt::darkGray );
MainWindow window;
window.resize( 800, 400 );
SamplingThread samplingThread;
samplingThread.setFrequency( window.frequency() );
samplingThread.setAmplitude( window.amplitude() );
samplingThread.setInterval( window.signalInterval() );
window.connect( &window, SIGNAL( frequencyChanged( double ) ),
&samplingThread, SLOT( setFrequency( double ) ) );
window.connect( &window, SIGNAL( amplitudeChanged( double ) ),
&samplingThread, SLOT( setAmplitude( double ) ) );
window.connect( &window, SIGNAL( signalIntervalChanged( double ) ),
&samplingThread, SLOT( setInterval( double ) ) );
window.show();
samplingThread.start();
window.start();
bool ok = app.exec();
samplingThread.stop();
samplingThread.wait( 1000 );
return ok;
}

View file

@ -0,0 +1,69 @@
#include "mainwindow.h"
#include "plot.h"
#include "knob.h"
#include "wheelbox.h"
#include <qwt_scale_engine.h>
#include <qlabel.h>
#include <qlayout.h>
MainWindow::MainWindow( QWidget *parent ):
QWidget( parent )
{
const double intervalLength = 10.0; // seconds
d_plot = new Plot( this );
d_plot->setIntervalLength( intervalLength );
d_amplitudeKnob = new Knob( "Amplitude", 0.0, 200.0, this );
d_amplitudeKnob->setValue( 160.0 );
d_frequencyKnob = new Knob( "Frequency [Hz]", 0.1, 20.0, this );
d_frequencyKnob->setValue( 17.8 );
d_intervalWheel = new WheelBox( "Displayed [s]", 1.0, 100.0, 1.0, this );
d_intervalWheel->setValue( intervalLength );
d_timerWheel = new WheelBox( "Sample Interval [ms]", 0.0, 20.0, 0.1, this );
d_timerWheel->setValue( 10.0 );
QVBoxLayout* vLayout1 = new QVBoxLayout();
vLayout1->addWidget( d_intervalWheel );
vLayout1->addWidget( d_timerWheel );
vLayout1->addStretch( 10 );
vLayout1->addWidget( d_amplitudeKnob );
vLayout1->addWidget( d_frequencyKnob );
QHBoxLayout *layout = new QHBoxLayout( this );
layout->addWidget( d_plot, 10 );
layout->addLayout( vLayout1 );
connect( d_amplitudeKnob, SIGNAL( valueChanged( double ) ),
SIGNAL( amplitudeChanged( double ) ) );
connect( d_frequencyKnob, SIGNAL( valueChanged( double ) ),
SIGNAL( frequencyChanged( double ) ) );
connect( d_timerWheel, SIGNAL( valueChanged( double ) ),
SIGNAL( signalIntervalChanged( double ) ) );
connect( d_intervalWheel, SIGNAL( valueChanged( double ) ),
d_plot, SLOT( setIntervalLength( double ) ) );
}
void MainWindow::start()
{
d_plot->start();
}
double MainWindow::frequency() const
{
return d_frequencyKnob->value();
}
double MainWindow::amplitude() const
{
return d_amplitudeKnob->value();
}
double MainWindow::signalInterval() const
{
return d_timerWheel->value();
}

View file

@ -0,0 +1,32 @@
#include <qwidget.h>
class Plot;
class Knob;
class WheelBox;
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow( QWidget * = NULL );
void start();
double amplitude() const;
double frequency() const;
double signalInterval() const;
Q_SIGNALS:
void amplitudeChanged( double );
void frequencyChanged( double );
void signalIntervalChanged( double );
private:
Knob *d_frequencyKnob;
Knob *d_amplitudeKnob;
WheelBox *d_timerWheel;
WheelBox *d_intervalWheel;
Plot *d_plot;
};

View file

@ -0,0 +1,55 @@
MainWindow
{
border: 1px solid white;
border-radius: 20px;
padding: 10px;
background-color: qlineargradient( x1: 0, y1: 0, x2: 1, y2: 1,
stop: 0 #31312C, stop: 0.5 #808080 stop: 1 #31312C );
}
QwtPlotCanvas
{
border: 1px solid White;
border-radius: 10px;
background-color: #101010;
color: yellow; /* used as curve color */
}
QwtScaleWidget
{
color: white;
}
WheelBox
{
qproperty-theme: #878787;
}
QwtWheel
{
/* background-color: yellow; */
qproperty-mass: 0.0;
qproperty-tickCount: 5;
qproperty-wheelWidth: 15;
qproperty-borderWidth: 2;
qproperty-wheelBorderWidth: 2;
qproperty-wrapping: true;
}
Knob
{
qproperty-theme: #606060;
}
QwtKnob
{
qproperty-knobStyle: Sunken;
qproperty-markerStyle: Nub;
qproperty-markerSize: 8;
qproperty-borderWidth: 2;
}
QLCDNumber
{
color: yellow;
}

View file

@ -0,0 +1,31 @@
################################################################
# 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( $${PWD}/../examples.pri )
TARGET = oscilloscope
HEADERS = \
signaldata.h \
plot.h \
knob.h \
wheelbox.h \
samplingthread.h \
curvedata.h \
mainwindow.h
SOURCES = \
signaldata.cpp \
plot.cpp \
knob.cpp \
wheelbox.cpp \
samplingthread.cpp \
curvedata.cpp \
mainwindow.cpp \
main.cpp

View file

@ -0,0 +1,254 @@
#include "plot.h"
#include "curvedata.h"
#include "signaldata.h"
#include <qwt_plot_grid.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_directpainter.h>
#include <qwt_curve_fitter.h>
#include <qwt_painter.h>
#include <qevent.h>
class Canvas: public QwtPlotCanvas
{
public:
Canvas( QwtPlot *plot = NULL ):
QwtPlotCanvas( plot )
{
// The backing store is important, when working with widget
// overlays ( f.e rubberbands for zooming ).
// Here we don't have them and the internal
// backing store of QWidget is good enough.
setPaintAttribute( QwtPlotCanvas::BackingStore, false );
setBorderRadius( 10 );
if ( QwtPainter::isX11GraphicsSystem() )
{
#if QT_VERSION < 0x050000
// Even if not liked by the Qt development, Qt::WA_PaintOutsidePaintEvent
// works on X11. This has a nice effect on the performance.
setAttribute( Qt::WA_PaintOutsidePaintEvent, true );
#endif
// Disabling the backing store of Qt improves the performance
// for the direct painter even more, but the canvas becomes
// a native window of the window system, receiving paint events
// for resize and expose operations. Those might be expensive
// when there are many points and the backing store of
// the canvas is disabled. So in this application
// we better don't disable both backing stores.
if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) )
{
setAttribute( Qt::WA_PaintOnScreen, true );
setAttribute( Qt::WA_NoSystemBackground, true );
}
}
setupPalette();
}
private:
void setupPalette()
{
QPalette pal = palette();
#if QT_VERSION >= 0x040400
QLinearGradient gradient;
gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
gradient.setColorAt( 0.0, QColor( 0, 49, 110 ) );
gradient.setColorAt( 1.0, QColor( 0, 87, 174 ) );
pal.setBrush( QPalette::Window, QBrush( gradient ) );
#else
pal.setBrush( QPalette::Window, QBrush( color ) );
#endif
// QPalette::WindowText is used for the curve color
pal.setColor( QPalette::WindowText, Qt::green );
setPalette( pal );
}
};
Plot::Plot( QWidget *parent ):
QwtPlot( parent ),
d_paintedPoints( 0 ),
d_interval( 0.0, 10.0 ),
d_timerId( -1 )
{
d_directPainter = new QwtPlotDirectPainter();
setAutoReplot( false );
setCanvas( new Canvas() );
plotLayout()->setAlignCanvasToScales( true );
setAxisTitle( QwtPlot::xBottom, "Time [s]" );
setAxisScale( QwtPlot::xBottom, d_interval.minValue(), d_interval.maxValue() );
setAxisScale( QwtPlot::yLeft, -200.0, 200.0 );
QwtPlotGrid *grid = new QwtPlotGrid();
grid->setPen( Qt::gray, 0.0, Qt::DotLine );
grid->enableX( true );
grid->enableXMin( true );
grid->enableY( true );
grid->enableYMin( false );
grid->attach( this );
d_origin = new QwtPlotMarker();
d_origin->setLineStyle( QwtPlotMarker::Cross );
d_origin->setValue( d_interval.minValue() + d_interval.width() / 2.0, 0.0 );
d_origin->setLinePen( Qt::gray, 0.0, Qt::DashLine );
d_origin->attach( this );
d_curve = new QwtPlotCurve();
d_curve->setStyle( QwtPlotCurve::Lines );
d_curve->setPen( canvas()->palette().color( QPalette::WindowText ) );
d_curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
d_curve->setPaintAttribute( QwtPlotCurve::ClipPolygons, false );
d_curve->setData( new CurveData() );
d_curve->attach( this );
}
Plot::~Plot()
{
delete d_directPainter;
}
void Plot::start()
{
d_clock.start();
d_timerId = startTimer( 10 );
}
void Plot::replot()
{
CurveData *data = static_cast<CurveData *>( d_curve->data() );
data->values().lock();
QwtPlot::replot();
d_paintedPoints = data->size();
data->values().unlock();
}
void Plot::setIntervalLength( double interval )
{
if ( interval > 0.0 && interval != d_interval.width() )
{
d_interval.setMaxValue( d_interval.minValue() + interval );
setAxisScale( QwtPlot::xBottom,
d_interval.minValue(), d_interval.maxValue() );
replot();
}
}
void Plot::updateCurve()
{
CurveData *data = static_cast<CurveData *>( d_curve->data() );
data->values().lock();
const int numPoints = data->size();
if ( numPoints > d_paintedPoints )
{
const bool doClip = !canvas()->testAttribute( Qt::WA_PaintOnScreen );
if ( doClip )
{
/*
Depending on the platform setting a clip might be an important
performance issue. F.e. for Qt Embedded this reduces the
part of the backing store that has to be copied out - maybe
to an unaccelerated frame buffer device.
*/
const QwtScaleMap xMap = canvasMap( d_curve->xAxis() );
const QwtScaleMap yMap = canvasMap( d_curve->yAxis() );
QRectF br = qwtBoundingRect( *data,
d_paintedPoints - 1, numPoints - 1 );
const QRect clipRect = QwtScaleMap::transform( xMap, yMap, br ).toRect();
d_directPainter->setClipRegion( clipRect );
}
d_directPainter->drawSeries( d_curve,
d_paintedPoints - 1, numPoints - 1 );
d_paintedPoints = numPoints;
}
data->values().unlock();
}
void Plot::incrementInterval()
{
d_interval = QwtInterval( d_interval.maxValue(),
d_interval.maxValue() + d_interval.width() );
CurveData *data = static_cast<CurveData *>( d_curve->data() );
data->values().clearStaleValues( d_interval.minValue() );
// To avoid, that the grid is jumping, we disable
// the autocalculation of the ticks and shift them
// manually instead.
QwtScaleDiv scaleDiv = axisScaleDiv( QwtPlot::xBottom );
scaleDiv.setInterval( d_interval );
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
{
QList<double> ticks = scaleDiv.ticks( i );
for ( int j = 0; j < ticks.size(); j++ )
ticks[j] += d_interval.width();
scaleDiv.setTicks( i, ticks );
}
setAxisScaleDiv( QwtPlot::xBottom, scaleDiv );
d_origin->setValue( d_interval.minValue() + d_interval.width() / 2.0, 0.0 );
d_paintedPoints = 0;
replot();
}
void Plot::timerEvent( QTimerEvent *event )
{
if ( event->timerId() == d_timerId )
{
updateCurve();
const double elapsed = d_clock.elapsed() / 1000.0;
if ( elapsed > d_interval.maxValue() )
incrementInterval();
return;
}
QwtPlot::timerEvent( event );
}
void Plot::resizeEvent( QResizeEvent *event )
{
d_directPainter->reset();
QwtPlot::resizeEvent( event );
}
void Plot::showEvent( QShowEvent * )
{
replot();
}
bool Plot::eventFilter( QObject *object, QEvent *event )
{
if ( object == canvas() &&
event->type() == QEvent::PaletteChange )
{
d_curve->setPen( canvas()->palette().color( QPalette::WindowText ) );
}
return QwtPlot::eventFilter( object, event );
}

View file

@ -0,0 +1,44 @@
#include <qwt_plot.h>
#include <qwt_interval.h>
#include <qwt_system_clock.h>
class QwtPlotCurve;
class QwtPlotMarker;
class QwtPlotDirectPainter;
class Plot: public QwtPlot
{
Q_OBJECT
public:
Plot( QWidget * = NULL );
virtual ~Plot();
void start();
virtual void replot();
virtual bool eventFilter( QObject *, QEvent * );
public Q_SLOTS:
void setIntervalLength( double );
protected:
virtual void showEvent( QShowEvent * );
virtual void resizeEvent( QResizeEvent * );
virtual void timerEvent( QTimerEvent * );
private:
void updateCurve();
void incrementInterval();
QwtPlotMarker *d_origin;
QwtPlotCurve *d_curve;
int d_paintedPoints;
QwtPlotDirectPainter *d_directPainter;
QwtInterval d_interval;
int d_timerId;
QwtSystemClock d_clock;
};

View file

@ -0,0 +1,54 @@
#include "samplingthread.h"
#include "signaldata.h"
#include <qwt_math.h>
#include <math.h>
#if QT_VERSION < 0x040600
#define qFastSin(x) ::sin(x)
#endif
SamplingThread::SamplingThread( QObject *parent ):
QwtSamplingThread( parent ),
d_frequency( 5.0 ),
d_amplitude( 20.0 )
{
}
void SamplingThread::setFrequency( double frequency )
{
d_frequency = frequency;
}
double SamplingThread::frequency() const
{
return d_frequency;
}
void SamplingThread::setAmplitude( double amplitude )
{
d_amplitude = amplitude;
}
double SamplingThread::amplitude() const
{
return d_amplitude;
}
void SamplingThread::sample( double elapsed )
{
if ( d_frequency > 0.0 )
{
const QPointF s( elapsed, value( elapsed ) );
SignalData::instance().append( s );
}
}
double SamplingThread::value( double timeStamp ) const
{
const double period = 1.0 / d_frequency;
const double x = ::fmod( timeStamp, period );
const double v = d_amplitude * qFastSin( x / period * 2 * M_PI );
return v;
}

View file

@ -0,0 +1,25 @@
#include <qwt_sampling_thread.h>
class SamplingThread: public QwtSamplingThread
{
Q_OBJECT
public:
SamplingThread( QObject *parent = NULL );
double frequency() const;
double amplitude() const;
public Q_SLOTS:
void setAmplitude( double );
void setFrequency( double );
protected:
virtual void sample( double elapsed );
private:
virtual double value( double timeStamp ) const;
double d_frequency;
double d_amplitude;
};

View file

@ -0,0 +1,133 @@
#include "signaldata.h"
#include <qvector.h>
#include <qmutex.h>
#include <qreadwritelock.h>
class SignalData::PrivateData
{
public:
PrivateData():
boundingRect( 1.0, 1.0, -2.0, -2.0 ) // invalid
{
values.reserve( 1000 );
}
inline void append( const QPointF &sample )
{
values.append( sample );
// adjust the bounding rectangle
if ( boundingRect.width() < 0 || boundingRect.height() < 0 )
{
boundingRect.setRect( sample.x(), sample.y(), 0.0, 0.0 );
}
else
{
boundingRect.setRight( sample.x() );
if ( sample.y() > boundingRect.bottom() )
boundingRect.setBottom( sample.y() );
if ( sample.y() < boundingRect.top() )
boundingRect.setTop( sample.y() );
}
}
QReadWriteLock lock;
QVector<QPointF> values;
QRectF boundingRect;
QMutex mutex; // protecting pendingValues
QVector<QPointF> pendingValues;
};
SignalData::SignalData()
{
d_data = new PrivateData();
}
SignalData::~SignalData()
{
delete d_data;
}
int SignalData::size() const
{
return d_data->values.size();
}
QPointF SignalData::value( int index ) const
{
return d_data->values[index];
}
QRectF SignalData::boundingRect() const
{
return d_data->boundingRect;
}
void SignalData::lock()
{
d_data->lock.lockForRead();
}
void SignalData::unlock()
{
d_data->lock.unlock();
}
void SignalData::append( const QPointF &sample )
{
d_data->mutex.lock();
d_data->pendingValues += sample;
const bool isLocked = d_data->lock.tryLockForWrite();
if ( isLocked )
{
const int numValues = d_data->pendingValues.size();
const QPointF *pendingValues = d_data->pendingValues.data();
for ( int i = 0; i < numValues; i++ )
d_data->append( pendingValues[i] );
d_data->pendingValues.clear();
d_data->lock.unlock();
}
d_data->mutex.unlock();
}
void SignalData::clearStaleValues( double limit )
{
d_data->lock.lockForWrite();
d_data->boundingRect = QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid
const QVector<QPointF> values = d_data->values;
d_data->values.clear();
d_data->values.reserve( values.size() );
int index;
for ( index = values.size() - 1; index >= 0; index-- )
{
if ( values[index].x() < limit )
break;
}
if ( index > 0 )
d_data->append( values[index++] );
while ( index < values.size() - 1 )
d_data->append( values[index++] );
d_data->lock.unlock();
}
SignalData &SignalData::instance()
{
static SignalData valueVector;
return valueVector;
}

View file

@ -0,0 +1,33 @@
#ifndef _SIGNAL_DATA_H_
#define _SIGNAL_DATA_H_ 1
#include <qrect.h>
class SignalData
{
public:
static SignalData &instance();
void append( const QPointF &pos );
void clearStaleValues( double min );
int size() const;
QPointF value( int index ) const;
QRectF boundingRect() const;
void lock();
void unlock();
private:
SignalData();
SignalData( const SignalData & );
SignalData &operator=( const SignalData & );
virtual ~SignalData();
class PrivateData;
PrivateData *d_data;
};
#endif

View file

@ -0,0 +1,102 @@
#include "wheelbox.h"
#include <qwt_wheel.h>
#include <qlcdnumber.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qevent.h>
#include <qapplication.h>
class Wheel: public QwtWheel
{
public:
Wheel( WheelBox *parent ):
QwtWheel( parent )
{
setFocusPolicy( Qt::WheelFocus );
parent->installEventFilter( this );
}
virtual bool eventFilter( QObject *object, QEvent *event )
{
if ( event->type() == QEvent::Wheel )
{
const QWheelEvent *we = static_cast<QWheelEvent *>( event );
QWheelEvent wheelEvent( QPoint( 5, 5 ), we->delta(),
we->buttons(), we->modifiers(),
we->orientation() );
QApplication::sendEvent( this, &wheelEvent );
return true;
}
return QwtWheel::eventFilter( object, event );
}
};
WheelBox::WheelBox( const QString &title,
double min, double max, double stepSize, QWidget *parent ):
QWidget( parent )
{
d_number = new QLCDNumber( this );
d_number->setSegmentStyle( QLCDNumber::Filled );
d_number->setAutoFillBackground( true );
d_number->setFixedHeight( d_number->sizeHint().height() * 2 );
d_number->setFocusPolicy( Qt::WheelFocus );
QPalette pal( Qt::black );
pal.setColor( QPalette::WindowText, Qt::green );
d_number->setPalette( pal );
d_wheel = new Wheel( this );
d_wheel->setOrientation( Qt::Vertical );
d_wheel->setInverted( true );
d_wheel->setRange( min, max );
d_wheel->setSingleStep( stepSize );
d_wheel->setPageStepCount( 5 );
d_wheel->setFixedHeight( d_number->height() );
d_number->setFocusProxy( d_wheel );
QFont font( "Helvetica", 10 );
font.setBold( true );
d_label = new QLabel( title, this );
d_label->setFont( font );
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->setContentsMargins( 0, 0, 0, 0 );
hLayout->setSpacing( 2 );
hLayout->addWidget( d_number, 10 );
hLayout->addWidget( d_wheel );
QVBoxLayout *vLayout = new QVBoxLayout( this );
vLayout->addLayout( hLayout, 10 );
vLayout->addWidget( d_label, 0, Qt::AlignTop | Qt::AlignHCenter );
connect( d_wheel, SIGNAL( valueChanged( double ) ),
d_number, SLOT( display( double ) ) );
connect( d_wheel, SIGNAL( valueChanged( double ) ),
this, SIGNAL( valueChanged( double ) ) );
}
void WheelBox::setTheme( const QColor &color )
{
d_wheel->setPalette( color );
}
QColor WheelBox::theme() const
{
return d_wheel->palette().color( QPalette::Window );
}
void WheelBox::setValue( double value )
{
d_wheel->setValue( value );
d_number->display( value );
}
double WheelBox::value() const
{
return d_wheel->value();
}

View file

@ -0,0 +1,40 @@
#ifndef _WHEELBOX_H_
#define _WHEELBOX_H_
#include <qwidget.h>
class QwtWheel;
class QLabel;
class QLCDNumber;
class WheelBox: public QWidget
{
Q_OBJECT
Q_PROPERTY( QColor theme READ theme WRITE setTheme )
public:
WheelBox( const QString &title,
double min, double max, double stepSize,
QWidget *parent = NULL );
void setTheme( const QColor & );
QColor theme() const;
void setUnit( const QString & );
QString unit() const;
void setValue( double value );
double value() const;
Q_SIGNALS:
double valueChanged( double );
private:
QLCDNumber *d_number;
QwtWheel *d_wheel;
QLabel *d_label;
QString d_unit;
};
#endif