新增qwt源码版本

master
feiyangqingyun 2019-11-07 10:55:57 +08:00
parent 80d4725cd9
commit 73422ddce9
377 changed files with 81225 additions and 1 deletions

View File

@ -23,4 +23,5 @@
| 20 | maskwidget | 遮罩层窗体 | | 20 | maskwidget | 遮罩层窗体 |
| 21 | battery | 电池电量控件 | | 21 | battery | 电池电量控件 |
| 22 | lineeditnext | 文本框回车焦点下移 | | 22 | lineeditnext | 文本框回车焦点下移 |
| 23 | zhtopy | 汉字转拼音 | | 23 | zhtopy | 汉字转拼音 |
| 24 | qwtdemo | qwt的源码版本无需插件直接源码集成到你的项目即可 |

View File

@ -0,0 +1,15 @@
TARGET = animation
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
SOURCES += main.cpp
SOURCES += plot.cpp
HEADERS += plot.h
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,46 @@
#include <qapplication.h>
#include "plot.h"
#ifndef QWT_NO_OPENGL
#define USE_OPENGL 1
#endif
#if USE_OPENGL
#include <qgl.h>
#include <qwt_plot_glcanvas.h>
#else
#include <qwt_plot_canvas.h>
#endif
int main ( int argc, char **argv )
{
#if USE_OPENGL
#if QT_VERSION >= 0x040600 && QT_VERSION < 0x050000
// on my box QPaintEngine::OpenGL2 has serious problems, f.e:
// the lines of a simple drawRect are wrong.
QGL::setPreferredPaintEngine( QPaintEngine::OpenGL );
#endif
#endif
QApplication a( argc, argv );
Plot plot;
#if USE_OPENGL
QwtPlotGLCanvas *canvas = new QwtPlotGLCanvas();
canvas->setFrameStyle( QwtPlotGLCanvas::NoFrame );
#else
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setFrameStyle( QFrame::NoFrame );
canvas->setPaintAttribute( QwtPlotCanvas::BackingStore, false );
#endif
plot.setCanvas( canvas );
plot.setCanvasBackground( QColor( 30, 30, 50 ) );
plot.resize( 400, 400 );
plot.show();
return a.exec();
}

View File

@ -0,0 +1,241 @@
#include <qapplication.h>
#include <qwt_math.h>
#include <qwt_symbol.h>
#include <qwt_curve_fitter.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_layout.h>
#include <qevent.h>
#include "plot.h"
class Curve: public QwtPlotCurve
{
public:
void setTransformation( const QTransform &transform )
{
d_transform = transform;
}
virtual void updateSamples( double phase )
{
setSamples( d_transform.map( points( phase ) ) );
}
private:
virtual QPolygonF points( double phase ) const = 0;
private:
QTransform d_transform;
};
class Curve1: public Curve
{
public:
Curve1()
{
setPen( QColor( 150, 150, 200 ), 2 );
setStyle( QwtPlotCurve::Lines );
QwtSplineCurveFitter *curveFitter = new QwtSplineCurveFitter();
curveFitter->setSplineSize( 150 );
setCurveFitter( curveFitter );
setCurveAttribute( QwtPlotCurve::Fitted, true );
QwtSymbol *symbol = new QwtSymbol( QwtSymbol::XCross );
symbol->setPen( Qt::yellow );
symbol->setSize( 7 );
setSymbol( symbol );
// somewhere to the left
QTransform transform;
transform.scale( 1.5, 1.0 );
transform.translate( 1.5, 3.0 );
setTransformation( transform );
}
virtual QPolygonF points( double phase ) const
{
QPolygonF points;
const int numSamples = 15;
for ( int i = 0; i < numSamples; i++ )
{
const double v = 6.28 * double( i ) / double( numSamples - 1 );
points += QPointF( qSin( v - phase ), v );
}
return points;
}
};
class Curve2: public Curve
{
public:
Curve2()
{
setStyle( QwtPlotCurve::Sticks );
setPen( QColor( 200, 150, 50 ) );
setSymbol( new QwtSymbol( QwtSymbol::Ellipse,
QColor( Qt::gray ), QColor( Qt::yellow ), QSize( 5, 5 ) ) );
}
private:
virtual QPolygonF points( double phase ) const
{
QPolygonF points;
const int numSamples = 50;
for ( int i = 0; i < numSamples; i++ )
{
const double v = 10.0 * i / double( numSamples - 1 );
points += QPointF( v, qCos( 3.0 * ( v + phase ) ) );
}
return points;
}
};
class Curve3: public Curve
{
public:
Curve3()
{
setStyle( QwtPlotCurve::Lines );
setPen( QColor( 100, 200, 150 ), 2 );
QwtSplineCurveFitter* curveFitter = new QwtSplineCurveFitter();
curveFitter->setFitMode( QwtSplineCurveFitter::ParametricSpline );
curveFitter->setSplineSize( 200 );
setCurveFitter( curveFitter );
setCurveAttribute( QwtPlotCurve::Fitted, true );
// somewhere in the top right corner
QTransform transform;
transform.translate( 7.0, 7.5 );
transform.scale( 2.0, 2.0 );
setTransformation( transform );
}
private:
virtual QPolygonF points( double phase ) const
{
QPolygonF points;
const int numSamples = 9;
for ( int i = 0; i < numSamples; i++ )
{
const double v = i * 2.0 * M_PI / ( numSamples - 1 );
points += QPointF( qSin( v - phase ), qCos( 3.0 * ( v + phase ) ) );
}
return points;
}
};
class Curve4: public Curve
{
public:
Curve4()
{
setStyle( QwtPlotCurve::Lines );
setPen( Qt::red, 2 );
initSamples();
// somewhere in the center
QTransform transform;
transform.translate( 7.0, 3.0 );
transform.scale( 1.5, 1.5 );
setTransformation( transform );
}
private:
virtual QPolygonF points( double phase ) const
{
const double speed = 0.05;
const double s = speed * qSin( phase );
const double c = qSqrt( 1.0 - s * s );
for ( int i = 0; i < d_points.size(); i++ )
{
const QPointF p = d_points[i];
const double u = p.x();
const double v = p.y();
d_points[i].setX( u * c - v * s );
d_points[i].setY( v * c + u * s );
}
return d_points;
}
void initSamples()
{
const int numSamples = 15;
for ( int i = 0; i < numSamples; i++ )
{
const double angle = i * ( 2.0 * M_PI / ( numSamples - 1 ) );
QPointF p( qCos( angle ), qSin( angle ) );
if ( i % 2 )
p *= 0.4;
d_points += p;
}
}
private:
mutable QPolygonF d_points;
};
Plot::Plot( QWidget *parent ):
QwtPlot( parent)
{
setAutoReplot( false );
setTitle( "Animated Curves" );
// hide all axes
for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
enableAxis( axis, false );
plotLayout()->setCanvasMargin( 10 );
d_curves[0] = new Curve1();
d_curves[1] = new Curve2();
d_curves[2] = new Curve3();
d_curves[3] = new Curve4();
updateCurves();
for ( int i = 0; i < CurveCount; i++ )
d_curves[i]->attach( this );
d_time.start();
( void )startTimer( 40 );
}
void Plot::timerEvent( QTimerEvent * )
{
updateCurves();
replot();
}
void Plot::updateCurves()
{
const double speed = 2 * M_PI / 25000.0; // a cycle every 25 seconds
const double phase = d_time.elapsed() * speed;
for ( int i = 0; i < CurveCount; i++ )
d_curves[i]->updateSamples( phase );
}

View File

@ -0,0 +1,21 @@
#include <qwt_plot.h>
#include <qdatetime.h>
class Curve;
class Plot: public QwtPlot
{
public:
Plot( QWidget * = NULL);
protected:
virtual void timerEvent( QTimerEvent * );
private:
void updateCurves();
enum { CurveCount = 4 };
Curve *d_curves[CurveCount];
QTime d_time;
};

View File

@ -0,0 +1,132 @@
#include "barchart.h"
#include <qwt_plot_renderer.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_multi_barchart.h>
#include <qwt_column_symbol.h>
#include <qwt_plot_layout.h>
#include <qwt_legend.h>
#include <qwt_scale_draw.h>
BarChart::BarChart( QWidget *parent ):
QwtPlot( parent )
{
setAutoFillBackground( true );
setPalette( Qt::white );
canvas()->setPalette( QColor( "LemonChiffon" ) );
setTitle( "Bar Chart" );
setAxisTitle( QwtPlot::yLeft, "Whatever" );
setAxisTitle( QwtPlot::xBottom, "Whatever" );
d_barChartItem = new QwtPlotMultiBarChart( "Bar Chart " );
d_barChartItem->setLayoutPolicy( QwtPlotMultiBarChart::AutoAdjustSamples );
d_barChartItem->setSpacing( 20 );
d_barChartItem->setMargin( 3 );
d_barChartItem->attach( this );
insertLegend( new QwtLegend() );
populate();
setOrientation( 0 );
setAutoReplot( true );
}
void BarChart::populate()
{
static const char *colors[] = { "DarkOrchid", "SteelBlue", "Gold" };
const int numSamples = 5;
const int numBars = sizeof( colors ) / sizeof( colors[0] );
QList<QwtText> titles;
for ( int i = 0; i < numBars; i++ )
{
QString title("Bar %1");
titles += title.arg( i );
}
d_barChartItem->setBarTitles( titles );
d_barChartItem->setLegendIconSize( QSize( 10, 14 ) );
for ( int i = 0; i < numBars; i++ )
{
QwtColumnSymbol *symbol = new QwtColumnSymbol( QwtColumnSymbol::Box );
symbol->setLineWidth( 2 );
symbol->setFrameStyle( QwtColumnSymbol::Raised );
symbol->setPalette( QPalette( colors[i] ) );
d_barChartItem->setSymbol( i, symbol );
}
QVector< QVector<double> > series;
for ( int i = 0; i < numSamples; i++ )
{
QVector<double> values;
for ( int j = 0; j < numBars; j++ )
values += ( 2 + qrand() % 8 );
series += values;
}
d_barChartItem->setSamples( series );
}
void BarChart::setMode( int mode )
{
if ( mode == 0 )
{
d_barChartItem->setStyle( QwtPlotMultiBarChart::Grouped );
}
else
{
d_barChartItem->setStyle( QwtPlotMultiBarChart::Stacked );
}
}
void BarChart::setOrientation( int orientation )
{
QwtPlot::Axis axis1, axis2;
if ( orientation == 0 )
{
axis1 = QwtPlot::xBottom;
axis2 = QwtPlot::yLeft;
d_barChartItem->setOrientation( Qt::Vertical );
}
else
{
axis1 = QwtPlot::yLeft;
axis2 = QwtPlot::xBottom;
d_barChartItem->setOrientation( Qt::Horizontal );
}
setAxisScale( axis1, 0, d_barChartItem->dataSize() - 1, 1.0 );
setAxisAutoScale( axis2 );
QwtScaleDraw *scaleDraw1 = axisScaleDraw( axis1 );
scaleDraw1->enableComponent( QwtScaleDraw::Backbone, false );
scaleDraw1->enableComponent( QwtScaleDraw::Ticks, false );
QwtScaleDraw *scaleDraw2 = axisScaleDraw( axis2 );
scaleDraw2->enableComponent( QwtScaleDraw::Backbone, true );
scaleDraw2->enableComponent( QwtScaleDraw::Ticks, true );
plotLayout()->setAlignCanvasToScale( axis1, true );
plotLayout()->setAlignCanvasToScale( axis2, false );
plotLayout()->setCanvasMargin( 0 );
updateCanvasMargins();
replot();
}
void BarChart::exportChart()
{
QwtPlotRenderer renderer;
renderer.exportTo( this, "barchart.pdf" );
}

View File

@ -0,0 +1,25 @@
#ifndef _BAR_CHART_H_
#include <qwt_plot.h>
class QwtPlotMultiBarChart;
class BarChart: public QwtPlot
{
Q_OBJECT
public:
BarChart( QWidget * = NULL );
public Q_SLOTS:
void setMode( int );
void setOrientation( int );
void exportChart();
private:
void populate();
QwtPlotMultiBarChart *d_barChartItem;
};
#endif

View File

@ -0,0 +1,15 @@
TARGET = barchart
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
SOURCES += main.cpp
SOURCES += barchart.cpp
HEADERS += barchart.h
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,64 @@
#include <qapplication.h>
#include <qmainwindow.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qcombobox.h>
#include "barchart.h"
class MainWindow: public QMainWindow
{
public:
MainWindow( QWidget * = NULL );
private:
BarChart *d_chart;
};
MainWindow::MainWindow( QWidget *parent ):
QMainWindow( parent )
{
d_chart = new BarChart( this );
setCentralWidget( d_chart );
QToolBar *toolBar = new QToolBar( this );
QComboBox *typeBox = new QComboBox( toolBar );
typeBox->addItem( "Grouped" );
typeBox->addItem( "Stacked" );
typeBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
QComboBox *orientationBox = new QComboBox( toolBar );
orientationBox->addItem( "Vertical" );
orientationBox->addItem( "Horizontal" );
orientationBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
QToolButton *btnExport = new QToolButton( toolBar );
btnExport->setText( "Export" );
btnExport->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
connect( btnExport, SIGNAL( clicked() ), d_chart, SLOT( exportChart() ) );
toolBar->addWidget( typeBox );
toolBar->addWidget( orientationBox );
toolBar->addWidget( btnExport );
addToolBar( toolBar );
d_chart->setMode( typeBox->currentIndex() );
connect( typeBox, SIGNAL( currentIndexChanged( int ) ),
d_chart, SLOT( setMode( int ) ) );
d_chart->setOrientation( orientationBox->currentIndex() );
connect( orientationBox, SIGNAL( currentIndexChanged( int ) ),
d_chart, SLOT( setOrientation( int ) ) );
}
int main( int argc, char **argv )
{
QApplication a( argc, argv );
MainWindow mainWindow;
mainWindow.resize( 600, 400 );
mainWindow.show();
return a.exec();
}

View File

@ -0,0 +1,19 @@
TARGET = bode
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
SOURCES += main.cpp
SOURCES += plot.cpp
SOURCES += mainwindow.cpp
HEADERS += plot.h
HEADERS += mainwindow.h
HEADERS += complexnumber.h
HEADERS += pixmaps.h
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,83 @@
#ifndef _COMPLEX_NUMBER_H_
#define _COMPLEX_NUMBER_H_
#include <math.h>
class ComplexNumber
{
public:
ComplexNumber() ;
ComplexNumber( double r, double i = 0.0 );
double real() const;
double imag() const;
friend ComplexNumber operator*(
const ComplexNumber &, const ComplexNumber & );
friend ComplexNumber operator+(
const ComplexNumber &, const ComplexNumber & );
friend ComplexNumber operator-(
const ComplexNumber &, const ComplexNumber & );
friend ComplexNumber operator/(
const ComplexNumber &, const ComplexNumber & );
private:
double d_real;
double d_imag;
};
inline ComplexNumber::ComplexNumber():
d_real( 0.0 ),
d_imag( -0.0 )
{
}
inline ComplexNumber::ComplexNumber( double re, double im ):
d_real( re ),
d_imag( im )
{
}
inline double ComplexNumber::real() const
{
return d_real;
}
inline double ComplexNumber::imag() const
{
return d_imag;
}
inline ComplexNumber operator+(
const ComplexNumber &x1, const ComplexNumber &x2 )
{
return ComplexNumber( x1.d_real + x2.d_real, x1.d_imag + x2.d_imag );
}
inline ComplexNumber operator-(
const ComplexNumber &x1, const ComplexNumber &x2 )
{
return ComplexNumber( x1.d_real - x2.d_real, x1.d_imag - x2.d_imag );
}
inline ComplexNumber operator*(
const ComplexNumber &x1, const ComplexNumber &x2 )
{
return ComplexNumber( x1.d_real * x2.d_real - x1.d_imag * x2.d_imag,
x1.d_real * x2.d_imag + x2.d_real * x1.d_imag );
}
inline ComplexNumber operator/(
const ComplexNumber &x1, const ComplexNumber &x2 )
{
double denom = x2.d_real * x2.d_real + x2.d_imag * x2.d_imag;
return ComplexNumber(
( x1.d_real * x2.d_real + x1.d_imag * x2.d_imag ) / denom,
( x1.d_imag * x2.d_real - x2.d_imag * x1.d_real ) / denom
);
}
#endif

View File

@ -0,0 +1,13 @@
#include <qapplication.h>
#include "mainwindow.h"
int main ( int argc, char **argv )
{
QApplication a( argc, argv );
MainWindow w;
w.resize( 540, 400 );
w.show();
return a.exec();
}

View File

@ -0,0 +1,231 @@
#include <qregexp.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qstatusbar.h>
#include <qprinter.h>
#include <qpicture.h>
#include <qpainter.h>
#include <qprintdialog.h>
#include <qwt_counter.h>
#include <qwt_picker_machine.h>
#include <qwt_plot_zoomer.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_renderer.h>
#include <qwt_text.h>
#include <qwt_math.h>
#include "pixmaps.h"
#include "plot.h"
#include "mainwindow.h"
class Zoomer: public QwtPlotZoomer
{
public:
Zoomer( int xAxis, int yAxis, QWidget *canvas ):
QwtPlotZoomer( xAxis, yAxis, canvas )
{
setTrackerMode( QwtPicker::AlwaysOff );
setRubberBand( QwtPicker::NoRubberBand );
// RightButton: zoom out by 1
// Ctrl+RightButton: zoom out to full size
setMousePattern( QwtEventPattern::MouseSelect2,
Qt::RightButton, Qt::ControlModifier );
setMousePattern( QwtEventPattern::MouseSelect3,
Qt::RightButton );
}
};
//-----------------------------------------------------------------
//
// bode.cpp -- A demo program featuring QwtPlot and QwtCounter
//
// This example demonstrates the mapping of different curves
// to different axes in a QwtPlot widget. It also shows how to
// display the cursor position and how to implement zooming.
//
//-----------------------------------------------------------------
MainWindow::MainWindow( QWidget *parent ):
QMainWindow( parent )
{
d_plot = new Plot( this );
const int margin = 5;
d_plot->setContentsMargins( margin, margin, margin, 0 );
setContextMenuPolicy( Qt::NoContextMenu );
d_zoomer[0] = new Zoomer( QwtPlot::xBottom, QwtPlot::yLeft,
d_plot->canvas() );
d_zoomer[0]->setRubberBand( QwtPicker::RectRubberBand );
d_zoomer[0]->setRubberBandPen( QColor( Qt::green ) );
d_zoomer[0]->setTrackerMode( QwtPicker::ActiveOnly );
d_zoomer[0]->setTrackerPen( QColor( Qt::white ) );
d_zoomer[1] = new Zoomer( QwtPlot::xTop, QwtPlot::yRight,
d_plot->canvas() );
d_panner = new QwtPlotPanner( d_plot->canvas() );
d_panner->setMouseButton( Qt::MidButton );
d_picker = new QwtPlotPicker( QwtPlot::xBottom, QwtPlot::yLeft,
QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn,
d_plot->canvas() );
d_picker->setStateMachine( new QwtPickerDragPointMachine() );
d_picker->setRubberBandPen( QColor( Qt::green ) );
d_picker->setRubberBand( QwtPicker::CrossRubberBand );
d_picker->setTrackerPen( QColor( Qt::white ) );
setCentralWidget( d_plot );
QToolBar *toolBar = new QToolBar( this );
QToolButton *btnZoom = new QToolButton( toolBar );
btnZoom->setText( "Zoom" );
btnZoom->setIcon( QPixmap( zoom_xpm ) );
btnZoom->setCheckable( true );
btnZoom->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
toolBar->addWidget( btnZoom );
connect( btnZoom, SIGNAL( toggled( bool ) ), SLOT( enableZoomMode( bool ) ) );
#ifndef QT_NO_PRINTER
QToolButton *btnPrint = new QToolButton( toolBar );
btnPrint->setText( "Print" );
btnPrint->setIcon( QPixmap( print_xpm ) );
btnPrint->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
toolBar->addWidget( btnPrint );
connect( btnPrint, SIGNAL( clicked() ), SLOT( print() ) );
#endif
QToolButton *btnExport = new QToolButton( toolBar );
btnExport->setText( "Export" );
btnExport->setIcon( QPixmap( print_xpm ) );
btnExport->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
toolBar->addWidget( btnExport );
connect( btnExport, SIGNAL( clicked() ), SLOT( exportDocument() ) );
toolBar->addSeparator();
QWidget *hBox = new QWidget( toolBar );
QHBoxLayout *layout = new QHBoxLayout( hBox );
layout->setSpacing( 0 );
layout->addWidget( new QWidget( hBox ), 10 ); // spacer
layout->addWidget( new QLabel( "Damping Factor", hBox ), 0 );
layout->addSpacing( 10 );
QwtCounter *cntDamp = new QwtCounter( hBox );
cntDamp->setRange( 0.0, 5.0 );
cntDamp->setSingleStep( 0.01 );
cntDamp->setValue( 0.0 );
layout->addWidget( cntDamp, 0 );
( void )toolBar->addWidget( hBox );
addToolBar( toolBar );
#ifndef QT_NO_STATUSBAR
( void )statusBar();
#endif
enableZoomMode( false );
showInfo();
connect( cntDamp, SIGNAL( valueChanged( double ) ),
d_plot, SLOT( setDamp( double ) ) );
connect( d_picker, SIGNAL( moved( const QPoint & ) ),
SLOT( moved( const QPoint & ) ) );
connect( d_picker, SIGNAL( selected( const QPolygon & ) ),
SLOT( selected( const QPolygon & ) ) );
}
#ifndef QT_NO_PRINTER
void MainWindow::print()
{
QPrinter printer( QPrinter::HighResolution );
QString docName = d_plot->title().text();
if ( !docName.isEmpty() )
{
docName.replace ( QRegExp ( QString::fromLatin1 ( "\n" ) ), tr ( " -- " ) );
printer.setDocName ( docName );
}
printer.setCreator( "Bode example" );
printer.setOrientation( QPrinter::Landscape );
QPrintDialog dialog( &printer );
if ( dialog.exec() )
{
QwtPlotRenderer renderer;
if ( printer.colorMode() == QPrinter::GrayScale )
{
renderer.setDiscardFlag( QwtPlotRenderer::DiscardBackground );
renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasBackground );
renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasFrame );
renderer.setLayoutFlag( QwtPlotRenderer::FrameWithScales );
}
renderer.renderTo( d_plot, printer );
}
}
#endif
void MainWindow::exportDocument()
{
QwtPlotRenderer renderer;
renderer.exportTo( d_plot, "bode.pdf" );
}
void MainWindow::enableZoomMode( bool on )
{
d_panner->setEnabled( on );
d_zoomer[0]->setEnabled( on );
d_zoomer[0]->zoom( 0 );
d_zoomer[1]->setEnabled( on );
d_zoomer[1]->zoom( 0 );
d_picker->setEnabled( !on );
showInfo();
}
void MainWindow::showInfo( QString text )
{
if ( text == QString::null )
{
if ( d_picker->rubberBand() )
text = "Cursor Pos: Press left mouse button in plot region";
else
text = "Zoom: Press mouse button and drag";
}
#ifndef QT_NO_STATUSBAR
statusBar()->showMessage( text );
#endif
}
void MainWindow::moved( const QPoint &pos )
{
QString info;
info.sprintf( "Freq=%g, Ampl=%g, Phase=%g",
d_plot->invTransform( QwtPlot::xBottom, pos.x() ),
d_plot->invTransform( QwtPlot::yLeft, pos.y() ),
d_plot->invTransform( QwtPlot::yRight, pos.y() )
);
showInfo( info );
}
void MainWindow::selected( const QPolygon & )
{
showInfo();
}

View File

@ -0,0 +1,35 @@
#include <qmainwindow.h>
class QwtPlotZoomer;
class QwtPlotPicker;
class QwtPlotPanner;
class Plot;
class QPolygon;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow( QWidget *parent = 0 );
private Q_SLOTS:
void moved( const QPoint & );
void selected( const QPolygon & );
#ifndef QT_NO_PRINTER
void print();
#endif
void exportDocument();
void enableZoomMode( bool );
private:
void showInfo( QString text = QString::null );
Plot *d_plot;
QwtPlotZoomer *d_zoomer[2];
QwtPlotPicker *d_picker;
QwtPlotPanner *d_panner;
};

View File

@ -0,0 +1,99 @@
#ifndef PIXMAPS_H
#define PIXMAPS_H
static const char *print_xpm[] =
{
"32 32 12 1",
"a c #ffffff",
"h c #ffff00",
"c c #ffffff",
"f c #dcdcdc",
"b c #c0c0c0",
"j c #a0a0a4",
"e c #808080",
"g c #808000",
"d c #585858",
"i c #00ff00",
"# c #000000",
". c None",
"................................",
"................................",
"...........###..................",
"..........#abb###...............",
".........#aabbbbb###............",
".........#ddaaabbbbb###.........",
"........#ddddddaaabbbbb###......",
".......#deffddddddaaabbbbb###...",
"......#deaaabbbddddddaaabbbbb###",
".....#deaaaaaaabbbddddddaaabbbb#",
"....#deaaabbbaaaa#ddedddfggaaad#",
"...#deaaaaaaaaaa#ddeeeeafgggfdd#",
"..#deaaabbbaaaa#ddeeeeabbbbgfdd#",
".#deeefaaaaaaa#ddeeeeabbhhbbadd#",
"#aabbbeeefaaa#ddeeeeabbbbbbaddd#",
"#bbaaabbbeee#ddeeeeabbiibbadddd#",
"#bbbbbaaabbbeeeeeeabbbbbbaddddd#",
"#bjbbbbbbaaabbbbeabbbbbbadddddd#",
"#bjjjjbbbbbbaaaeabbbbbbaddddddd#",
"#bjaaajjjbbbbbbaaabbbbadddddddd#",
"#bbbbbaaajjjbbbbbbaaaaddddddddd#",
"#bjbbbbbbaaajjjbbbbbbddddddddd#.",
"#bjjjjbbbbbbaaajjjbbbdddddddd#..",
"#bjaaajjjbbbbbbjaajjbddddddd#...",
"#bbbbbaaajjjbbbjbbaabdddddd#....",
"###bbbbbbaaajjjjbbbbbddddd#.....",
"...###bbbbbbaaajbbbbbdddd#......",
"......###bbbbbbjbbbbbddd#.......",
".........###bbbbbbbbbdd#........",
"............###bbbbbbd#.........",
"...............###bbb#..........",
"..................###..........."
};
static const char *zoom_xpm[] =
{
"32 32 8 1",
"# c #000000",
"b c #c0c0c0",
"a c #ffffff",
"e c #585858",
"d c #a0a0a4",
"c c #0000ff",
"f c #00ffff",
". c None",
"..######################........",
".#a#baaaaaaaaaaaaaaaaaa#........",
"#aa#baaaaaaaaaaaaaccaca#........",
"####baaaaaaaaaaaaaaaaca####.....",
"#bbbbaaaaaaaaaaaacccaaa#da#.....",
"#aaaaaaaaaaaaaaaacccaca#da#.....",
"#aaaaaaaaaaaaaaaaaccaca#da#.....",
"#aaaaaaaaaabe###ebaaaaa#da#.....",
"#aaaaaaaaa#########aaaa#da#.....",
"#aaaaaaaa###dbbbb###aaa#da#.....",
"#aaaaaaa###aaaaffb###aa#da#.....",
"#aaaaaab##aaccaaafb##ba#da#.....",
"#aaaaaae#daaccaccaad#ea#da#.....",
"#aaaaaa##aaaaaaccaab##a#da#.....",
"#aaaaaa##aacccaaaaab##a#da#.....",
"#aaaaaa##aaccccaccab##a#da#.....",
"#aaaaaae#daccccaccad#ea#da#.....",
"#aaaaaab##aacccaaaa##da#da#.....",
"#aaccacd###aaaaaaa###da#da#.....",
"#aaaaacad###daaad#####a#da#.....",
"#acccaaaad##########da##da#.....",
"#acccacaaadde###edd#eda#da#.....",
"#aaccacaaaabdddddbdd#eda#a#.....",
"#aaaaaaaaaaaaaaaaaadd#eda##.....",
"#aaaaaaaaaaaaaaaaaaadd#eda#.....",
"#aaaaaaaccacaaaaaaaaadd#eda#....",
"#aaaaaaaaaacaaaaaaaaaad##eda#...",
"#aaaaaacccaaaaaaaaaaaaa#d#eda#..",
"########################dd#eda#.",
"...#dddddddddddddddddddddd##eda#",
"...#aaaaaaaaaaaaaaaaaaaaaa#.####",
"...########################..##."
};
#endif

View File

@ -0,0 +1,190 @@
#include <qwt_math.h>
#include <qwt_scale_engine.h>
#include <qwt_symbol.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_curve.h>
#include <qwt_legend.h>
#include <qwt_text.h>
#include <qwt_plot_canvas.h>
#include <qmath.h>
#include "complexnumber.h"
#include "plot.h"
#if QT_VERSION < 0x040601
#define qExp(x) ::exp(x)
#define qAtan2(y, x) ::atan2(y, x)
#endif
static void logSpace( double *array, int size, double xmin, double xmax )
{
if ( ( xmin <= 0.0 ) || ( xmax <= 0.0 ) || ( size <= 0 ) )
return;
const int imax = size - 1;
array[0] = xmin;
array[imax] = xmax;
const double lxmin = log( xmin );
const double lxmax = log( xmax );
const double lstep = ( lxmax - lxmin ) / double( imax );
for ( int i = 1; i < imax; i++ )
array[i] = qExp( lxmin + double( i ) * lstep );
}
Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
setAutoReplot( false );
setTitle( "Frequency Response of a Second-Order System" );
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setBorderRadius( 10 );
setCanvas( canvas );
setCanvasBackground( QColor( "MidnightBlue" ) );
// legend
QwtLegend *legend = new QwtLegend;
insertLegend( legend, QwtPlot::BottomLegend );
// grid
QwtPlotGrid *grid = new QwtPlotGrid;
grid->enableXMin( true );
grid->setMajorPen( Qt::white, 0, Qt::DotLine );
grid->setMinorPen( Qt::gray, 0 , Qt::DotLine );
grid->attach( this );
// axes
enableAxis( QwtPlot::yRight );
setAxisTitle( QwtPlot::xBottom, "Normalized Frequency" );
setAxisTitle( QwtPlot::yLeft, "Amplitude [dB]" );
setAxisTitle( QwtPlot::yRight, "Phase [deg]" );
setAxisMaxMajor( QwtPlot::xBottom, 6 );
setAxisMaxMinor( QwtPlot::xBottom, 9 );
setAxisScaleEngine( QwtPlot::xBottom, new QwtLogScaleEngine );
// curves
d_curve1 = new QwtPlotCurve( "Amplitude" );
d_curve1->setRenderHint( QwtPlotItem::RenderAntialiased );
d_curve1->setPen( Qt::yellow );
d_curve1->setLegendAttribute( QwtPlotCurve::LegendShowLine );
d_curve1->setYAxis( QwtPlot::yLeft );
d_curve1->attach( this );
d_curve2 = new QwtPlotCurve( "Phase" );
d_curve2->setRenderHint( QwtPlotItem::RenderAntialiased );
d_curve2->setPen( Qt::cyan );
d_curve2->setLegendAttribute( QwtPlotCurve::LegendShowLine );
d_curve2->setYAxis( QwtPlot::yRight );
d_curve2->attach( this );
// marker
d_marker1 = new QwtPlotMarker();
d_marker1->setValue( 0.0, 0.0 );
d_marker1->setLineStyle( QwtPlotMarker::VLine );
d_marker1->setLabelAlignment( Qt::AlignRight | Qt::AlignBottom );
d_marker1->setLinePen( Qt::green, 0, Qt::DashDotLine );
d_marker1->attach( this );
d_marker2 = new QwtPlotMarker();
d_marker2->setLineStyle( QwtPlotMarker::HLine );
d_marker2->setLabelAlignment( Qt::AlignRight | Qt::AlignBottom );
d_marker2->setLinePen( QColor( 200, 150, 0 ), 0, Qt::DashDotLine );
d_marker2->setSymbol( new QwtSymbol( QwtSymbol::Diamond,
QColor( Qt::yellow ), QColor( Qt::green ), QSize( 8, 8 ) ) );
d_marker2->attach( this );
setDamp( 0.0 );
setAutoReplot( true );
}
void Plot::showData( const double *frequency, const double *amplitude,
const double *phase, int count )
{
d_curve1->setSamples( frequency, amplitude, count );
d_curve2->setSamples( frequency, phase, count );
}
void Plot::showPeak( double freq, double amplitude )
{
QString label;
label.sprintf( "Peak: %.3g dB", amplitude );
QwtText text( label );
text.setFont( QFont( "Helvetica", 10, QFont::Bold ) );
text.setColor( QColor( 200, 150, 0 ) );
d_marker2->setValue( freq, amplitude );
d_marker2->setLabel( text );
}
void Plot::show3dB( double freq )
{
QString label;
label.sprintf( "-3 dB at f = %.3g", freq );
QwtText text( label );
text.setFont( QFont( "Helvetica", 10, QFont::Bold ) );
text.setColor( Qt::green );
d_marker1->setValue( freq, 0.0 );
d_marker1->setLabel( text );
}
//
// re-calculate frequency response
//
void Plot::setDamp( double damping )
{
const bool doReplot = autoReplot();
setAutoReplot( false );
const int ArraySize = 200;
double frequency[ArraySize];
double amplitude[ArraySize];
double phase[ArraySize];
// build frequency vector with logarithmic division
logSpace( frequency, ArraySize, 0.01, 100 );
int i3 = 1;
double fmax = 1;
double amax = -1000.0;
for ( int i = 0; i < ArraySize; i++ )
{
double f = frequency[i];
const ComplexNumber g =
ComplexNumber( 1.0 ) / ComplexNumber( 1.0 - f * f, 2.0 * damping * f );
amplitude[i] = 20.0 * log10( qSqrt( g.real() * g.real() + g.imag() * g.imag() ) );
phase[i] = qAtan2( g.imag(), g.real() ) * ( 180.0 / M_PI );
if ( ( i3 <= 1 ) && ( amplitude[i] < -3.0 ) )
i3 = i;
if ( amplitude[i] > amax )
{
amax = amplitude[i];
fmax = frequency[i];
}
}
double f3 = frequency[i3] - ( frequency[i3] - frequency[i3 - 1] )
/ ( amplitude[i3] - amplitude[i3 -1] ) * ( amplitude[i3] + 3 );
showPeak( fmax, amax );
show3dB( f3 );
showData( frequency, amplitude, phase, ArraySize );
setAutoReplot( doReplot );
replot();
}

View File

@ -0,0 +1,31 @@
#ifndef _PLOT_H_
#define _PLOT_H_
#include <qwt_plot.h>
class QwtPlotCurve;
class QwtPlotMarker;
class Plot: public QwtPlot
{
Q_OBJECT
public:
Plot( QWidget *parent );
public Q_SLOTS:
void setDamp( double damping );
private:
void showData( const double *frequency, const double *amplitude,
const double *phase, int count );
void showPeak( double freq, double amplitude );
void show3dB( double freq );
QwtPlotCurve *d_curve1;
QwtPlotCurve *d_curve2;
QwtPlotMarker *d_marker1;
QwtPlotMarker *d_marker2;
};
#endif

View File

@ -0,0 +1,32 @@
TARGET = controls
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
sliderbox.h \
slidertab.h \
wheelbox.h \
wheeltab.h \
knobbox.h \
knobtab.h \
dialbox.h \
dialtab.h
SOURCES = \
sliderbox.cpp \
slidertab.cpp \
wheelbox.cpp \
wheeltab.cpp \
knobbox.cpp \
knobtab.cpp \
dialbox.cpp \
dialtab.cpp \
main.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,163 @@
#include <qlabel.h>
#include <qlayout.h>
#include <qwt_dial.h>
#include <qwt_dial_needle.h>
#include <qwt_scale_engine.h>
#include <qwt_transform.h>
#include <qwt_round_scale_draw.h>
#include "dialbox.h"
DialBox::DialBox( QWidget *parent, int type ):
QWidget( parent )
{
d_dial = createDial( type );
d_label = new QLabel( this );
d_label->setAlignment( Qt::AlignCenter );
QVBoxLayout *layout = new QVBoxLayout( this );;
layout->setSpacing( 0 );
layout->addWidget( d_dial, 10 );
layout->addWidget( d_label );
connect( d_dial, SIGNAL( valueChanged( double ) ),
this, SLOT( setNum( double ) ) );
setNum( d_dial->value() );
}
QwtDial *DialBox::createDial( int type ) const
{
QwtDial *dial = new QwtDial();
dial->setTracking( true );
dial->setFocusPolicy( Qt::StrongFocus );
dial->setObjectName( QString( "Dial %1" ).arg( type + 1 ) );
QColor needleColor( Qt::red );
switch( type )
{
case 0:
{
dial->setOrigin( 135.0 );
dial->setScaleArc( 0.0, 270.0 );
dial->setScaleMaxMinor( 4 );
dial->setScaleMaxMajor( 10 );
dial->setScale( -100.0, 100.0 );
needleColor = QColor( "Goldenrod" );
break;
}
case 1:
{
dial->setOrigin( 135.0 );
dial->setScaleArc( 0.0, 270.0 );
dial->setScaleMaxMinor( 10 );
dial->setScaleMaxMajor( 10 );
dial->setScale( 10.0, 0.0 );
QwtRoundScaleDraw *scaleDraw = new QwtRoundScaleDraw();
scaleDraw->setSpacing( 8 );
scaleDraw->enableComponent(
QwtAbstractScaleDraw::Backbone, false );
scaleDraw->setTickLength( QwtScaleDiv::MinorTick, 2 );
scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 4 );
scaleDraw->setTickLength( QwtScaleDiv::MajorTick, 8 );
dial->setScaleDraw( scaleDraw );
break;
}
case 2:
{
dial->setOrigin( 150.0 );
dial->setScaleArc( 0.0, 240.0 );
QwtLinearScaleEngine *scaleEngine = new QwtLinearScaleEngine( 2 );
scaleEngine->setTransformation( new QwtPowerTransform( 2 ) );
dial->setScaleEngine( scaleEngine );
QList< double > ticks[ QwtScaleDiv::NTickTypes ];
ticks[ QwtScaleDiv::MajorTick ] << 0 << 4
<< 16 << 32 << 64 << 96 << 128;
ticks[ QwtScaleDiv::MediumTick ] << 24 << 48 << 80 << 112;
ticks[ QwtScaleDiv::MinorTick ]
<< 0.5 << 1 << 2
<< 7 << 10 << 13
<< 20 << 28
<< 40 << 56
<< 72 << 88
<< 104 << 120;
dial->setScale( QwtScaleDiv( 0, 128, ticks ) );
break;
}
case 3:
{
dial->setOrigin( 135.0 );
dial->setScaleArc( 0.0, 270.0 );
dial->setScaleMaxMinor( 9 );
dial->setScaleEngine( new QwtLogScaleEngine );
dial->setScale( 1.0e-2, 1.0e2 );
break;
}
case 4:
{
dial->setOrigin( 225.0 );
dial->setScaleArc( 0.0, 360.0 );
dial->setScaleMaxMinor( 5 );
dial->setScaleStepSize( 20 );
dial->setScale( 100.0, -100.0 );
dial->setWrapping( true );
dial->setTotalSteps( 40 );
dial->setMode( QwtDial::RotateScale );
dial->setValue( 70.0 );
needleColor = QColor( "DarkSlateBlue" );
break;
}
case 5:
{
dial->setOrigin( 45.0 );
dial->setScaleArc( 0.0, 225.0 );
dial->setScaleMaxMinor( 5 );
dial->setScaleMaxMajor( 10 );
dial->setScale( 0.0, 10.0 );
break;
}
}
QwtDialSimpleNeedle *needle = new QwtDialSimpleNeedle(
QwtDialSimpleNeedle::Arrow, true, needleColor,
QColor( Qt::gray ).light( 130 ) );
dial->setNeedle( needle );
//const QColor base( QColor( "DimGray" ) );
const QColor base( QColor( Qt::darkGray ).dark( 150 ) );
QPalette palette;
palette.setColor( QPalette::Base, base );
palette.setColor( QPalette::Window, base.dark( 150 ) );
palette.setColor( QPalette::Mid, base.dark( 110 ) );
palette.setColor( QPalette::Light, base.light( 170 ) );
palette.setColor( QPalette::Dark, base.dark( 170 ) );
palette.setColor( QPalette::Text, base.dark( 200 ).light( 800 ) );
palette.setColor( QPalette::WindowText, base.dark( 200 ) );
dial->setPalette( palette );
dial->setLineWidth( 4 );
dial->setFrameShadow( QwtDial::Sunken );
return dial;
}
void DialBox::setNum( double v )
{
QString text;
text.setNum( v, 'f', 2 );
d_label->setText( text );
}

View File

@ -0,0 +1,25 @@
#ifndef _DIAL_BOX_H_
#define _DIAL_BOX_H_
#include <qwidget.h>
class QLabel;
class QwtDial;
class DialBox: public QWidget
{
Q_OBJECT
public:
DialBox( QWidget *parent, int type );
private Q_SLOTS:
void setNum( double v );
private:
QwtDial *createDial( int type ) const;
QwtDial *d_dial;
QLabel *d_label;
};
#endif

View File

@ -0,0 +1,17 @@
#include "dialtab.h"
#include "dialbox.h"
#include <qlayout.h>
DialTab::DialTab( QWidget *parent ):
QWidget( parent )
{
QGridLayout *layout = new QGridLayout( this );
const int numRows = 3;
for ( int i = 0; i < 2 * numRows; i++ )
{
DialBox *dialBox = new DialBox( this, i );
layout->addWidget( dialBox, i / numRows, i % numRows );
}
}

View File

@ -0,0 +1,12 @@
#ifndef _DIAL_TAB_H
#define _DIAL_TAB_H 1
#include <qwidget.h>
class DialTab: public QWidget
{
public:
DialTab( QWidget *parent = NULL );
};
#endif

View File

@ -0,0 +1,119 @@
#include <qlabel.h>
#include <qlayout.h>
#include <qwt_knob.h>
#include <qwt_scale_engine.h>
#include <qwt_transform.h>
#include "knobbox.h"
KnobBox::KnobBox( QWidget *parent, int knobType ):
QWidget( parent )
{
d_knob = createKnob( knobType );
d_knob->setKnobWidth( 100 );
d_label = new QLabel( this );
d_label->setAlignment( Qt::AlignCenter );
QVBoxLayout *layout = new QVBoxLayout( this );;
layout->setSpacing( 0 );
layout->addWidget( d_knob, 10 );
layout->addWidget( d_label );
layout->addStretch( 10 );
connect( d_knob, SIGNAL( valueChanged( double ) ),
this, SLOT( setNum( double ) ) );
setNum( d_knob->value() );
}
QwtKnob *KnobBox::createKnob( int knobType ) const
{
QwtKnob *knob = new QwtKnob();
knob->setTracking( true );
switch( knobType )
{
case 0:
{
knob->setKnobStyle( QwtKnob::Sunken );
knob->setMarkerStyle( QwtKnob::Nub );
knob->setWrapping( true );
knob->setNumTurns( 4 );
knob->setScaleStepSize( 10.0 );
knob->setScale( 0, 400 );
knob->setTotalSteps( 400 );
break;
}
case 1:
{
knob->setKnobStyle( QwtKnob::Sunken );
knob->setMarkerStyle( QwtKnob::Dot );
break;
}
case 2:
{
knob->setKnobStyle( QwtKnob::Sunken );
knob->setMarkerStyle( QwtKnob::Tick );
QwtLinearScaleEngine *scaleEngine = new QwtLinearScaleEngine( 2 );
scaleEngine->setTransformation( new QwtPowerTransform( 2 ) );
knob->setScaleEngine( scaleEngine );
QList< double > ticks[ QwtScaleDiv::NTickTypes ];
ticks[ QwtScaleDiv::MajorTick ] << 0 << 4
<< 16 << 32 << 64 << 96 << 128;
ticks[ QwtScaleDiv::MediumTick ] << 24 << 48 << 80 << 112;
ticks[ QwtScaleDiv::MinorTick ]
<< 0.5 << 1 << 2
<< 7 << 10 << 13
<< 20 << 28
<< 40 << 56
<< 72 << 88
<< 104 << 120;
knob->setScale( QwtScaleDiv( 0, 128, ticks ) );
knob->setTotalSteps( 100 );
knob->setStepAlignment( false );
knob->setSingleSteps( 1 );
knob->setPageSteps( 5 );
break;
}
case 3:
{
knob->setKnobStyle( QwtKnob::Flat );
knob->setMarkerStyle( QwtKnob::Notch );
knob->setScaleEngine( new QwtLogScaleEngine() );
knob->setScaleStepSize( 1.0 );
knob->setScale( 0.1, 1000.0 );
knob->setScaleMaxMinor( 10 );
break;
}
case 4:
{
knob->setKnobStyle( QwtKnob::Raised );
knob->setMarkerStyle( QwtKnob::Dot );
knob->setWrapping( true );
break;
}
case 5:
{
knob->setKnobStyle( QwtKnob::Styled );
knob->setMarkerStyle( QwtKnob::Triangle );
knob->setTotalAngle( 180.0 );
knob->setScale( 100, -100 );
break;
}
}
return knob;
}
void KnobBox::setNum( double v )
{
QString text;
text.setNum( v, 'f', 2 );
d_label->setText( text );
}

View File

@ -0,0 +1,25 @@
#ifndef _KNOB_BOX_H_
#define _KNOB_BOX_H_
#include <qwidget.h>
class QLabel;
class QwtKnob;
class KnobBox: public QWidget
{
Q_OBJECT
public:
KnobBox( QWidget *parent, int knobType );
private Q_SLOTS:
void setNum( double v );
private:
QwtKnob *createKnob( int knobType ) const;
QwtKnob *d_knob;
QLabel *d_label;
};
#endif

View File

@ -0,0 +1,17 @@
#include "knobtab.h"
#include "knobbox.h"
#include <qlayout.h>
KnobTab::KnobTab( QWidget *parent ):
QWidget( parent )
{
QGridLayout *layout = new QGridLayout( this );
const int numRows = 3;
for ( int i = 0; i < 2 * numRows; i++ )
{
KnobBox *knobBox = new KnobBox( this, i );
layout->addWidget( knobBox, i / numRows, i % numRows );
}
}

View File

@ -0,0 +1,12 @@
#ifndef _KNOB_TAB_H
#define _KNOB_TAB_H 1
#include <qwidget.h>
class KnobTab: public QWidget
{
public:
KnobTab( QWidget *parent = NULL );
};
#endif

View File

@ -0,0 +1,41 @@
#include <qapplication.h>
#include <qtabwidget.h>
#include "slidertab.h"
#include "wheeltab.h"
#include "knobtab.h"
#include "dialtab.h"
int main ( int argc, char **argv )
{
QApplication a( argc, argv );
QTabWidget tabWidget;
SliderTab *sliderTab = new SliderTab();
sliderTab->setAutoFillBackground( true );
sliderTab->setPalette( QColor( "DimGray" ) );
WheelTab *wheelTab = new WheelTab();
wheelTab->setAutoFillBackground( true );
wheelTab->setPalette( QColor( "Silver" ) );
KnobTab *knobTab = new KnobTab();
knobTab->setAutoFillBackground( true );
knobTab->setPalette( Qt::darkGray );
DialTab *dialTab = new DialTab();
dialTab->setAutoFillBackground( true );
dialTab->setPalette( Qt::darkGray );
tabWidget.addTab( new SliderTab, "Slider" );
tabWidget.addTab( new WheelTab, "Wheel/Thermo" );
tabWidget.addTab( knobTab, "Knob" );
tabWidget.addTab( dialTab, "Dial" );
tabWidget.resize( 800, 600 );
tabWidget.show();
return a.exec();
}

View File

@ -0,0 +1,172 @@
#include <qlabel.h>
#include <qlayout.h>
#include <qwt_slider.h>
#include <qwt_scale_engine.h>
#include <qwt_transform.h>
#include "sliderbox.h"
SliderBox::SliderBox( int sliderType, QWidget *parent ):
QWidget( parent )
{
d_slider = createSlider( sliderType );
QFlags<Qt::AlignmentFlag> alignment;
if ( d_slider->orientation() == Qt::Horizontal )
{
if ( d_slider->scalePosition() == QwtSlider::TrailingScale )
alignment = Qt::AlignBottom;
else
alignment = Qt::AlignTop;
alignment |= Qt::AlignHCenter;
}
else
{
if ( d_slider->scalePosition() == QwtSlider::TrailingScale )
alignment = Qt::AlignRight;
else
alignment = Qt::AlignLeft;
alignment |= Qt::AlignVCenter;
}
d_label = new QLabel( this );
d_label->setAlignment( alignment );
d_label->setFixedWidth( d_label->fontMetrics().width( "10000.9" ) );
connect( d_slider, SIGNAL( valueChanged( double ) ), SLOT( setNum( double ) ) );
QBoxLayout *layout;
if ( d_slider->orientation() == Qt::Horizontal )
layout = new QHBoxLayout( this );
else
layout = new QVBoxLayout( this );
layout->addWidget( d_slider );
layout->addWidget( d_label );
setNum( d_slider->value() );
}
QwtSlider *SliderBox::createSlider( int sliderType ) const
{
QwtSlider *slider = new QwtSlider();
switch( sliderType )
{
case 0:
{
slider->setOrientation( Qt::Horizontal );
slider->setScalePosition( QwtSlider::TrailingScale );
slider->setTrough( true );
slider->setGroove( false );
slider->setSpacing( 0 );
slider->setHandleSize( QSize( 30, 16 ) );
slider->setScale( 10.0, -10.0 );
slider->setTotalSteps( 8 );
slider->setSingleSteps( 1 );
slider->setPageSteps( 1 );
slider->setWrapping( true );
break;
}
case 1:
{
slider->setOrientation( Qt::Horizontal );
slider->setScalePosition( QwtSlider::NoScale );
slider->setTrough( true );
slider->setGroove( true );
slider->setScale( 0.0, 1.0 );
slider->setTotalSteps( 100 );
slider->setSingleSteps( 1 );
slider->setPageSteps( 5 );
break;
}
case 2:
{
slider->setOrientation( Qt::Horizontal );
slider->setScalePosition( QwtSlider::LeadingScale );
slider->setTrough( false );
slider->setGroove( true );
slider->setHandleSize( QSize( 12, 25 ) );
slider->setScale( 1000.0, 3000.0 );
slider->setTotalSteps( 200.0 );
slider->setSingleSteps( 2 );
slider->setPageSteps( 10 );
break;
}
case 3:
{
slider->setOrientation( Qt::Horizontal );
slider->setScalePosition( QwtSlider::TrailingScale );
slider->setTrough( true );
slider->setGroove( true );
QwtLinearScaleEngine *scaleEngine = new QwtLinearScaleEngine( 2 );
scaleEngine->setTransformation( new QwtPowerTransform( 2 ) );
slider->setScaleEngine( scaleEngine );
slider->setScale( 0.0, 128.0 );
slider->setTotalSteps( 100 );
slider->setStepAlignment( false );
slider->setSingleSteps( 1 );
slider->setPageSteps( 5 );
break;
}
case 4:
{
slider->setOrientation( Qt::Vertical );
slider->setScalePosition( QwtSlider::TrailingScale );
slider->setTrough( false );
slider->setGroove( true );
slider->setScale( 100.0, 0.0 );
slider->setInvertedControls( true );
slider->setTotalSteps( 100 );
slider->setPageSteps( 5 );
slider->setScaleMaxMinor( 5 );
break;
}
case 5:
{
slider->setOrientation( Qt::Vertical );
slider->setScalePosition( QwtSlider::NoScale );
slider->setTrough( true );
slider->setGroove( false );
slider->setScale( 0.0, 100.0 );
slider->setTotalSteps( 100 );
slider->setPageSteps( 10 );
break;
}
case 6:
{
slider->setOrientation( Qt::Vertical );
slider->setScalePosition( QwtSlider::LeadingScale );
slider->setTrough( true );
slider->setGroove( true );
slider->setScaleEngine( new QwtLogScaleEngine );
slider->setStepAlignment( false );
slider->setHandleSize( QSize( 20, 32 ) );
slider->setBorderWidth( 1 );
slider->setScale( 1.0, 1.0e4 );
slider->setTotalSteps( 100 );
slider->setPageSteps( 10 );
slider->setScaleMaxMinor( 9 );
break;
}
}
if ( slider )
{
QString name( "Slider %1" );
slider->setObjectName( name.arg( sliderType ) );
}
return slider;
}
void SliderBox::setNum( double v )
{
QString text;
text.setNum( v, 'f', 2 );
d_label->setText( text );
}

View File

@ -0,0 +1,25 @@
#ifndef _SLIDER_BOX_H_
#define _SLIDER_BOX_H_ 1
#include <qwidget.h>
class QLabel;
class QwtSlider;
class SliderBox: public QWidget
{
Q_OBJECT
public:
SliderBox( int sliderType, QWidget *parent = NULL );
private Q_SLOTS:
void setNum( double v );
private:
QwtSlider *createSlider( int sliderType ) const;
QwtSlider *d_slider;
QLabel *d_label;
};
#endif

View File

@ -0,0 +1,37 @@
#include "slidertab.h"
#include "sliderbox.h"
#include <qlayout.h>
SliderTab::SliderTab( QWidget *parent ):
QWidget( parent )
{
int i;
QBoxLayout *hLayout = createLayout( Qt::Vertical );
for ( i = 0; i < 4; i++ )
hLayout->addWidget( new SliderBox( i ) );
hLayout->addStretch();
QBoxLayout *vLayout = createLayout( Qt::Horizontal );
for ( ; i < 7; i++ )
vLayout->addWidget( new SliderBox( i ) );
QBoxLayout *mainLayout = createLayout( Qt::Horizontal, this );
mainLayout->addLayout( vLayout );
mainLayout->addLayout( hLayout, 10 );
}
QBoxLayout *SliderTab::createLayout(
Qt::Orientation orientation, QWidget *widget )
{
QBoxLayout *layout =
new QBoxLayout( QBoxLayout::LeftToRight, widget );
if ( orientation == Qt::Vertical )
layout->setDirection( QBoxLayout::TopToBottom );
layout->setSpacing( 20 );
layout->setMargin( 0 );
return layout;
}

View File

@ -0,0 +1,18 @@
#ifndef _SLIDER_TAB_H
#define _SLIDER_TAB_H 1
#include <qwidget.h>
class QBoxLayout;
class SliderTab: public QWidget
{
public:
SliderTab( QWidget *parent = NULL );
private:
QBoxLayout *createLayout( Qt::Orientation,
QWidget *widget = NULL );
};
#endif

View File

@ -0,0 +1,188 @@
#include <qlabel.h>
#include <qlayout.h>
#include <qwt_wheel.h>
#include <qwt_thermo.h>
#include <qwt_scale_engine.h>
#include <qwt_transform.h>
#include <qwt_color_map.h>
#include "wheelbox.h"
WheelBox::WheelBox( Qt::Orientation orientation,
int type, QWidget *parent ):
QWidget( parent )
{
QWidget *box = createBox( orientation, type );
d_label = new QLabel( this );
d_label->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
QBoxLayout *layout = new QVBoxLayout( this );
layout->addWidget( box );
layout->addWidget( d_label );
setNum( d_wheel->value() );
connect( d_wheel, SIGNAL( valueChanged( double ) ),
this, SLOT( setNum( double ) ) );
}
QWidget *WheelBox::createBox(
Qt::Orientation orientation, int type )
{
d_wheel = new QwtWheel();
d_wheel->setValue( 80 );
d_wheel->setWheelWidth( 20 );
d_wheel->setMass( 1.0 );
d_thermo = new QwtThermo();
d_thermo->setOrientation( orientation );
if ( orientation == Qt::Horizontal )
{
d_thermo->setScalePosition( QwtThermo::LeadingScale );
d_wheel->setOrientation( Qt::Vertical );
}
else
{
d_thermo->setScalePosition( QwtThermo::TrailingScale );
d_wheel->setOrientation( Qt::Horizontal );
}
switch( type )
{
case 0:
{
QwtLinearColorMap *colorMap = new QwtLinearColorMap();
colorMap->setColorInterval( Qt::blue, Qt::red );
d_thermo->setColorMap( colorMap );
break;
}
case 1:
{
QwtLinearColorMap *colorMap = new QwtLinearColorMap();
colorMap->setMode( QwtLinearColorMap::FixedColors );
int idx = 4;
colorMap->setColorInterval( Qt::GlobalColor( idx ),
Qt::GlobalColor( idx + 10 ) );
for ( int i = 1; i < 10; i++ )
{
colorMap->addColorStop( i / 10.0,
Qt::GlobalColor( idx + i ) );
}
d_thermo->setColorMap( colorMap );
break;
}
case 2:
{
d_wheel->setRange( 10, 1000 );
d_wheel->setSingleStep( 1.0 );
d_thermo->setScaleEngine( new QwtLogScaleEngine );
d_thermo->setScaleMaxMinor( 10 );
d_thermo->setFillBrush( Qt::darkCyan );
d_thermo->setAlarmBrush( Qt::magenta );
d_thermo->setAlarmLevel( 500.0 );
d_wheel->setValue( 800 );
break;
}
case 3:
{
d_wheel->setRange( -1000, 1000 );
d_wheel->setSingleStep( 1.0 );
d_wheel->setPalette( QColor( "Tan" ) );
QwtLinearScaleEngine *scaleEngine = new QwtLinearScaleEngine();
scaleEngine->setTransformation( new QwtPowerTransform( 2 ) );
d_thermo->setScaleMaxMinor( 5 );
d_thermo->setScaleEngine( scaleEngine );
QPalette pal = palette();
pal.setColor( QPalette::Base, Qt::darkGray );
pal.setColor( QPalette::ButtonText, QColor( "darkKhaki" ) );
d_thermo->setPalette( pal );
break;
}
case 4:
{
d_wheel->setRange( -100, 300 );
d_wheel->setInverted( true );
QwtLinearColorMap *colorMap = new QwtLinearColorMap();
colorMap->setColorInterval( Qt::darkCyan, Qt::yellow );
d_thermo->setColorMap( colorMap );
d_wheel->setValue( 243 );
break;
}
case 5:
{
d_thermo->setFillBrush( Qt::darkCyan );
d_thermo->setAlarmBrush( Qt::magenta );
d_thermo->setAlarmLevel( 60.0 );
break;
}
case 6:
{
d_thermo->setOriginMode( QwtThermo::OriginMinimum );
d_thermo->setFillBrush( QBrush( "DarkSlateBlue" ) );
d_thermo->setAlarmBrush( QBrush( "DarkOrange" ) );
d_thermo->setAlarmLevel( 60.0 );
break;
}
case 7:
{
d_wheel->setRange( -100, 100 );
d_thermo->setOriginMode( QwtThermo::OriginCustom );
d_thermo->setOrigin( 0.0 );
d_thermo->setFillBrush( Qt::darkBlue );
break;
}
}
double min = d_wheel->minimum();
double max = d_wheel->maximum();
if ( d_wheel->isInverted() )
qSwap( min, max );
d_thermo->setScale( min, max );
d_thermo->setValue( d_wheel->value() );
connect( d_wheel, SIGNAL( valueChanged( double ) ),
d_thermo, SLOT( setValue( double ) ) );
QWidget *box = new QWidget();
QBoxLayout *layout;
if ( orientation == Qt::Horizontal )
layout = new QHBoxLayout( box );
else
layout = new QVBoxLayout( box );
layout->addWidget( d_thermo, Qt::AlignCenter );
layout->addWidget( d_wheel );
return box;
}
void WheelBox::setNum( double v )
{
QString text;
text.setNum( v, 'f', 2 );
d_label->setText( text );
}

View File

@ -0,0 +1,29 @@
#ifndef _WHEEL_BOX_H_
#define _WHEEL_BOX_H_ 1
#include <qwidget.h>
class QLabel;
class QwtThermo;
class QwtWheel;
class WheelBox: public QWidget
{
Q_OBJECT
public:
WheelBox( Qt::Orientation,
int type, QWidget *parent = NULL );
private Q_SLOTS:
void setNum( double v );
private:
QWidget *createBox( Qt::Orientation, int type );
private:
QwtWheel *d_wheel;
QwtThermo *d_thermo;
QLabel *d_label;
};
#endif

View File

@ -0,0 +1,28 @@
#include "wheeltab.h"
#include "wheelbox.h"
#include <qlayout.h>
WheelTab::WheelTab( QWidget *parent ):
QWidget( parent )
{
const int numBoxes = 4;
QGridLayout *layout1 = new QGridLayout();
for ( int i = 0; i < numBoxes; i++ )
{
WheelBox *box = new WheelBox( Qt::Vertical, i );
layout1->addWidget( box, i / 2, i % 2 );
}
QGridLayout *layout2 = new QGridLayout();
for ( int i = 0; i < numBoxes; i++ )
{
WheelBox *box = new WheelBox( Qt::Horizontal, i + numBoxes );
layout2->addWidget( box, i / 2, i % 2 );
}
QHBoxLayout *layout = new QHBoxLayout( this );
layout->addLayout( layout1, 2 );
layout->addLayout( layout2, 5 );
}

View File

@ -0,0 +1,12 @@
#ifndef _WHEEL_TAB_H
#define _WHEEL_TAB_H 1
#include <qwidget.h>
class WheelTab: public QWidget
{
public:
WheelTab( QWidget *parent = NULL );
};
#endif

View File

@ -0,0 +1,54 @@
#include <qpainter.h>
#include <qwt_scale_map.h>
#include <qwt_plot_curve.h>
#include "cpuplot.h"
#include "cpupiemarker.h"
CpuPieMarker::CpuPieMarker()
{
setZ( 1000 );
setRenderHint( QwtPlotItem::RenderAntialiased, true );
}
int CpuPieMarker::rtti() const
{
return QwtPlotItem::Rtti_PlotUserItem;
}
void CpuPieMarker::draw( QPainter *painter,
const QwtScaleMap &, const QwtScaleMap &,
const QRectF &rect ) const
{
const CpuPlot *cpuPlot = static_cast<CpuPlot *> ( plot() );
const QwtScaleMap yMap = cpuPlot->canvasMap( QwtPlot::yLeft );
const int margin = 5;
QRectF pieRect;
pieRect.setX( rect.x() + margin );
pieRect.setY( rect.y() + margin );
pieRect.setHeight( yMap.transform( 80.0 ) );
pieRect.setWidth( pieRect.height() );
const int dataType[] = { CpuPlot::User, CpuPlot::System, CpuPlot::Idle };
int angle = static_cast<int>( 5760 * 0.75 );
for ( unsigned int i = 0;
i < sizeof( dataType ) / sizeof( dataType[0] ); i++ )
{
const QwtPlotCurve *curve = cpuPlot->cpuCurve( dataType[i] );
if ( curve->dataSize() > 0 )
{
const int value = static_cast<int>( 5760 * curve->sample( 0 ).y() / 100.0 );
painter->save();
painter->setBrush( QBrush( curve->brush().color(), Qt::SolidPattern ) );
if ( value != 0 )
painter->drawPie( pieRect, -angle, -value );
painter->restore();
angle += value;
}
}
}

View File

@ -0,0 +1,17 @@
//-----------------------------------------------------------------
// This class shows how to extend QwtPlotItems. It displays a
// pie chart of user/total/idle cpu usage in percent.
//-----------------------------------------------------------------
#include <qwt_plot_item.h>
class CpuPieMarker: public QwtPlotItem
{
public:
CpuPieMarker();
virtual int rtti() const;
virtual void draw( QPainter *,
const QwtScaleMap &, const QwtScaleMap &, const QRectF & ) const;
};

View File

@ -0,0 +1,254 @@
#include <qapplication.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qpainter.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_curve.h>
#include <qwt_scale_draw.h>
#include <qwt_scale_widget.h>
#include <qwt_legend.h>
#include <qwt_legend_label.h>
#include <qwt_plot_canvas.h>
#include "cpupiemarker.h"
#include "cpuplot.h"
class TimeScaleDraw: public QwtScaleDraw
{
public:
TimeScaleDraw( const QTime &base ):
baseTime( base )
{
}
virtual QwtText label( double v ) const
{
QTime upTime = baseTime.addSecs( static_cast<int>( v ) );
return upTime.toString();
}
private:
QTime baseTime;
};
class Background: public QwtPlotItem
{
public:
Background()
{
setZ( 0.0 );
}
virtual int rtti() const
{
return QwtPlotItem::Rtti_PlotUserItem;
}
virtual void draw( QPainter *painter,
const QwtScaleMap &, const QwtScaleMap &yMap,
const QRectF &canvasRect ) const
{
QColor c( Qt::white );
QRectF r = canvasRect;
for ( int i = 100; i > 0; i -= 10 )
{
r.setBottom( yMap.transform( i - 10 ) );
r.setTop( yMap.transform( i ) );
painter->fillRect( r, c );
c = c.dark( 110 );
}
}
};
class CpuCurve: public QwtPlotCurve
{
public:
CpuCurve( const QString &title ):
QwtPlotCurve( title )
{
setRenderHint( QwtPlotItem::RenderAntialiased );
}
void setColor( const QColor &color )
{
QColor c = color;
c.setAlpha( 150 );
setPen( QPen( Qt::NoPen ) );
setBrush( c );
}
};
CpuPlot::CpuPlot( QWidget *parent ):
QwtPlot( parent ),
dataCount( 0 )
{
setAutoReplot( false );
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setBorderRadius( 10 );
setCanvas( canvas );
plotLayout()->setAlignCanvasToScales( true );
QwtLegend *legend = new QwtLegend;
legend->setDefaultItemMode( QwtLegendData::Checkable );
insertLegend( legend, QwtPlot::RightLegend );
setAxisTitle( QwtPlot::xBottom, " System Uptime [h:m:s]" );
setAxisScaleDraw( QwtPlot::xBottom,
new TimeScaleDraw( cpuStat.upTime() ) );
setAxisScale( QwtPlot::xBottom, 0, HISTORY );
setAxisLabelRotation( QwtPlot::xBottom, -50.0 );
setAxisLabelAlignment( QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom );
/*
In situations, when there is a label at the most right position of the
scale, additional space is needed to display the overlapping part
of the label would be taken by reducing the width of scale and canvas.
To avoid this "jumping canvas" effect, we add a permanent margin.
We don't need to do the same for the left border, because there
is enough space for the overlapping label below the left scale.
*/
QwtScaleWidget *scaleWidget = axisWidget( QwtPlot::xBottom );
const int fmh = QFontMetrics( scaleWidget->font() ).height();
scaleWidget->setMinBorderDist( 0, fmh / 2 );
setAxisTitle( QwtPlot::yLeft, "Cpu Usage [%]" );
setAxisScale( QwtPlot::yLeft, 0, 100 );
Background *bg = new Background();
bg->attach( this );
CpuPieMarker *pie = new CpuPieMarker();
pie->attach( this );
CpuCurve *curve;
curve = new CpuCurve( "System" );
curve->setColor( Qt::red );
curve->attach( this );
data[System].curve = curve;
curve = new CpuCurve( "User" );
curve->setColor( Qt::blue );
curve->setZ( curve->z() - 1 );
curve->attach( this );
data[User].curve = curve;
curve = new CpuCurve( "Total" );
curve->setColor( Qt::black );
curve->setZ( curve->z() - 2 );
curve->attach( this );
data[Total].curve = curve;
curve = new CpuCurve( "Idle" );
curve->setColor( Qt::darkCyan );
curve->setZ( curve->z() - 3 );
curve->attach( this );
data[Idle].curve = curve;
showCurve( data[System].curve, true );
showCurve( data[User].curve, true );
showCurve( data[Total].curve, false );
showCurve( data[Idle].curve, false );
for ( int i = 0; i < HISTORY; i++ )
timeData[HISTORY - 1 - i] = i;
( void )startTimer( 1000 ); // 1 second
connect( legend, SIGNAL( checked( const QVariant &, bool, int ) ),
SLOT( legendChecked( const QVariant &, bool ) ) );
}
void CpuPlot::timerEvent( QTimerEvent * )
{
for ( int i = dataCount; i > 0; i-- )
{
for ( int c = 0; c < NCpuData; c++ )
{
if ( i < HISTORY )
data[c].data[i] = data[c].data[i-1];
}
}
cpuStat.statistic( data[User].data[0], data[System].data[0] );
data[Total].data[0] = data[User].data[0] + data[System].data[0];
data[Idle].data[0] = 100.0 - data[Total].data[0];
if ( dataCount < HISTORY )
dataCount++;
for ( int j = 0; j < HISTORY; j++ )
timeData[j]++;
setAxisScale( QwtPlot::xBottom,
timeData[HISTORY - 1], timeData[0] );
for ( int c = 0; c < NCpuData; c++ )
{
data[c].curve->setRawSamples(
timeData, data[c].data, dataCount );
}
replot();
}
void CpuPlot::legendChecked( const QVariant &itemInfo, bool on )
{
QwtPlotItem *plotItem = infoToItem( itemInfo );
if ( plotItem )
showCurve( plotItem, on );
}
void CpuPlot::showCurve( QwtPlotItem *item, bool on )
{
item->setVisible( on );
QwtLegend *lgd = qobject_cast<QwtLegend *>( legend() );
QList<QWidget *> legendWidgets =
lgd->legendWidgets( itemToInfo( item ) );
if ( legendWidgets.size() == 1 )
{
QwtLegendLabel *legendLabel =
qobject_cast<QwtLegendLabel *>( legendWidgets[0] );
if ( legendLabel )
legendLabel->setChecked( on );
}
replot();
}
int main( int argc, char **argv )
{
QApplication a( argc, argv );
QWidget vBox;
vBox.setWindowTitle( "Cpu Plot" );
CpuPlot *plot = new CpuPlot( &vBox );
plot->setTitle( "History" );
const int margin = 5;
plot->setContentsMargins( margin, margin, margin, margin );
QString info( "Press the legend to en/disable a curve" );
QLabel *label = new QLabel( info, &vBox );
QVBoxLayout *layout = new QVBoxLayout( &vBox );
layout->addWidget( plot );
layout->addWidget( label );
vBox.resize( 600, 400 );
vBox.show();
return a.exec();
}

View File

@ -0,0 +1,47 @@
#include <qwt_plot.h>
#include "cpustat.h"
#define HISTORY 60 // seconds
class QwtPlotCurve;
class CpuPlot : public QwtPlot
{
Q_OBJECT
public:
enum CpuData
{
User,
System,
Total,
Idle,
NCpuData
};
CpuPlot( QWidget * = 0 );
const QwtPlotCurve *cpuCurve( int id ) const
{
return data[id].curve;
}
protected:
void timerEvent( QTimerEvent *e );
private Q_SLOTS:
void legendChecked( const QVariant &, bool on );
private:
void showCurve( QwtPlotItem *, bool on );
struct
{
QwtPlotCurve *curve;
double data[HISTORY];
} data[NCpuData];
double timeData[HISTORY];
int dataCount;
CpuStat cpuStat;
};

View File

@ -0,0 +1,21 @@
TARGET = cpuplot
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
cpuplot.h \
cpustat.h \
cpupiemarker.h
SOURCES = \
cpuplot.cpp \
cpustat.cpp \
cpupiemarker.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,224 @@
#include <qstringlist.h>
#include <qfile.h>
#include <qtextstream.h>
#include "cpustat.h"
CpuStat::CpuStat()
{
lookUp( procValues );
}
QTime CpuStat::upTime() const
{
QTime t( 0, 0, 0 );
for ( int i = 0; i < NValues; i++ )
t = t.addSecs( int( procValues[i] / 100 ) );
return t;
}
void CpuStat::statistic( double &user, double &system )
{
double values[NValues];
lookUp( values );
double userDelta = values[User] + values[Nice]
- procValues[User] - procValues[Nice];
double systemDelta = values[System] - procValues[System];
double totalDelta = 0;
for ( int i = 0; i < NValues; i++ )
totalDelta += values[i] - procValues[i];
user = userDelta / totalDelta * 100.0;
system = systemDelta / totalDelta * 100.0;
for ( int j = 0; j < NValues; j++ )
procValues[j] = values[j];
}
void CpuStat::lookUp( double values[NValues] ) const
{
QFile file( "/proc/stat" );
#if 1
if ( !file.open( QIODevice::ReadOnly ) )
#else
if ( true )
#endif
{
static double dummyValues[][NValues] =
{
{ 103726, 0, 23484, 819556 },
{ 103783, 0, 23489, 819604 },
{ 103798, 0, 23490, 819688 },
{ 103820, 0, 23490, 819766 },
{ 103840, 0, 23493, 819843 },
{ 103875, 0, 23499, 819902 },
{ 103917, 0, 23504, 819955 },
{ 103950, 0, 23508, 820018 },
{ 103987, 0, 23510, 820079 },
{ 104020, 0, 23513, 820143 },
{ 104058, 0, 23514, 820204 },
{ 104099, 0, 23520, 820257 },
{ 104121, 0, 23525, 820330 },
{ 104159, 0, 23530, 820387 },
{ 104176, 0, 23534, 820466 },
{ 104215, 0, 23538, 820523 },
{ 104245, 0, 23541, 820590 },
{ 104267, 0, 23545, 820664 },
{ 104311, 0, 23555, 820710 },
{ 104355, 0, 23565, 820756 },
{ 104367, 0, 23567, 820842 },
{ 104383, 0, 23572, 820921 },
{ 104396, 0, 23577, 821003 },
{ 104413, 0, 23579, 821084 },
{ 104446, 0, 23588, 821142 },
{ 104521, 0, 23594, 821161 },
{ 104611, 0, 23604, 821161 },
{ 104708, 0, 23607, 821161 },
{ 104804, 0, 23611, 821161 },
{ 104895, 0, 23620, 821161 },
{ 104993, 0, 23622, 821161 },
{ 105089, 0, 23626, 821161 },
{ 105185, 0, 23630, 821161 },
{ 105281, 0, 23634, 821161 },
{ 105379, 0, 23636, 821161 },
{ 105472, 0, 23643, 821161 },
{ 105569, 0, 23646, 821161 },
{ 105666, 0, 23649, 821161 },
{ 105763, 0, 23652, 821161 },
{ 105828, 0, 23661, 821187 },
{ 105904, 0, 23666, 821206 },
{ 105999, 0, 23671, 821206 },
{ 106094, 0, 23676, 821206 },
{ 106184, 0, 23686, 821206 },
{ 106273, 0, 23692, 821211 },
{ 106306, 0, 23700, 821270 },
{ 106341, 0, 23703, 821332 },
{ 106392, 0, 23709, 821375 },
{ 106423, 0, 23715, 821438 },
{ 106472, 0, 23721, 821483 },
{ 106531, 0, 23727, 821517 },
{ 106562, 0, 23732, 821582 },
{ 106597, 0, 23736, 821643 },
{ 106633, 0, 23737, 821706 },
{ 106666, 0, 23742, 821768 },
{ 106697, 0, 23744, 821835 },
{ 106730, 0, 23748, 821898 },
{ 106765, 0, 23751, 821960 },
{ 106799, 0, 23754, 822023 },
{ 106831, 0, 23758, 822087 },
{ 106862, 0, 23761, 822153 },
{ 106899, 0, 23763, 822214 },
{ 106932, 0, 23766, 822278 },
{ 106965, 0, 23768, 822343 },
{ 107009, 0, 23771, 822396 },
{ 107040, 0, 23775, 822461 },
{ 107092, 0, 23780, 822504 },
{ 107143, 0, 23787, 822546 },
{ 107200, 0, 23795, 822581 },
{ 107250, 0, 23803, 822623 },
{ 107277, 0, 23810, 822689 },
{ 107286, 0, 23810, 822780 },
{ 107313, 0, 23817, 822846 },
{ 107325, 0, 23818, 822933 },
{ 107332, 0, 23818, 823026 },
{ 107344, 0, 23821, 823111 },
{ 107357, 0, 23821, 823198 },
{ 107368, 0, 23823, 823284 },
{ 107375, 0, 23824, 823377 },
{ 107386, 0, 23825, 823465 },
{ 107396, 0, 23826, 823554 },
{ 107422, 0, 23830, 823624 },
{ 107434, 0, 23831, 823711 },
{ 107456, 0, 23835, 823785 },
{ 107468, 0, 23838, 823870 },
{ 107487, 0, 23840, 823949 },
{ 107515, 0, 23843, 824018 },
{ 107528, 0, 23846, 824102 },
{ 107535, 0, 23851, 824190 },
{ 107548, 0, 23853, 824275 },
{ 107562, 0, 23857, 824357 },
{ 107656, 0, 23863, 824357 },
{ 107751, 0, 23868, 824357 },
{ 107849, 0, 23870, 824357 },
{ 107944, 0, 23875, 824357 },
{ 108043, 0, 23876, 824357 },
{ 108137, 0, 23882, 824357 },
{ 108230, 0, 23889, 824357 },
{ 108317, 0, 23902, 824357 },
{ 108412, 0, 23907, 824357 },
{ 108511, 0, 23908, 824357 },
{ 108608, 0, 23911, 824357 },
{ 108704, 0, 23915, 824357 },
{ 108801, 0, 23918, 824357 },
{ 108891, 0, 23928, 824357 },
{ 108987, 0, 23932, 824357 },
{ 109072, 0, 23943, 824361 },
{ 109079, 0, 23943, 824454 },
{ 109086, 0, 23944, 824546 },
{ 109098, 0, 23950, 824628 },
{ 109108, 0, 23955, 824713 },
{ 109115, 0, 23957, 824804 },
{ 109122, 0, 23958, 824896 },
{ 109132, 0, 23959, 824985 },
{ 109142, 0, 23961, 825073 },
{ 109146, 0, 23962, 825168 },
{ 109153, 0, 23964, 825259 },
{ 109162, 0, 23966, 825348 },
{ 109168, 0, 23969, 825439 },
{ 109176, 0, 23971, 825529 },
{ 109185, 0, 23974, 825617 },
{ 109193, 0, 23977, 825706 },
{ 109198, 0, 23978, 825800 },
{ 109206, 0, 23978, 825892 },
{ 109212, 0, 23981, 825983 },
{ 109219, 0, 23981, 826076 },
{ 109225, 0, 23981, 826170 },
{ 109232, 0, 23984, 826260 },
{ 109242, 0, 23984, 826350 },
{ 109255, 0, 23986, 826435 },
{ 109268, 0, 23987, 826521 },
{ 109283, 0, 23990, 826603 },
{ 109288, 0, 23991, 826697 },
{ 109295, 0, 23993, 826788 },
{ 109308, 0, 23994, 826874 },
{ 109322, 0, 24009, 826945 },
{ 109328, 0, 24011, 827037 },
{ 109338, 0, 24012, 827126 },
{ 109347, 0, 24012, 827217 },
{ 109354, 0, 24017, 827305 },
{ 109367, 0, 24017, 827392 },
{ 109371, 0, 24019, 827486 },
};
static int counter = 0;
for ( int i = 0; i < NValues; i++ )
values[i] = dummyValues[counter][i];
counter = ( counter + 1 )
% ( sizeof( dummyValues ) / sizeof( dummyValues[0] ) );
}
else
{
QTextStream textStream( &file );
do
{
QString line = textStream.readLine();
line = line.trimmed();
if ( line.startsWith( "cpu " ) )
{
const QStringList valueList =
line.split( " ", QString::SkipEmptyParts );
if ( valueList.count() >= 5 )
{
for ( int i = 0; i < NValues; i++ )
values[i] = valueList[i+1].toDouble();
}
break;
}
}
while( !textStream.atEnd() );
}
}

View File

@ -0,0 +1,23 @@
#include <qdatetime.h>
class CpuStat
{
public:
CpuStat();
void statistic( double &user, double &system );
QTime upTime() const;
enum Value
{
User,
Nice,
System,
Idle,
NValues
};
private:
void lookUp( double[NValues] ) const;
double procValues[NValues];
};

View File

@ -0,0 +1,202 @@
#include <qwt_scale_map.h>
#include <qwt_plot_curve.h>
#include <qwt_symbol.h>
#include <qwt_math.h>
#include <qcolor.h>
#include <qpainter.h>
#include <qapplication.h>
#include <qframe.h>
//------------------------------------------------------------
// curvdemo1
//
// This example program features some of the different
// display styles of the QwtPlotCurve class
//------------------------------------------------------------
//
// Array Sizes
//
const int Size = 27;
const int CurvCnt = 6;
//
// Arrays holding the values
//
double xval[Size];
double yval[Size];
QwtScaleMap xMap;
QwtScaleMap yMap;
class MainWin : public QFrame
{
public:
MainWin();
protected:
virtual void paintEvent( QPaintEvent * );
void drawContents( QPainter *p );
private:
void shiftDown( QRect &rect, int offset ) const;
QwtPlotCurve d_curves[CurvCnt];
};
MainWin::MainWin()
{
int i;
xMap.setScaleInterval( -0.5, 10.5 );
yMap.setScaleInterval( -1.1, 1.1 );
//
// Frame style
//
setFrameStyle( QFrame::Box | QFrame::Raised );
setLineWidth( 2 );
setMidLineWidth( 3 );
//
// Calculate values
//
for( i = 0; i < Size; i++ )
{
xval[i] = double( i ) * 10.0 / double( Size - 1 );
yval[i] = qSin( xval[i] ) * qCos( 2.0 * xval[i] );
}
//
// define curve styles
//
i = 0;
d_curves[i].setSymbol( new QwtSymbol( QwtSymbol::Cross, Qt::NoBrush,
QPen( Qt::black ), QSize( 5, 5 ) ) );
d_curves[i].setPen( Qt::darkGreen );
d_curves[i].setStyle( QwtPlotCurve::Lines );
d_curves[i].setCurveAttribute( QwtPlotCurve::Fitted );
i++;
d_curves[i].setSymbol( new QwtSymbol( QwtSymbol::Ellipse, Qt::yellow,
QPen( Qt::blue ), QSize( 5, 5 ) ) );
d_curves[i].setPen( Qt::red );
d_curves[i].setStyle( QwtPlotCurve::Sticks );
i++;
d_curves[i].setPen( Qt::darkBlue );
d_curves[i].setStyle( QwtPlotCurve::Lines );
i++;
d_curves[i].setPen( Qt::darkBlue );
d_curves[i].setStyle( QwtPlotCurve::Lines );
d_curves[i].setRenderHint( QwtPlotItem::RenderAntialiased );
i++;
d_curves[i].setPen( Qt::darkCyan );
d_curves[i].setStyle( QwtPlotCurve::Steps );
i++;
d_curves[i].setSymbol( new QwtSymbol( QwtSymbol::XCross, Qt::NoBrush,
QPen( Qt::darkMagenta ), QSize( 5, 5 ) ) );
d_curves[i].setStyle( QwtPlotCurve::NoCurve );
i++;
//
// attach data
//
for( i = 0; i < CurvCnt; i++ )
d_curves[i].setRawSamples( xval, yval, Size );
}
void MainWin::shiftDown( QRect &rect, int offset ) const
{
rect.translate( 0, offset );
}
void MainWin::paintEvent( QPaintEvent *event )
{
QFrame::paintEvent( event );
QPainter painter( this );
painter.setClipRect( contentsRect() );
drawContents( &painter );
}
//
// REDRAW CONTENTS
//
void MainWin::drawContents( QPainter *painter )
{
int deltay, i;
QRect r = contentsRect();
deltay = r.height() / CurvCnt - 1;
r.setHeight( deltay );
//
// draw curves
//
for ( i = 0; i < CurvCnt; i++ )
{
xMap.setPaintInterval( r.left(), r.right() );
yMap.setPaintInterval( r.top(), r.bottom() );
painter->setRenderHint( QPainter::Antialiasing,
d_curves[i].testRenderHint( QwtPlotItem::RenderAntialiased ) );
d_curves[i].draw( painter, xMap, yMap, r );
shiftDown( r, deltay );
}
//
// draw titles
//
r = contentsRect(); // reset r
painter->setFont( QFont( "Helvetica", 8 ) );
const int alignment = Qt::AlignTop | Qt::AlignHCenter;
painter->setPen( Qt::black );
painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),
alignment, "Style: Line/Fitted, Symbol: Cross" );
shiftDown( r, deltay );
painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),
alignment, "Style: Sticks, Symbol: Ellipse" );
shiftDown( r, deltay );
painter->drawText( 0 , r.top(), r.width(), painter->fontMetrics().height(),
alignment, "Style: Lines, Symbol: None" );
shiftDown( r, deltay );
painter->drawText( 0 , r.top(), r.width(), painter->fontMetrics().height(),
alignment, "Style: Lines, Symbol: None, Antialiased" );
shiftDown( r, deltay );
painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),
alignment, "Style: Steps, Symbol: None" );
shiftDown( r, deltay );
painter->drawText( 0, r.top(), r.width(), painter->fontMetrics().height(),
alignment, "Style: NoCurve, Symbol: XCross" );
}
int main ( int argc, char **argv )
{
QApplication a( argc, argv );
MainWin w;
w.resize( 300, 600 );
w.show();
return a.exec();
}

View File

@ -0,0 +1,14 @@
TARGET = curvdemo1
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
SOURCES = \
curvdemo1.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,127 @@
#include "attitude_indicator.h"
#include <qwt_point_polar.h>
#include <qwt_round_scale_draw.h>
#include <qevent.h>
#include <qpainter.h>
#include <qpolygon.h>
AttitudeIndicatorNeedle::AttitudeIndicatorNeedle( const QColor &color )
{
QPalette palette;
palette.setColor( QPalette::Text, color );
setPalette( palette );
}
void AttitudeIndicatorNeedle::drawNeedle( QPainter *painter,
double length, QPalette::ColorGroup colorGroup ) const
{
double triangleSize = length * 0.1;
double pos = length - 2.0;
QPainterPath path;
path.moveTo( pos, 0 );
path.lineTo( pos - 2 * triangleSize, triangleSize );
path.lineTo( pos - 2 * triangleSize, -triangleSize );
path.closeSubpath();
painter->setBrush( palette().brush( colorGroup, QPalette::Text ) );
painter->drawPath( path );
double l = length - 2;
painter->setPen( QPen( palette().color( colorGroup, QPalette::Text ), 3 ) );
painter->drawLine( QPointF( 0.0, -l ), QPointF( 0.0, l ) );
}
AttitudeIndicator::AttitudeIndicator(
QWidget *parent ):
QwtDial( parent ),
d_gradient( 0.0 )
{
QwtRoundScaleDraw *scaleDraw = new QwtRoundScaleDraw();
scaleDraw->enableComponent( QwtAbstractScaleDraw::Backbone, false );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Labels, false );
setScaleDraw( scaleDraw );
setMode( RotateScale );
setWrapping( true );
setOrigin( 270.0 );
setScaleMaxMinor( 0 );
setScaleStepSize( 30.0 );
setScale( 0.0, 360.0 );
const QColor color = palette().color( QPalette::Text );
setNeedle( new AttitudeIndicatorNeedle( color ) );
}
void AttitudeIndicator::setGradient( double gradient )
{
if ( gradient < -1.0 )
gradient = -1.0;
else if ( gradient > 1.0 )
gradient = 1.0;
if ( d_gradient != gradient )
{
d_gradient = gradient;
update();
}
}
void AttitudeIndicator::drawScale( QPainter *painter,
const QPointF &center, double radius ) const
{
const double offset = 4.0;
const QPointF p0 = qwtPolar2Pos( center, offset, 1.5 * M_PI );
const double w = innerRect().width();
QPainterPath path;
path.moveTo( qwtPolar2Pos( p0, w, 0.0 ) );
path.lineTo( qwtPolar2Pos( path.currentPosition(), 2 * w, M_PI ) );
path.lineTo( qwtPolar2Pos( path.currentPosition(), w, 0.5 * M_PI ) );
path.lineTo( qwtPolar2Pos( path.currentPosition(), w, 0.0 ) );
painter->save();
painter->setClipPath( path ); // swallow 180 - 360 degrees
QwtDial::drawScale( painter, center, radius );
painter->restore();
}
void AttitudeIndicator::drawScaleContents( QPainter *painter,
const QPointF &, double ) const
{
int dir = 360 - qRound( origin() - value() ); // counter clockwise
int arc = 90 + qRound( gradient() * 90 );
const QColor skyColor( 38, 151, 221 );
painter->save();
painter->setBrush( skyColor );
painter->drawChord( scaleInnerRect(),
( dir - arc ) * 16, 2 * arc * 16 );
painter->restore();
}
void AttitudeIndicator::keyPressEvent( QKeyEvent *event )
{
switch( event->key() )
{
case Qt::Key_Plus:
{
setGradient( gradient() + 0.05 );
break;
}
case Qt::Key_Minus:
{
setGradient( gradient() - 0.05 );
break;
}
default:
QwtDial::keyPressEvent( event );
}
}

View File

@ -0,0 +1,39 @@
#include <qwt_dial.h>
#include <qwt_dial_needle.h>
class AttitudeIndicatorNeedle: public QwtDialNeedle
{
public:
AttitudeIndicatorNeedle( const QColor & );
protected:
virtual void drawNeedle( QPainter *,
double length, QPalette::ColorGroup ) const;
};
class AttitudeIndicator: public QwtDial
{
Q_OBJECT
public:
AttitudeIndicator( QWidget *parent = NULL );
double angle() const { return value(); }
double gradient() const { return d_gradient; }
public Q_SLOTS:
void setGradient( double );
void setAngle( double angle ) { setValue( angle ); }
protected:
virtual void keyPressEvent( QKeyEvent * );
virtual void drawScale( QPainter *,
const QPointF &center, double radius ) const;
virtual void drawScaleContents( QPainter *painter,
const QPointF &center, double radius ) const;
private:
double d_gradient;
};

View File

@ -0,0 +1,186 @@
#include <qlayout.h>
#include <qtimer.h>
#include <qwt_analog_clock.h>
#include <qwt_round_scale_draw.h>
#include "attitude_indicator.h"
#include "speedo_meter.h"
#include "cockpit_grid.h"
CockpitGrid::CockpitGrid( QWidget *parent ):
QFrame( parent )
{
setAutoFillBackground( true );
setPalette( colorTheme( QColor( Qt::darkGray ).dark( 150 ) ) );
QGridLayout *layout = new QGridLayout( this );
layout->setSpacing( 5 );
layout->setMargin( 0 );
int i;
for ( i = 0; i < 3; i++ )
{
QwtDial *dial = createDial( i );
layout->addWidget( dial, 0, i );
}
for ( i = 0; i < layout->columnCount(); i++ )
layout->setColumnStretch( i, 1 );
}
QwtDial *CockpitGrid::createDial( int pos )
{
QwtDial *dial = NULL;
switch( pos )
{
case 0:
{
d_clock = new QwtAnalogClock( this );
#if 0
// disable minor ticks
d_clock->scaleDraw()->setTickLength( QwtScaleDiv::MinorTick, 0 );
#endif
const QColor knobColor = QColor( Qt::gray ).light( 130 );
for ( int i = 0; i < QwtAnalogClock::NHands; i++ )
{
QColor handColor = QColor( Qt::gray ).light( 150 );
int width = 8;
if ( i == QwtAnalogClock::SecondHand )
{
handColor = Qt::gray;
width = 5;
}
QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle(
QwtDialSimpleNeedle::Arrow, true, handColor, knobColor );
hand->setWidth( width );
d_clock->setHand( static_cast<QwtAnalogClock::Hand>( i ), hand );
}
QTimer *timer = new QTimer( d_clock );
timer->connect( timer, SIGNAL( timeout() ),
d_clock, SLOT( setCurrentTime() ) );
timer->start( 1000 );
dial = d_clock;
break;
}
case 1:
{
d_speedo = new SpeedoMeter( this );
d_speedo->setScaleStepSize( 20.0 );
d_speedo->setScale( 0.0, 240.0 );
d_speedo->scaleDraw()->setPenWidth( 2 );
QTimer *timer = new QTimer( d_speedo );
timer->connect( timer, SIGNAL( timeout() ),
this, SLOT( changeSpeed() ) );
timer->start( 50 );
dial = d_speedo;
break;
}
case 2:
{
d_ai = new AttitudeIndicator( this );
d_ai->scaleDraw()->setPenWidth( 3 );
QTimer *gradientTimer = new QTimer( d_ai );
gradientTimer->connect( gradientTimer, SIGNAL( timeout() ),
this, SLOT( changeGradient() ) );
gradientTimer->start( 100 );
QTimer *angleTimer = new QTimer( d_ai );
angleTimer->connect( angleTimer, SIGNAL( timeout() ),
this, SLOT( changeAngle() ) );
angleTimer->start( 100 );
dial = d_ai;
break;
}
}
if ( dial )
{
dial->setReadOnly( true );
dial->setLineWidth( 4 );
dial->setFrameShadow( QwtDial::Sunken );
}
return dial;
}
QPalette CockpitGrid::colorTheme( const QColor &base ) const
{
QPalette palette;
palette.setColor( QPalette::Base, base );
palette.setColor( QPalette::Window, base.dark( 150 ) );
palette.setColor( QPalette::Mid, base.dark( 110 ) );
palette.setColor( QPalette::Light, base.light( 170 ) );
palette.setColor( QPalette::Dark, base.dark( 170 ) );
palette.setColor( QPalette::Text, base.dark( 200 ).light( 800 ) );
palette.setColor( QPalette::WindowText, base.dark( 200 ) );
return palette;
}
void CockpitGrid::changeSpeed()
{
static double offset = 0.8;
double speed = d_speedo->value();
if ( ( speed < 7.0 && offset < 0.0 ) ||
( speed > 203.0 && offset > 0.0 ) )
{
offset = -offset;
}
static int counter = 0;
switch( counter++ % 12 )
{
case 0:
case 2:
case 7:
case 8:
break;
default:
d_speedo->setValue( speed + offset );
}
}
void CockpitGrid::changeAngle()
{
static double offset = 0.05;
double angle = d_ai->angle();
if ( angle > 180.0 )
angle -= 360.0;
if ( ( angle < -5.0 && offset < 0.0 ) ||
( angle > 5.0 && offset > 0.0 ) )
{
offset = -offset;
}
d_ai->setAngle( angle + offset );
}
void CockpitGrid::changeGradient()
{
static double offset = 0.005;
double gradient = d_ai->gradient();
if ( ( gradient < -0.05 && offset < 0.0 ) ||
( gradient > 0.05 && offset > 0.0 ) )
{
offset = -offset;
}
d_ai->setGradient( gradient + offset );
}

View File

@ -0,0 +1,28 @@
#include <qframe.h>
#include <qpalette.h>
class QwtDial;
class QwtAnalogClock;
class SpeedoMeter;
class AttitudeIndicator;
class CockpitGrid: public QFrame
{
Q_OBJECT
public:
CockpitGrid( QWidget *parent = NULL );
private Q_SLOTS:
void changeSpeed();
void changeGradient();
void changeAngle();
private:
QPalette colorTheme( const QColor & ) const;
QwtDial *createDial( int pos );
QwtAnalogClock *d_clock;
SpeedoMeter *d_speedo;
AttitudeIndicator *d_ai;
};

View File

@ -0,0 +1,226 @@
#include <qlayout.h>
#include <qwt_compass.h>
#include <qwt_compass_rose.h>
#include <qwt_dial_needle.h>
#include "compass_grid.h"
CompassGrid::CompassGrid( QWidget *parent ):
QFrame( parent )
{
QPalette p = palette();
p.setColor( backgroundRole(), Qt::gray );
setPalette( p );
setAutoFillBackground( true );
QGridLayout *layout = new QGridLayout( this );
layout->setSpacing( 5 );
layout->setMargin( 0 );
int i;
for ( i = 0; i < 6; i++ )
{
QwtCompass *compass = createCompass( i );
layout->addWidget( compass, i / 3, i % 3 );
}
for ( i = 0; i < layout->columnCount(); i++ )
layout->setColumnStretch( i, 1 );
}
QwtCompass *CompassGrid::createCompass( int pos )
{
int c;
QPalette palette0;
for ( c = 0; c < QPalette::NColorRoles; c++ )
{
const QPalette::ColorRole colorRole =
static_cast<QPalette::ColorRole>( c );
palette0.setColor( colorRole, QColor() );
}
palette0.setColor( QPalette::Base,
palette().color( backgroundRole() ).light( 120 ) );
palette0.setColor( QPalette::WindowText,
palette0.color( QPalette::Base ) );
QwtCompass *compass = new QwtCompass( this );
compass->setLineWidth( 4 );
compass->setFrameShadow(
pos <= 2 ? QwtCompass::Sunken : QwtCompass::Raised );
switch( pos )
{
case 0:
{
/*
A compass with a rose and no needle. Scale and rose are
rotating.
*/
compass->setMode( QwtCompass::RotateScale );
QwtSimpleCompassRose *rose = new QwtSimpleCompassRose( 16, 2 );
rose->setWidth( 0.15 );
compass->setRose( rose );
break;
}
case 1:
{
/*
A windrose, with a scale indicating the main directions only
*/
QMap<double, QString> map;
map.insert( 0.0, "N" );
map.insert( 90.0, "E" );
map.insert( 180.0, "S" );
map.insert( 270.0, "W" );
compass->setScaleDraw( new QwtCompassScaleDraw( map ) );
QwtSimpleCompassRose *rose = new QwtSimpleCompassRose( 4, 1 );
compass->setRose( rose );
compass->setNeedle(
new QwtCompassWindArrow( QwtCompassWindArrow::Style2 ) );
compass->setValue( 60.0 );
break;
}
case 2:
{
/*
A compass with a rotating needle in darkBlue. Shows
a ticks for each degree.
*/
palette0.setColor( QPalette::Base, Qt::darkBlue );
palette0.setColor( QPalette::WindowText,
QColor( Qt::darkBlue ).dark( 120 ) );
palette0.setColor( QPalette::Text, Qt::white );
QwtCompassScaleDraw *scaleDraw = new QwtCompassScaleDraw();
scaleDraw->enableComponent( QwtAbstractScaleDraw::Ticks, true );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Labels, true );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Backbone, false );
scaleDraw->setTickLength( QwtScaleDiv::MinorTick, 1 );
scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 1 );
scaleDraw->setTickLength( QwtScaleDiv::MajorTick, 3 );
compass->setScaleDraw( scaleDraw );
compass->setScaleMaxMajor( 36 );
compass->setScaleMaxMinor( 5 );
compass->setNeedle(
new QwtCompassMagnetNeedle( QwtCompassMagnetNeedle::ThinStyle ) );
compass->setValue( 220.0 );
break;
}
case 3:
{
/*
A compass without a frame, showing numbers as tick labels.
The origin is at 220.0
*/
palette0.setColor( QPalette::Base,
palette().color( backgroundRole() ) );
palette0.setColor( QPalette::WindowText, Qt::blue );
compass->setLineWidth( 0 );
QMap<double, QString> map;
for ( double d = 0.0; d < 360.0; d += 60.0 )
{
QString label;
label.sprintf( "%.0f", d );
map.insert( d, label );
}
QwtCompassScaleDraw *scaleDraw =
new QwtCompassScaleDraw( map );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Ticks, true );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Labels, true );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Backbone, true );
scaleDraw->setTickLength( QwtScaleDiv::MinorTick, 0 );
scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 0 );
scaleDraw->setTickLength( QwtScaleDiv::MajorTick, 3 );
compass->setScaleDraw( scaleDraw );
compass->setScaleMaxMajor( 36 );
compass->setScaleMaxMinor( 5 );
compass->setNeedle( new QwtDialSimpleNeedle( QwtDialSimpleNeedle::Ray,
true, Qt::white ) );
compass->setOrigin( 220.0 );
compass->setValue( 20.0 );
break;
}
case 4:
{
/*
A compass showing another needle
*/
QwtCompassScaleDraw *scaleDraw = new QwtCompassScaleDraw();
scaleDraw->enableComponent( QwtAbstractScaleDraw::Ticks, true );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Labels, true );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Backbone, false );
scaleDraw->setTickLength( QwtScaleDiv::MinorTick, 0 );
scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 0 );
scaleDraw->setTickLength( QwtScaleDiv::MajorTick, 3 );
compass->setScaleDraw( scaleDraw );
compass->setNeedle( new QwtCompassMagnetNeedle(
QwtCompassMagnetNeedle::TriangleStyle, Qt::white, Qt::red ) );
compass->setValue( 220.0 );
break;
}
case 5:
{
/*
A compass with a yellow on black ray
*/
palette0.setColor( QPalette::WindowText, Qt::black );
compass->setNeedle( new QwtDialSimpleNeedle( QwtDialSimpleNeedle::Ray,
false, Qt::yellow ) );
compass->setValue( 315.0 );
break;
}
}
QPalette newPalette = compass->palette();
for ( c = 0; c < QPalette::NColorRoles; c++ )
{
const QPalette::ColorRole colorRole =
static_cast<QPalette::ColorRole>( c );
if ( palette0.color( colorRole ).isValid() )
newPalette.setColor( colorRole, palette0.color( colorRole ) );
}
for ( int i = 0; i < QPalette::NColorGroups; i++ )
{
const QPalette::ColorGroup colorGroup =
static_cast<QPalette::ColorGroup>( i );
const QColor light =
newPalette.color( colorGroup, QPalette::Base ).light( 170 );
const QColor dark = newPalette.color( colorGroup, QPalette::Base ).dark( 170 );
const QColor mid = compass->frameShadow() == QwtDial::Raised
? newPalette.color( colorGroup, QPalette::Base ).dark( 110 )
: newPalette.color( colorGroup, QPalette::Base ).light( 110 );
newPalette.setColor( colorGroup, QPalette::Dark, dark );
newPalette.setColor( colorGroup, QPalette::Mid, mid );
newPalette.setColor( colorGroup, QPalette::Light, light );
}
compass->setPalette( newPalette );
return compass;
}

View File

@ -0,0 +1,11 @@
#include <qframe.h>
class QwtCompass;
class CompassGrid: public QFrame
{
public:
CompassGrid( QWidget *parent = NULL );
private:
QwtCompass *createCompass( int pos );
};

View File

@ -0,0 +1,24 @@
#include <qapplication.h>
#include <qtabwidget.h>
#include "compass_grid.h"
#include "cockpit_grid.h"
//-----------------------------------------------------------------
//
// dials.cpp -- A demo program featuring QwtDial and friends
//
//-----------------------------------------------------------------
int main ( int argc, char **argv )
{
QApplication a( argc, argv );
QTabWidget tabWidget;
tabWidget.addTab( new CompassGrid, "Compass" );
tabWidget.addTab( new CockpitGrid, "Cockpit" );
tabWidget.show();
return a.exec();
}

View File

@ -0,0 +1,24 @@
TARGET = dials
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
attitude_indicator.h \
speedo_meter.h \
cockpit_grid.h \
compass_grid.h
SOURCES = \
attitude_indicator.cpp \
speedo_meter.cpp \
cockpit_grid.cpp \
compass_grid.cpp \
dials.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,52 @@
#include <qpainter.h>
#include <qwt_dial_needle.h>
#include <qwt_round_scale_draw.h>
#include "speedo_meter.h"
SpeedoMeter::SpeedoMeter( QWidget *parent ):
QwtDial( parent ),
d_label( "km/h" )
{
QwtRoundScaleDraw *scaleDraw = new QwtRoundScaleDraw();
scaleDraw->setSpacing( 8 );
scaleDraw->enableComponent( QwtAbstractScaleDraw::Backbone, false );
scaleDraw->setTickLength( QwtScaleDiv::MinorTick, 0 );
scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 4 );
scaleDraw->setTickLength( QwtScaleDiv::MajorTick, 8 );
setScaleDraw( scaleDraw );
setWrapping( false );
setReadOnly( true );
setOrigin( 135.0 );
setScaleArc( 0.0, 270.0 );
QwtDialSimpleNeedle *needle = new QwtDialSimpleNeedle(
QwtDialSimpleNeedle::Arrow, true, Qt::red,
QColor( Qt::gray ).light( 130 ) );
setNeedle( needle );
}
void SpeedoMeter::setLabel( const QString &label )
{
d_label = label;
update();
}
QString SpeedoMeter::label() const
{
return d_label;
}
void SpeedoMeter::drawScaleContents( QPainter *painter,
const QPointF &center, double radius ) const
{
QRectF rect( 0.0, 0.0, 2.0 * radius, 2.0 * radius - 10.0 );
rect.moveCenter( center );
const QColor color = palette().color( QPalette::Text );
painter->setPen( color );
const int flags = Qt::AlignBottom | Qt::AlignHCenter;
painter->drawText( rect, flags, d_label );
}

View File

@ -0,0 +1,18 @@
#include <qstring.h>
#include <qwt_dial.h>
class SpeedoMeter: public QwtDial
{
public:
SpeedoMeter( QWidget *parent = NULL );
void setLabel( const QString & );
QString label() const;
protected:
virtual void drawScaleContents( QPainter *painter,
const QPointF &center, double radius ) const;
private:
QString d_label;
};

View File

@ -0,0 +1,196 @@
#include "barchart.h"
#include <qwt_plot_renderer.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_barchart.h>
#include <qwt_column_symbol.h>
#include <qwt_plot_layout.h>
#include <qwt_legend.h>
#include <qwt_scale_draw.h>
class DistroScaleDraw: public QwtScaleDraw
{
public:
DistroScaleDraw( Qt::Orientation orientation, const QStringList &labels ):
d_labels( labels )
{
setTickLength( QwtScaleDiv::MinorTick, 0 );
setTickLength( QwtScaleDiv::MediumTick, 0 );
setTickLength( QwtScaleDiv::MajorTick, 2 );
enableComponent( QwtScaleDraw::Backbone, false );
if ( orientation == Qt::Vertical )
{
setLabelRotation( -60.0 );
}
else
{
setLabelRotation( -20.0 );
}
setLabelAlignment( Qt::AlignLeft | Qt::AlignVCenter );
}
virtual QwtText label( double value ) const
{
QwtText lbl;
const int index = qRound( value );
if ( index >= 0 && index < d_labels.size() )
{
lbl = d_labels[ index ];
}
return lbl;
}
private:
const QStringList d_labels;
};
class DistroChartItem: public QwtPlotBarChart
{
public:
DistroChartItem():
QwtPlotBarChart( "Page Hits" )
{
setLegendMode( QwtPlotBarChart::LegendBarTitles );
setLegendIconSize( QSize( 10, 14 ) );
setLayoutPolicy( AutoAdjustSamples );
setLayoutHint( 4.0 ); // minimum width for a single bar
setSpacing( 10 ); // spacing between bars
}
void addDistro( const QString &distro, const QColor &color )
{
d_colors += color;
d_distros += distro;
itemChanged();
}
virtual QwtColumnSymbol *specialSymbol(
int index, const QPointF& ) const
{
// we want to have individual colors for each bar
QwtColumnSymbol *symbol = new QwtColumnSymbol( QwtColumnSymbol::Box );
symbol->setLineWidth( 2 );
symbol->setFrameStyle( QwtColumnSymbol::Raised );
QColor c( Qt::white );
if ( index >= 0 && index < d_colors.size() )
c = d_colors[ index ];
symbol->setPalette( c );
return symbol;
}
virtual QwtText barTitle( int sampleIndex ) const
{
QwtText title;
if ( sampleIndex >= 0 && sampleIndex < d_distros.size() )
title = d_distros[ sampleIndex ];
return title;
}
private:
QList<QColor> d_colors;
QList<QString> d_distros;
};
BarChart::BarChart( QWidget *parent ):
QwtPlot( parent )
{
const struct
{
const char *distro;
const int hits;
QColor color;
} pageHits[] =
{
{ "Arch", 1114, QColor( "DodgerBlue" ) },
{ "Debian", 1373, QColor( "#d70751" ) },
{ "Fedora", 1638, QColor( "SteelBlue" ) },
{ "Mageia", 1395, QColor( "Indigo" ) },
{ "Mint", 3874, QColor( 183, 255, 183 ) },
{ "openSuSE", 1532, QColor( 115, 186, 37 ) },
{ "Puppy", 1059, QColor( "LightSkyBlue" ) },
{ "Ubuntu", 2391, QColor( "FireBrick" ) }
};
setAutoFillBackground( true );
setPalette( QColor( "Linen" ) );
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setLineWidth( 2 );
canvas->setFrameStyle( QFrame::Box | QFrame::Sunken );
canvas->setBorderRadius( 10 );
QPalette canvasPalette( QColor( "Plum" ) );
canvasPalette.setColor( QPalette::Foreground, QColor( "Indigo" ) );
canvas->setPalette( canvasPalette );
setCanvas( canvas );
setTitle( "DistroWatch Page Hit Ranking, April 2012" );
d_barChartItem = new DistroChartItem();
QVector< double > samples;
for ( uint i = 0; i < sizeof( pageHits ) / sizeof( pageHits[ 0 ] ); i++ )
{
d_distros += pageHits[ i ].distro;
samples += pageHits[ i ].hits;
d_barChartItem->addDistro(
pageHits[ i ].distro, pageHits[ i ].color );
}
d_barChartItem->setSamples( samples );
d_barChartItem->attach( this );
insertLegend( new QwtLegend() );
setOrientation( 0 );
setAutoReplot( false );
}
void BarChart::setOrientation( int o )
{
const Qt::Orientation orientation =
( o == 0 ) ? Qt::Vertical : Qt::Horizontal;
int axis1 = QwtPlot::xBottom;
int axis2 = QwtPlot::yLeft;
if ( orientation == Qt::Horizontal )
qSwap( axis1, axis2 );
d_barChartItem->setOrientation( orientation );
setAxisTitle( axis1, "Distros" );
setAxisMaxMinor( axis1, 3 );
setAxisScaleDraw( axis1, new DistroScaleDraw( orientation, d_distros ) );
setAxisTitle( axis2, "Hits per day ( HPD )" );
setAxisMaxMinor( axis2, 3 );
QwtScaleDraw *scaleDraw = new QwtScaleDraw();
scaleDraw->setTickLength( QwtScaleDiv::MediumTick, 4 );
setAxisScaleDraw( axis2, scaleDraw );
plotLayout()->setCanvasMargin( 0 );
replot();
}
void BarChart::exportChart()
{
QwtPlotRenderer renderer;
renderer.exportTo( this, "distrowatch.pdf" );
}

View File

@ -0,0 +1,26 @@
#ifndef _BAR_CHART_H_
#include <qwt_plot.h>
#include <qstringlist.h>
class DistroChartItem;
class BarChart: public QwtPlot
{
Q_OBJECT
public:
BarChart( QWidget * = NULL );
public Q_SLOTS:
void setOrientation( int );
void exportChart();
private:
void populate();
DistroChartItem *d_barChartItem;
QStringList d_distros;
};
#endif

View File

@ -0,0 +1,18 @@
TARGET = distrowatch
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
barchart.h
SOURCES = \
barchart.cpp \
main.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,54 @@
#include <qapplication.h>
#include <qmainwindow.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qcombobox.h>
#include "barchart.h"
class MainWindow: public QMainWindow
{
public:
MainWindow( QWidget * = NULL );
private:
BarChart *d_chart;
};
MainWindow::MainWindow( QWidget *parent ):
QMainWindow( parent )
{
d_chart = new BarChart( this );
setCentralWidget( d_chart );
QToolBar *toolBar = new QToolBar( this );
QComboBox *orientationBox = new QComboBox( toolBar );
orientationBox->addItem( "Vertical" );
orientationBox->addItem( "Horizontal" );
orientationBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
QToolButton *btnExport = new QToolButton( toolBar );
btnExport->setText( "Export" );
btnExport->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
connect( btnExport, SIGNAL( clicked() ), d_chart, SLOT( exportChart() ) );
toolBar->addWidget( orientationBox );
toolBar->addWidget( btnExport );
addToolBar( toolBar );
d_chart->setOrientation( orientationBox->currentIndex() );
connect( orientationBox, SIGNAL( currentIndexChanged( int ) ),
d_chart, SLOT( setOrientation( int ) ) );
}
int main( int argc, char **argv )
{
QApplication a( argc, argv );
MainWindow mainWindow;
mainWindow.resize( 600, 400 );
mainWindow.show();
return a.exec();
}

View File

@ -0,0 +1,27 @@
QwtPlot is a composite widget consisting of a title label,
the canvas, the scales and a legend. Although all components
should be exchangable some day, the current design isn´t ready for it.
In this situation event filtering is the mechanism to extend the behaviour
of the plot components. event_filter shows 3 examples how to use it:
1) CanvasPicker
The CanvasPicker implements a solution, how to move points on the canvas
with mouse and keyboard.
2) ScalePicker
The ScalePicker translates the position of mouse clicks on the scales
and emits them as signals.
3) Plot: ColorBar, QSlider
The Plot class shows how to add widgets to the scales. In this example
there is no filter class. The derived plot widget filters its components.
Please note that CanvasPicker and ScalePicker are standalone classes
that could be connected with your QwtPlot as well.
Uwe

View File

@ -0,0 +1,372 @@
#include <qapplication.h>
#include <qevent.h>
#include <qwhatsthis.h>
#include <qpainter.h>
#include <qwt_plot.h>
#include <qwt_symbol.h>
#include <qwt_scale_map.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_directpainter.h>
#include "canvaspicker.h"
CanvasPicker::CanvasPicker( QwtPlot *plot ):
QObject( plot ),
d_selectedCurve( NULL ),
d_selectedPoint( -1 )
{
QwtPlotCanvas *canvas = qobject_cast<QwtPlotCanvas *>( plot->canvas() );
canvas->installEventFilter( this );
// We want the focus, but no focus rect. The
// selected point will be highlighted instead.
canvas->setFocusPolicy( Qt::StrongFocus );
#ifndef QT_NO_CURSOR
canvas->setCursor( Qt::PointingHandCursor );
#endif
canvas->setFocusIndicator( QwtPlotCanvas::ItemFocusIndicator );
canvas->setFocus();
const char *text =
"All points can be moved using the left mouse button "
"or with these keys:\n\n"
"- Up:\t\tSelect next curve\n"
"- Down:\t\tSelect previous curve\n"
"- Left, ´-´:\tSelect next point\n"
"- Right, ´+´:\tSelect previous point\n"
"- 7, 8, 9, 4, 6, 1, 2, 3:\tMove selected point";
canvas->setWhatsThis( text );
shiftCurveCursor( true );
}
QwtPlot *CanvasPicker::plot()
{
return qobject_cast<QwtPlot *>( parent() );
}
const QwtPlot *CanvasPicker::plot() const
{
return qobject_cast<const QwtPlot *>( parent() );
}
bool CanvasPicker::event( QEvent *ev )
{
if ( ev->type() == QEvent::User )
{
showCursor( true );
return true;
}
return QObject::event( ev );
}
bool CanvasPicker::eventFilter( QObject *object, QEvent *event )
{
if ( plot() == NULL || object != plot()->canvas() )
return false;
switch( event->type() )
{
case QEvent::FocusIn:
{
showCursor( true );
break;
}
case QEvent::FocusOut:
{
showCursor( false );
break;
}
case QEvent::Paint:
{
QApplication::postEvent( this, new QEvent( QEvent::User ) );
break;
}
case QEvent::MouseButtonPress:
{
const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>( event );
select( mouseEvent->pos() );
return true;
}
case QEvent::MouseMove:
{
const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>( event );
move( mouseEvent->pos() );
return true;
}
case QEvent::KeyPress:
{
const QKeyEvent *keyEvent = static_cast<QKeyEvent *>( event );
const int delta = 5;
switch( keyEvent->key() )
{
case Qt::Key_Up:
{
shiftCurveCursor( true );
return true;
}
case Qt::Key_Down:
{
shiftCurveCursor( false );
return true;
}
case Qt::Key_Right:
case Qt::Key_Plus:
{
if ( d_selectedCurve )
shiftPointCursor( true );
else
shiftCurveCursor( true );
return true;
}
case Qt::Key_Left:
case Qt::Key_Minus:
{
if ( d_selectedCurve )
shiftPointCursor( false );
else
shiftCurveCursor( true );
return true;
}
// The following keys represent a direction, they are
// organized on the keyboard.
case Qt::Key_1:
{
moveBy( -delta, delta );
break;
}
case Qt::Key_2:
{
moveBy( 0, delta );
break;
}
case Qt::Key_3:
{
moveBy( delta, delta );
break;
}
case Qt::Key_4:
{
moveBy( -delta, 0 );
break;
}
case Qt::Key_6:
{
moveBy( delta, 0 );
break;
}
case Qt::Key_7:
{
moveBy( -delta, -delta );
break;
}
case Qt::Key_8:
{
moveBy( 0, -delta );
break;
}
case Qt::Key_9:
{
moveBy( delta, -delta );
break;
}
default:
break;
}
}
default:
break;
}
return QObject::eventFilter( object, event );
}
// Select the point at a position. If there is no point
// deselect the selected point
void CanvasPicker::select( const QPoint &pos )
{
QwtPlotCurve *curve = NULL;
double dist = 10e10;
int index = -1;
const QwtPlotItemList& itmList = plot()->itemList();
for ( QwtPlotItemIterator it = itmList.begin();
it != itmList.end(); ++it )
{
if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve )
{
QwtPlotCurve *c = static_cast<QwtPlotCurve *>( *it );
double d;
int idx = c->closestPoint( pos, &d );
if ( d < dist )
{
curve = c;
index = idx;
dist = d;
}
}
}
showCursor( false );
d_selectedCurve = NULL;
d_selectedPoint = -1;
if ( curve && dist < 10 ) // 10 pixels tolerance
{
d_selectedCurve = curve;
d_selectedPoint = index;
showCursor( true );
}
}
// Move the selected point
void CanvasPicker::moveBy( int dx, int dy )
{
if ( dx == 0 && dy == 0 )
return;
if ( !d_selectedCurve )
return;
const QPointF sample =
d_selectedCurve->sample( d_selectedPoint );
const double x = plot()->transform(
d_selectedCurve->xAxis(), sample.x() );
const double y = plot()->transform(
d_selectedCurve->yAxis(), sample.y() );
move( QPoint( qRound( x + dx ), qRound( y + dy ) ) );
}
// Move the selected point
void CanvasPicker::move( const QPoint &pos )
{
if ( !d_selectedCurve )
return;
QVector<double> xData( d_selectedCurve->dataSize() );
QVector<double> yData( d_selectedCurve->dataSize() );
for ( int i = 0;
i < static_cast<int>( d_selectedCurve->dataSize() ); i++ )
{
if ( i == d_selectedPoint )
{
xData[i] = plot()->invTransform(
d_selectedCurve->xAxis(), pos.x() );
yData[i] = plot()->invTransform(
d_selectedCurve->yAxis(), pos.y() );
}
else
{
const QPointF sample = d_selectedCurve->sample( i );
xData[i] = sample.x();
yData[i] = sample.y();
}
}
d_selectedCurve->setSamples( xData, yData );
/*
Enable QwtPlotCanvas::ImmediatePaint, so that the canvas has been
updated before we paint the cursor on it.
*/
QwtPlotCanvas *plotCanvas =
qobject_cast<QwtPlotCanvas *>( plot()->canvas() );
plotCanvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, true );
plot()->replot();
plotCanvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, false );
showCursor( true );
}
// Hightlight the selected point
void CanvasPicker::showCursor( bool showIt )
{
if ( !d_selectedCurve )
return;
QwtSymbol *symbol = const_cast<QwtSymbol *>( d_selectedCurve->symbol() );
const QBrush brush = symbol->brush();
if ( showIt )
symbol->setBrush( symbol->brush().color().dark( 180 ) );
QwtPlotDirectPainter directPainter;
directPainter.drawSeries( d_selectedCurve, d_selectedPoint, d_selectedPoint );
if ( showIt )
symbol->setBrush( brush ); // reset brush
}
// Select the next/previous curve
void CanvasPicker::shiftCurveCursor( bool up )
{
QwtPlotItemIterator it;
const QwtPlotItemList &itemList = plot()->itemList();
QwtPlotItemList curveList;
for ( it = itemList.begin(); it != itemList.end(); ++it )
{
if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve )
curveList += *it;
}
if ( curveList.isEmpty() )
return;
it = curveList.begin();
if ( d_selectedCurve )
{
for ( it = curveList.begin(); it != curveList.end(); ++it )
{
if ( d_selectedCurve == *it )
break;
}
if ( it == curveList.end() ) // not found
it = curveList.begin();
if ( up )
{
++it;
if ( it == curveList.end() )
it = curveList.begin();
}
else
{
if ( it == curveList.begin() )
it = curveList.end();
--it;
}
}
showCursor( false );
d_selectedPoint = 0;
d_selectedCurve = static_cast<QwtPlotCurve *>( *it );
showCursor( true );
}
// Select the next/previous neighbour of the selected point
void CanvasPicker::shiftPointCursor( bool up )
{
if ( !d_selectedCurve )
return;
int index = d_selectedPoint + ( up ? 1 : -1 );
index = ( index + d_selectedCurve->dataSize() ) % d_selectedCurve->dataSize();
if ( index != d_selectedPoint )
{
showCursor( false );
d_selectedPoint = index;
showCursor( true );
}
}

View File

@ -0,0 +1,33 @@
#include <qobject.h>
class QPoint;
class QCustomEvent;
class QwtPlot;
class QwtPlotCurve;
class CanvasPicker: public QObject
{
Q_OBJECT
public:
CanvasPicker( QwtPlot *plot );
virtual bool eventFilter( QObject *, QEvent * );
virtual bool event( QEvent * );
private:
void select( const QPoint & );
void move( const QPoint & );
void moveBy( int dx, int dy );
void release();
void showCursor( bool enable );
void shiftPointCursor( bool up );
void shiftCurveCursor( bool up );
QwtPlot *plot();
const QwtPlot *plot() const;
QwtPlotCurve *d_selectedCurve;
int d_selectedPoint;
};

View File

@ -0,0 +1,112 @@
#include <qevent.h>
#include <qpixmap.h>
#include <qimage.h>
#include <qpainter.h>
#include "colorbar.h"
ColorBar::ColorBar( Qt::Orientation o, QWidget *parent ):
QWidget( parent ),
d_orientation( o ),
d_light( Qt::white ),
d_dark( Qt::black )
{
#ifndef QT_NO_CURSOR
setCursor( Qt::PointingHandCursor );
#endif
}
void ColorBar::setOrientation( Qt::Orientation o )
{
d_orientation = o;
update();
}
void ColorBar::setLight( const QColor &light )
{
d_light = light;
update();
}
void ColorBar::setDark( const QColor &dark )
{
d_dark = dark;
update();
}
void ColorBar::setRange( const QColor &light, const QColor &dark )
{
d_light = light;
d_dark = dark;
update();
}
void ColorBar::mousePressEvent( QMouseEvent *e )
{
if( e->button() == Qt::LeftButton )
{
// emit the color of the position where the mouse click
// happened
const QPixmap pm = QPixmap::grabWidget( this );
const QRgb rgb = pm.toImage().pixel( e->x(), e->y() );
Q_EMIT selected( QColor( rgb ) );
e->accept();
}
}
void ColorBar::paintEvent( QPaintEvent * )
{
QPainter painter( this );
drawColorBar( &painter, rect() );
}
void ColorBar::drawColorBar( QPainter *painter, const QRect &rect ) const
{
int h1, s1, v1;
int h2, s2, v2;
d_light.getHsv( &h1, &s1, &v1 );
d_dark.getHsv( &h2, &s2, &v2 );
painter->save();
painter->setClipRect( rect );
painter->setClipping( true );
painter->fillRect( rect, d_dark );
const int sectionSize = 2;
int numIntervals;
if ( d_orientation == Qt::Horizontal )
numIntervals = rect.width() / sectionSize;
else
numIntervals = rect.height() / sectionSize;
for ( int i = 0; i < numIntervals; i++ )
{
QRect section;
if ( d_orientation == Qt::Horizontal )
{
section.setRect( rect.x() + i * sectionSize, rect.y(),
sectionSize, rect.height() );
}
else
{
section.setRect( rect.x(), rect.y() + i * sectionSize,
rect.width(), sectionSize );
}
const double ratio = i / static_cast<double>( numIntervals );
QColor c;
c.setHsv( h1 + qRound( ratio * ( h2 - h1 ) ),
s1 + qRound( ratio * ( s2 - s1 ) ),
v1 + qRound( ratio * ( v2 - v1 ) ) );
painter->fillRect( section, c );
}
painter->restore();
}

View File

@ -0,0 +1,33 @@
#include <qwidget.h>
class ColorBar: public QWidget
{
Q_OBJECT
public:
ColorBar( Qt::Orientation = Qt::Horizontal, QWidget * = NULL );
virtual void setOrientation( Qt::Orientation );
Qt::Orientation orientation() const { return d_orientation; }
void setRange( const QColor &light, const QColor &dark );
void setLight( const QColor &light );
void setDark( const QColor &dark );
QColor light() const { return d_light; }
QColor dark() const { return d_dark; }
Q_SIGNALS:
void selected( const QColor & );
protected:
virtual void mousePressEvent( QMouseEvent * );
virtual void paintEvent( QPaintEvent * );
void drawColorBar( QPainter *, const QRect & ) const;
private:
Qt::Orientation d_orientation;
QColor d_light;
QColor d_dark;
};

View File

@ -0,0 +1,51 @@
//-----------------------------------------------------------------
// A demo program showing how to use event filtering
//-----------------------------------------------------------------
#include <qapplication.h>
#include <qmainwindow.h>
#include <qwhatsthis.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include "plot.h"
#include "canvaspicker.h"
#include "scalepicker.h"
int main ( int argc, char **argv )
{
QApplication a( argc, argv );
QMainWindow mainWindow;
QToolBar *toolBar = new QToolBar( &mainWindow );
QAction *action = QWhatsThis::createAction( toolBar );
toolBar->addAction( action );
mainWindow.addToolBar( toolBar );
Plot *plot = new Plot( &mainWindow );
// The canvas picker handles all mouse and key
// events on the plot canvas
( void ) new CanvasPicker( plot );
// The scale picker translates mouse clicks
// int o clicked() signals
ScalePicker *scalePicker = new ScalePicker( plot );
a.connect( scalePicker, SIGNAL( clicked( int, double ) ),
plot, SLOT( insertCurve( int, double ) ) );
mainWindow.setCentralWidget( plot );
mainWindow.resize( 540, 400 );
mainWindow.show();
const char *text =
"An useless plot to demonstrate how to use event filtering.\n\n"
"You can click on the color bar, the scales or move the wheel.\n"
"All points can be moved using the mouse or the keyboard.";
plot->setWhatsThis( text );
int rv = a.exec();
return rv;
}

View File

@ -0,0 +1,24 @@
TARGET = event_filter
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
colorbar.h \
scalepicker.h \
canvaspicker.h \
plot.h
SOURCES = \
colorbar.cpp \
scalepicker.cpp \
canvaspicker.cpp \
plot.cpp \
event_filter.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,176 @@
#include "plot.h"
#include "colorbar.h"
#include <qevent.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_curve.h>
#include <qwt_symbol.h>
#include <qwt_scale_widget.h>
#include <qwt_wheel.h>
#include <stdlib.h>
Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
setTitle( "Interactive Plot" );
setCanvasColor( Qt::darkCyan );
QwtPlotGrid *grid = new QwtPlotGrid;
grid->setMajorPen( Qt::white, 0, Qt::DotLine );
grid->attach( this );
// axes
setAxisScale( QwtPlot::xBottom, 0.0, 100.0 );
setAxisScale( QwtPlot::yLeft, 0.0, 100.0 );
// Avoid jumping when label with 3 digits
// appear/disappear when scrolling vertically
QwtScaleDraw *sd = axisScaleDraw( QwtPlot::yLeft );
sd->setMinimumExtent( sd->extent( axisWidget( QwtPlot::yLeft )->font() ) );
plotLayout()->setAlignCanvasToScales( true );
insertCurve( Qt::Vertical, Qt::blue, 30.0 );
insertCurve( Qt::Vertical, Qt::magenta, 70.0 );
insertCurve( Qt::Horizontal, Qt::yellow, 30.0 );
insertCurve( Qt::Horizontal, Qt::white, 70.0 );
replot();
// ------------------------------------
// We add a color bar to the left axis
// ------------------------------------
QwtScaleWidget *scaleWidget = axisWidget( yLeft );
scaleWidget->setMargin( 10 ); // area for the color bar
d_colorBar = new ColorBar( Qt::Vertical, scaleWidget );
d_colorBar->setRange( Qt::red, Qt::darkBlue );
d_colorBar->setFocusPolicy( Qt::TabFocus );
connect( d_colorBar, SIGNAL( selected( const QColor & ) ),
SLOT( setCanvasColor( const QColor & ) ) );
// we need the resize events, to lay out the color bar
scaleWidget->installEventFilter( this );
// ------------------------------------
// We add a wheel to the canvas
// ------------------------------------
d_wheel = new QwtWheel( canvas() );
d_wheel->setOrientation( Qt::Vertical );
d_wheel->setRange( -100, 100 );
d_wheel->setValue( 0.0 );
d_wheel->setMass( 0.2 );
d_wheel->setTotalAngle( 4 * 360.0 );
connect( d_wheel, SIGNAL( valueChanged( double ) ),
SLOT( scrollLeftAxis( double ) ) );
// we need the resize events, to lay out the wheel
canvas()->installEventFilter( this );
d_colorBar->setWhatsThis(
"Selecting a color will change the background of the plot." );
scaleWidget->setWhatsThis(
"Selecting a value at the scale will insert a new curve." );
d_wheel->setWhatsThis(
"With the wheel you can move the visible area." );
axisWidget( xBottom )->setWhatsThis(
"Selecting a value at the scale will insert a new curve." );
}
void Plot::setCanvasColor( const QColor &c )
{
setCanvasBackground( c );
replot();
}
void Plot::scrollLeftAxis( double value )
{
setAxisScale( yLeft, value, value + 100.0 );
replot();
}
bool Plot::eventFilter( QObject *object, QEvent *e )
{
if ( e->type() == QEvent::Resize )
{
const QSize size = static_cast<QResizeEvent *>( e )->size();
if ( object == axisWidget( yLeft ) )
{
const QwtScaleWidget *scaleWidget = axisWidget( yLeft );
const int margin = 2;
// adjust the color bar to the scale backbone
const int x = size.width() - scaleWidget->margin() + margin;
const int w = scaleWidget->margin() - 2 * margin;
const int y = scaleWidget->startBorderDist();
const int h = size.height() -
scaleWidget->startBorderDist() - scaleWidget->endBorderDist();
d_colorBar->setGeometry( x, y, w, h );
}
if ( object == canvas() )
{
const int w = 16;
const int h = 50;
const int margin = 2;
const QRect cr = canvas()->contentsRect();
d_wheel->setGeometry(
cr.right() - margin - w, cr.center().y() - h / 2, w, h );
}
}
return QwtPlot::eventFilter( object, e );
}
void Plot::insertCurve( int axis, double base )
{
Qt::Orientation o;
if ( axis == yLeft || axis == yRight )
o = Qt::Horizontal;
else
o = Qt::Vertical;
QRgb rgb = static_cast<QRgb>( rand() );
insertCurve( o, QColor( rgb ), base );
replot();
}
void Plot::insertCurve( Qt::Orientation o,
const QColor &c, double base )
{
QwtPlotCurve *curve = new QwtPlotCurve();
curve->setPen( c );
curve->setSymbol( new QwtSymbol( QwtSymbol::Ellipse,
Qt::gray, c, QSize( 8, 8 ) ) );
double x[10];
double y[sizeof( x ) / sizeof( x[0] )];
for ( uint i = 0; i < sizeof( x ) / sizeof( x[0] ); i++ )
{
double v = 5.0 + i * 10.0;
if ( o == Qt::Horizontal )
{
x[i] = v;
y[i] = base;
}
else
{
x[i] = base;
y[i] = v;
}
}
curve->setSamples( x, y, sizeof( x ) / sizeof( x[0] ) );
curve->attach( this );
}

View File

@ -0,0 +1,25 @@
#include <qwt_plot.h>
class ColorBar;
class QwtWheel;
class Plot: public QwtPlot
{
Q_OBJECT
public:
Plot( QWidget *parent = NULL );
virtual bool eventFilter( QObject *, QEvent * );
public Q_SLOTS:
void setCanvasColor( const QColor & );
void insertCurve( int axis, double base );
private Q_SLOTS:
void scrollLeftAxis( double );
private:
void insertCurve( Qt::Orientation, const QColor &, double base );
ColorBar *d_colorBar;
QwtWheel *d_wheel;
};

View File

@ -0,0 +1,119 @@
#include "scalepicker.h"
#include <qwt_plot.h>
#include <qwt_scale_widget.h>
#include <qevent.h>
#include <qmath.h>
ScalePicker::ScalePicker( QwtPlot *plot ):
QObject( plot )
{
for ( uint i = 0; i < QwtPlot::axisCnt; i++ )
{
QwtScaleWidget *scaleWidget = plot->axisWidget( i );
if ( scaleWidget )
scaleWidget->installEventFilter( this );
}
}
bool ScalePicker::eventFilter( QObject *object, QEvent *event )
{
if ( event->type() == QEvent::MouseButtonPress )
{
QwtScaleWidget *scaleWidget = qobject_cast<QwtScaleWidget *>( object );
if ( scaleWidget )
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>( event );
mouseClicked( scaleWidget, mouseEvent->pos() );
return true;
}
}
return QObject::eventFilter( object, event );
}
void ScalePicker::mouseClicked( const QwtScaleWidget *scale, const QPoint &pos )
{
QRect rect = scaleRect( scale );
int margin = 10; // 10 pixels tolerance
rect.setRect( rect.x() - margin, rect.y() - margin,
rect.width() + 2 * margin, rect.height() + 2 * margin );
if ( rect.contains( pos ) ) // No click on the title
{
// translate the position in a value on the scale
double value = 0.0;
int axis = -1;
const QwtScaleDraw *sd = scale->scaleDraw();
switch( scale->alignment() )
{
case QwtScaleDraw::LeftScale:
{
value = sd->scaleMap().invTransform( pos.y() );
axis = QwtPlot::yLeft;
break;
}
case QwtScaleDraw::RightScale:
{
value = sd->scaleMap().invTransform( pos.y() );
axis = QwtPlot::yRight;
break;
}
case QwtScaleDraw::BottomScale:
{
value = sd->scaleMap().invTransform( pos.x() );
axis = QwtPlot::xBottom;
break;
}
case QwtScaleDraw::TopScale:
{
value = sd->scaleMap().invTransform( pos.x() );
axis = QwtPlot::xTop;
break;
}
}
Q_EMIT clicked( axis, value );
}
}
// The rect of a scale without the title
QRect ScalePicker::scaleRect( const QwtScaleWidget *scale ) const
{
const int bld = scale->margin();
const int mjt = qCeil( scale->scaleDraw()->maxTickLength() );
const int sbd = scale->startBorderDist();
const int ebd = scale->endBorderDist();
QRect rect;
switch( scale->alignment() )
{
case QwtScaleDraw::LeftScale:
{
rect.setRect( scale->width() - bld - mjt, sbd,
mjt, scale->height() - sbd - ebd );
break;
}
case QwtScaleDraw::RightScale:
{
rect.setRect( bld, sbd,
mjt, scale->height() - sbd - ebd );
break;
}
case QwtScaleDraw::BottomScale:
{
rect.setRect( sbd, bld,
scale->width() - sbd - ebd, mjt );
break;
}
case QwtScaleDraw::TopScale:
{
rect.setRect( sbd, scale->height() - bld - mjt,
scale->width() - sbd - ebd, mjt );
break;
}
}
return rect;
}

View File

@ -0,0 +1,20 @@
#include <qobject.h>
#include <qrect.h>
class QwtPlot;
class QwtScaleWidget;
class ScalePicker: public QObject
{
Q_OBJECT
public:
ScalePicker( QwtPlot *plot );
virtual bool eventFilter( QObject *, QEvent * );
Q_SIGNALS:
void clicked( int axis, double value );
private:
void mouseClicked( const QwtScaleWidget *, const QPoint & );
QRect scaleRect( const QwtScaleWidget * ) const;
};

View File

@ -0,0 +1,26 @@
TEMPLATE = subdirs
SUBDIRS += \
animation \
barchart \
cpuplot \
curvdemo1 \
distrowatch \
friedberg \
itemeditor \
legends \
stockchart \
simpleplot \
sinusplot \
realtime \
refreshtest \
scatterplot \
spectrogram \
rasterview \
tvplot \
bode \
event_filter \
oscilloscope \
sysinfo \
radio \
dials \
controls

View File

@ -0,0 +1,20 @@
TARGET = friedberg
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
plot.h \
friedberg2007.h
SOURCES = \
friedberg2007.cpp \
plot.cpp \
main.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,384 @@
#include "friedberg2007.h"
// Temperature 2007 from Friedberg somewhere in Germany
// See: http://wetter61169.de
Temperature friedberg2007[] =
{
/* 01.01 */ Temperature( 2.6, 9.8, 7.07862 ),
/* 02.01 */ Temperature( 0.8, 5.8, 3.6993 ),
/* 03.01 */ Temperature( 2, 7, 5.02388 ),
/* 04.01 */ Temperature( 5.3, 7.8, 6.37778 ),
/* 05.01 */ Temperature( 5.6, 7.7, 6.83149 ),
/* 06.01 */ Temperature( 7.2, 8.9, 8.0816 ),
/* 07.01 */ Temperature( 4.2, 9.9, 7.54704 ),
/* 08.01 */ Temperature( 3.5, 8.9, 6.71951 ),
/* 09.01 */ Temperature( 8.2, 12.9, 10.8594 ),
/* 10.01 */ Temperature( 6.3, 11.9, 9.76424 ),
/* 11.01 */ Temperature( 3.9, 9.2, 6.18223 ),
/* 12.01 */ Temperature( 6.9, 9.7, 8.44236 ),
/* 13.01 */ Temperature( 9, 12.3, 10.6649 ),
/* 14.01 */ Temperature( 1.8, 10.8, 7.23438 ),
/* 15.01 */ Temperature( -2.8, 1.8, -0.518403 ),
/* 16.01 */ Temperature( -0.6, 4.5, 2.39479 ),
/* 17.01 */ Temperature( 4.3, 10.2, 7.23472 ),
/* 18.01 */ Temperature( 9.1, 13.6, 10.9316 ),
/* 19.01 */ Temperature( 6.9, 12.4, 9.4128 ),
/* 20.01 */ Temperature( 7.1, 13.3, 10.5083 ),
/* 21.01 */ Temperature( 3.5, 9.6, 6.10871 ),
/* 22.01 */ Temperature( -1.8, 6, 2.89028 ),
/* 23.01 */ Temperature( -5.4, 1.7, -2.46678 ),
/* 24.01 */ Temperature( -5.3, -1.3, -3.71483 ),
/* 25.01 */ Temperature( -7.5, 3.3, -3.36736 ),
/* 26.01 */ Temperature( -11.1, 0.3, -5.50662 ),
/* 27.01 */ Temperature( 0.2, 3.2, 1.95345 ),
/* 28.01 */ Temperature( 1.9, 5.2, 3.43633 ),
/* 29.01 */ Temperature( 4.4, 9.1, 6.24236 ),
/* 30.01 */ Temperature( 2.3, 11.5, 6.03114 ),
/* 31.01 */ Temperature( 4.6, 10.2, 6.04192 ),
/* 01.02 */ Temperature( 4.8, 13.8, 7.87674 ),
/* 02.02 */ Temperature( 5.7, 10, 7.28646 ),
/* 03.02 */ Temperature( 2.9, 8.2, 5.71771 ),
/* 04.02 */ Temperature( -1.5, 7.2, 4.71319 ),
/* 05.02 */ Temperature( -2.6, 4.4, 1.23542 ),
/* 06.02 */ Temperature( 0.3, 9.2, 2.59965 ),
/* 07.02 */ Temperature( -0.4, 2.4, 0.641667 ),
/* 08.02 */ Temperature( -1.7, 3.8, 0.811458 ),
/* 09.02 */ Temperature( 0.7, 7, 3.58328 ),
/* 10.02 */ Temperature( 1, 6, 3.51181 ),
/* 11.02 */ Temperature( 4.7, 9.6, 6.14913 ),
/* 12.02 */ Temperature( 5.3, 8.7, 6.80552 ),
/* 13.02 */ Temperature( 4.4, 10.3, 6.84552 ),
/* 14.02 */ Temperature( 2.6, 6.5, 4.58681 ),
/* 15.02 */ Temperature( -0.8, 13.4, 6.38542 ),
/* 16.02 */ Temperature( -3, 14.4, 4.11336 ),
/* 17.02 */ Temperature( 0.5, 13, 5.87457 ),
/* 18.02 */ Temperature( -2.2, 14.1, 4.36528 ),
/* 19.02 */ Temperature( 3.9, 5.6, 4.63737 ),
/* 20.02 */ Temperature( -0.4, 9.2, 4.37014 ),
/* 21.02 */ Temperature( -1.9, 5.5, 1.85675 ),
/* 22.02 */ Temperature( 1, 13.1, 5.41176 ),
/* 23.02 */ Temperature( 1.9, 13.9, 7.74251 ),
/* 24.02 */ Temperature( 3.8, 9.6, 7.19306 ),
/* 25.02 */ Temperature( 5.8, 10.8, 7.80312 ),
/* 26.02 */ Temperature( 5.2, 10.4, 6.79481 ),
/* 27.02 */ Temperature( 3.2, 7.4, 5.22986 ),
/* 28.02 */ Temperature( 6.4, 13.4, 9.13356 ),
/* 01.03 */ Temperature( 4.6, 11.4, 7.70554 ),
/* 02.03 */ Temperature( 3.4, 10.9, 5.98408 ),
/* 03.03 */ Temperature( 2.9, 10.5, 5.45675 ),
/* 04.03 */ Temperature( -0.7, 16.8, 7.29585 ),
/* 05.03 */ Temperature( 4.2, 13.4, 8.35862 ),
/* 06.03 */ Temperature( 3, 13, 7.76644 ),
/* 07.03 */ Temperature( 2, 13.3, 8.24618 ),
/* 08.03 */ Temperature( -0.8, 15, 6.11765 ),
/* 09.03 */ Temperature( -0.7, 11, 5.7568 ),
/* 10.03 */ Temperature( 1.2, 14.4, 6.61389 ),
/* 11.03 */ Temperature( -1.7, 18, 6.66146 ),
/* 12.03 */ Temperature( -0.6, 21.9, 8.9816 ),
/* 13.03 */ Temperature( -0.9, 19.6, 9.08299 ),
/* 14.03 */ Temperature( 5.3, 18.9, 10.5562 ),
/* 15.03 */ Temperature( 2, 20.5, 9.65156 ),
/* 16.03 */ Temperature( 0.2, 16.7, 7.8699 ),
/* 17.03 */ Temperature( 4.5, 10.6, 7.87535 ),
/* 18.03 */ Temperature( 2.7, 9.7, 6.71806 ),
/* 19.03 */ Temperature( 0.4, 10.9, 3.92404 ),
/* 20.03 */ Temperature( -2, 12.7, 4.01359 ),
/* 21.03 */ Temperature( 0.3, 6.8, 3.00382 ),
/* 22.03 */ Temperature( 0.9, 4.2, 2.2816 ),
/* 23.03 */ Temperature( 2, 5.7, 3.39233 ),
/* 24.03 */ Temperature( 3.9, 9.3, 6.41076 ),
/* 25.03 */ Temperature( 4.2, 19.1, 9.92182 ),
/* 26.03 */ Temperature( 2.3, 22, 12.5716 ),
/* 27.03 */ Temperature( 4.9, 20.6, 13.4568 ),
/* 28.03 */ Temperature( 0.3, 22.8, 10.755 ),
/* 29.03 */ Temperature( 1.8, 17.2, 9.43924 ),
/* 30.03 */ Temperature( 1.9, 19.8, 10.25 ),
/* 31.03 */ Temperature( 6.7, 17, 11.1324 ),
/* 01.04 */ Temperature( 5.7, 22, 12.8457 ),
/* 02.04 */ Temperature( 6.4, 22.1, 13.3847 ),
/* 03.04 */ Temperature( 5.8, 17.5, 10.5614 ),
/* 04.04 */ Temperature( 2.8, 16.2, 8.06574 ),
/* 05.04 */ Temperature( -0.6, 20.8, 9.18062 ),
/* 06.04 */ Temperature( 2.1, 24, 13.0069 ),
/* 07.04 */ Temperature( 5.3, 16.2, 10.2771 ),
/* 08.04 */ Temperature( 0.1, 20.7, 9.79861 ),
/* 09.04 */ Temperature( 0.3, 18.9, 10.0087 ),
/* 10.04 */ Temperature( 4, 16.4, 11.4208 ),
/* 11.04 */ Temperature( 2.3, 23.4, 13.083 ),
/* 12.04 */ Temperature( 7, 29.4, 16.5826 ),
/* 13.04 */ Temperature( 10.6, 31.5, 19.2249 ),
/* 14.04 */ Temperature( 11.8, 34, 21.441 ),
/* 15.04 */ Temperature( 11.6, 33.8, 21.0201 ),
/* 16.04 */ Temperature( 8.7, 31.1, 18.7885 ),
/* 17.04 */ Temperature( 5.5, 27.2, 16.1432 ),
/* 18.04 */ Temperature( 6.1, 17.2, 10.6688 ),
/* 19.04 */ Temperature( -0.6, 21.3, 10.4806 ),
/* 20.04 */ Temperature( 5.9, 21.6, 12.6257 ),
/* 21.04 */ Temperature( 2.1, 21.6, 11.0858 ),
/* 22.04 */ Temperature( 3.9, 25.9, 14.2108 ),
/* 23.04 */ Temperature( 3.1, 27.8, 15.7111 ),
/* 24.04 */ Temperature( 13.7, 29, 19.6397 ),
/* 25.04 */ Temperature( 9.8, 31.6, 19.601 ),
/* 26.04 */ Temperature( 8.2, 32.4, 20.0389 ),
/* 27.04 */ Temperature( 11.8, 32.1, 21.0726 ),
/* 28.04 */ Temperature( 12.6, 33.3, 21.6993 ),
/* 29.04 */ Temperature( 10.5, 27.4, 19.1206 ),
/* 30.04 */ Temperature( 5.3, 26.4, 15.0972 ),
/* 01.05 */ Temperature( 6.9, 25.3, 15.2802 ),
/* 02.05 */ Temperature( 4.3, 26.2, 14.8401 ),
/* 03.05 */ Temperature( 7.1, 28.5, 17.2145 ),
/* 04.05 */ Temperature( 11, 28.5, 18.537 ),
/* 05.05 */ Temperature( 12, 28, 18.1672 ),
/* 06.05 */ Temperature( 10.4, 29, 18.3844 ),
/* 07.05 */ Temperature( 13, 18.1, 15.0028 ),
/* 08.05 */ Temperature( 10.7, 18.3, 13.2014 ),
/* 09.05 */ Temperature( 10.8, 14.4, 12.5208 ),
/* 10.05 */ Temperature( 11.9, 23.5, 16.9632 ),
/* 11.05 */ Temperature( 9.8, 16.9, 15.0795 ),
/* 12.05 */ Temperature( 9.2, 19.6, 13.8521 ),
/* 13.05 */ Temperature( 8.9, 26.3, 16.2028 ),
/* 14.05 */ Temperature( 11.1, 17.5, 13.2934 ),
/* 15.05 */ Temperature( 6.5, 17, 11.7743 ),
/* 16.05 */ Temperature( 4.9, 13.6, 9.75625 ),
/* 17.05 */ Temperature( 6.8, 16.6, 9.96701 ),
/* 18.05 */ Temperature( 2.4, 21.2, 11.4311 ),
/* 19.05 */ Temperature( 8.2, 24.4, 15.4188 ),
/* 20.05 */ Temperature( 14.1, 31.7, 21.3303 ),
/* 21.05 */ Temperature( 11, 30.9, 21.5359 ),
/* 22.05 */ Temperature( 13.8, 31, 21.5177 ),
/* 23.05 */ Temperature( 16, 27.8, 21.0271 ),
/* 24.05 */ Temperature( 15, 34, 23.4142 ),
/* 25.05 */ Temperature( 14.3, 31.8, 22.8903 ),
/* 26.05 */ Temperature( 13.6, 33.1, 22.6156 ),
/* 27.05 */ Temperature( 11.2, 23.4, 16.6192 ),
/* 28.05 */ Temperature( 9.6, 13.1, 11.3222 ),
/* 29.05 */ Temperature( 8.3, 11.2, 10.3529 ),
/* 30.05 */ Temperature( 4.2, 20.8, 12.6218 ),
/* 31.05 */ Temperature( 9.2, 23.6, 15.1073 ),
/* 01.06 */ Temperature( 10.8, 24.4, 16.3205 ),
/* 02.06 */ Temperature( 13, 26.5, 18.9649 ),
/* 03.06 */ Temperature( 14, 25.1, 18.5398 ),
/* 04.06 */ Temperature( 13, 28, 20.2139 ),
/* 05.06 */ Temperature( 14, 28.8, 20.438 ),
/* 06.06 */ Temperature( 14, 30.4, 21.7821 ),
/* 07.06 */ Temperature( 17, 34.8, 25.3087 ),
/* 08.06 */ Temperature( 17.9, 35.7, 25.7872 ),
/* 09.06 */ Temperature( 17.8, 31.6, 22.0788 ),
/* 10.06 */ Temperature( 15.5, 33.4, 22.4458 ),
/* 11.06 */ Temperature( 16.6, 28.3, 19.8797 ),
/* 12.06 */ Temperature( 14, 27.3, 20.2566 ),
/* 13.06 */ Temperature( 13.2, 28.2, 19.4233 ),
/* 14.06 */ Temperature( 12.7, 30, 20.1427 ),
/* 15.06 */ Temperature( 15.2, 22.6, 18.5917 ),
/* 16.06 */ Temperature( 13.2, 24, 17.7014 ),
/* 17.06 */ Temperature( 11.7, 27.9, 19.8229 ),
/* 18.06 */ Temperature( 15.9, 27.2, 20.3358 ),
/* 19.06 */ Temperature( 12.6, 33.7, 22.2427 ),
/* 20.06 */ Temperature( 15.7, 30.8, 23.7507 ),
/* 21.06 */ Temperature( 14.8, 22.6, 18.2538 ),
/* 22.06 */ Temperature( 12.4, 21.3, 15.9969 ),
/* 23.06 */ Temperature( 12.6, 21.6, 15.8149 ),
/* 24.06 */ Temperature( 13, 26, 18.4176 ),
/* 25.06 */ Temperature( 12.9, 24.4, 17.1299 ),
/* 26.06 */ Temperature( 10.8, 18.8, 13.2913 ),
/* 27.06 */ Temperature( 9.9, 18.8, 13.5465 ),
/* 28.06 */ Temperature( 12, 19.8, 14.8434 ),
/* 29.06 */ Temperature( 12, 19, 15.155 ),
/* 30.06 */ Temperature( 12.4, 22.4, 17.1354 ),
/* 01.07 */ Temperature( 12.1, 24.9, 19.1639 ),
/* 02.07 */ Temperature( 15.7, 24.3, 18.4554 ),
/* 03.07 */ Temperature( 12.7, 17.2, 14.6564 ),
/* 04.07 */ Temperature( 11.2, 19, 13.9529 ),
/* 05.07 */ Temperature( 11.5, 19, 14.6422 ),
/* 06.07 */ Temperature( 12.4, 22, 16.6146 ),
/* 07.07 */ Temperature( 11.6, 24, 17.666 ),
/* 08.07 */ Temperature( 9, 28, 19.1351 ),
/* 09.07 */ Temperature( 11.3, 21.5, 16.5271 ),
/* 10.07 */ Temperature( 11.3, 20.2, 14.2326 ),
/* 11.07 */ Temperature( 10.2, 19.2, 14.0649 ),
/* 12.07 */ Temperature( 13.2, 23.1, 16.6346 ),
/* 13.07 */ Temperature( 15, 27, 19.6844 ),
/* 14.07 */ Temperature( 13.4, 32.4, 23.845 ),
/* 15.07 */ Temperature( 15, 38.2, 26.8559 ),
/* 16.07 */ Temperature( 16.1, 36.5, 26.4483 ),
/* 17.07 */ Temperature( 19.7, 30.5, 24.189 ),
/* 18.07 */ Temperature( 14.2, 29.3, 22.1363 ),
/* 19.07 */ Temperature( 16.4, 25.9, 19.0819 ),
/* 20.07 */ Temperature( 16.2, 30.8, 22.151 ),
/* 21.07 */ Temperature( 14, 24.3, 18.6573 ),
/* 22.07 */ Temperature( 13.2, 24.5, 18.3301 ),
/* 23.07 */ Temperature( 10.6, 23.4, 16.6903 ),
/* 24.07 */ Temperature( 13.2, 20.8, 16.2743 ),
/* 25.07 */ Temperature( 12.2, 25.8, 18.8267 ),
/* 26.07 */ Temperature( 11.9, 28.9, 20.5522 ),
/* 27.07 */ Temperature( 17.6, 25.8, 21.5691 ),
/* 28.07 */ Temperature( 16.6, 24.6, 19.2295 ),
/* 29.07 */ Temperature( 13, 19, 15.9021 ),
/* 30.07 */ Temperature( 9.6, 19.7, 13.875 ),
/* 31.07 */ Temperature( 8, 22, 14.5284 ),
/* 01.08 */ Temperature( 7.6, 27.5, 17.5684 ),
/* 02.08 */ Temperature( 9.2, 22.2, 16.1035 ),
/* 03.08 */ Temperature( 12.7, 25.3, 18.2958 ),
/* 04.08 */ Temperature( 8.6, 31.3, 19.7941 ),
/* 05.08 */ Temperature( 10.3, 32.7, 21.492 ),
/* 06.08 */ Temperature( 10, 33.4, 22.4431 ),
/* 07.08 */ Temperature( 16.8, 22.6, 19.5583 ),
/* 08.08 */ Temperature( 13.5, 16.7, 15.0264 ),
/* 09.08 */ Temperature( 13.2, 18.8, 15.6003 ),
/* 10.08 */ Temperature( 14.6, 27.9, 18.8292 ),
/* 11.08 */ Temperature( 16.3, 26.4, 20.3837 ),
/* 12.08 */ Temperature( 12.1, 28.7, 19.9892 ),
/* 13.08 */ Temperature( 15, 27.4, 19.7542 ),
/* 14.08 */ Temperature( 11.3, 28.3, 20.5656 ),
/* 15.08 */ Temperature( 18.6, 28.4, 23.1215 ),
/* 16.08 */ Temperature( 16, 23.6, 19.491 ),
/* 17.08 */ Temperature( 12.6, 22, 17.0437 ),
/* 18.08 */ Temperature( 8.5, 25.7, 16.5589 ),
/* 19.08 */ Temperature( 13.4, 25.8, 18.0543 ),
/* 20.08 */ Temperature( 10.9, 21.5, 16.1306 ),
/* 21.08 */ Temperature( 10.6, 19.2, 14.6177 ),
/* 22.08 */ Temperature( 14, 24.6, 17.3841 ),
/* 23.08 */ Temperature( 13.8, 30.4, 20.6125 ),
/* 24.08 */ Temperature( 12.3, 30.3, 20.7622 ),
/* 25.08 */ Temperature( 12.8, 30.2, 21.6736 ),
/* 26.08 */ Temperature( 15, 29.3, 21.266 ),
/* 27.08 */ Temperature( 12.9, 25.9, 18.791 ),
/* 28.08 */ Temperature( 9.3, 24.6, 16.2833 ),
/* 29.08 */ Temperature( 10.8, 25, 16.8459 ),
/* 30.08 */ Temperature( 8.2, 24.4, 15.9267 ),
/* 31.08 */ Temperature( 14.1, 20.5, 16.6128 ),
/* 01.09 */ Temperature( 13.4, 21.9, 16.2205 ),
/* 02.09 */ Temperature( 12, 20.7, 16.0882 ),
/* 03.09 */ Temperature( 10.8, 21.3, 14.7913 ),
/* 04.09 */ Temperature( 7.8, 18.2, 12.2747 ),
/* 05.09 */ Temperature( 8.1, 22.2, 12.9406 ),
/* 06.09 */ Temperature( 10, 23.8, 13.8785 ),
/* 07.09 */ Temperature( 10.7, 21.2, 15.4823 ),
/* 08.09 */ Temperature( 12.4, 21, 15.8194 ),
/* 09.09 */ Temperature( 12.7, 16.9, 14.7212 ),
/* 10.09 */ Temperature( 10.3, 17.7, 12.9271 ),
/* 11.09 */ Temperature( 10.6, 20.8, 14.4788 ),
/* 12.09 */ Temperature( 10.8, 21.9, 15.0184 ),
/* 13.09 */ Temperature( 6.9, 24.6, 14.5222 ),
/* 14.09 */ Temperature( 8.1, 24, 15.6583 ),
/* 15.09 */ Temperature( 8.8, 22.8, 15.941 ),
/* 16.09 */ Temperature( 3.1, 24.5, 14.1486 ),
/* 17.09 */ Temperature( 12.4, 21.2, 16.0497 ),
/* 18.09 */ Temperature( 7.8, 16.1, 12.024 ),
/* 19.09 */ Temperature( 5.3, 18.1, 10.3003 ),
/* 20.09 */ Temperature( 6.4, 20.3, 12.3177 ),
/* 21.09 */ Temperature( 6, 23.8, 13.6247 ),
/* 22.09 */ Temperature( 5.7, 27, 14.6847 ),
/* 23.09 */ Temperature( 7.8, 28, 16.6238 ),
/* 24.09 */ Temperature( 9.6, 24.9, 16.7191 ),
/* 25.09 */ Temperature( 8.4, 17.6, 12.636 ),
/* 26.09 */ Temperature( 4.3, 18.9, 10.0809 ),
/* 27.09 */ Temperature( 9.4, 11.2, 10.3344 ),
/* 28.09 */ Temperature( 7.7, 12.6, 10.5337 ),
/* 29.09 */ Temperature( 9.8, 15.3, 11.9306 ),
/* 30.09 */ Temperature( 9.6, 21.1, 13.6635 ),
/* 01.10 */ Temperature( 8.9, 24.5, 14.8163 ),
/* 02.10 */ Temperature( 13.5, 20.2, 16.1628 ),
/* 03.10 */ Temperature( 12.5, 18, 15.4691 ),
/* 04.10 */ Temperature( 13.8, 25, 17.2073 ),
/* 05.10 */ Temperature( 9.1, 23.2, 14.6181 ),
/* 06.10 */ Temperature( 6.4, 23.4, 12.8625 ),
/* 07.10 */ Temperature( 4.6, 22.1, 11.0052 ),
/* 08.10 */ Temperature( 2, 22.2, 10.1677 ),
/* 09.10 */ Temperature( 7.8, 21.6, 12.2139 ),
/* 10.10 */ Temperature( 7.1, 22.7, 13.0115 ),
/* 11.10 */ Temperature( 6.1, 21.2, 11.4333 ),
/* 12.10 */ Temperature( 4.3, 15.2, 10.6104 ),
/* 13.10 */ Temperature( 5.8, 23, 12.8875 ),
/* 14.10 */ Temperature( 1, 23, 9.72986 ),
/* 15.10 */ Temperature( 1, 19.3, 9.33021 ),
/* 16.10 */ Temperature( 8.5, 20.4, 13.2639 ),
/* 17.10 */ Temperature( 6.8, 17.3, 11.8174 ),
/* 18.10 */ Temperature( 5.2, 15.6, 9.06076 ),
/* 19.10 */ Temperature( 2.7, 13.5, 7.1309 ),
/* 20.10 */ Temperature( -0.2, 15.8, 6.01667 ),
/* 21.10 */ Temperature( 2.6, 6.1, 4.9441 ),
/* 22.10 */ Temperature( -0.8, 13.2, 4.50694 ),
/* 23.10 */ Temperature( -0.4, 13.3, 4.71007 ),
/* 24.10 */ Temperature( 2.9, 8.1, 5.96979 ),
/* 25.10 */ Temperature( 6.3, 10.5, 8.01206 ),
/* 26.10 */ Temperature( 7, 10.8, 8.14965 ),
/* 27.10 */ Temperature( 6.6, 9.7, 7.7809 ),
/* 28.10 */ Temperature( 1.7, 10.8, 6.95728 ),
/* 29.10 */ Temperature( 2.2, 9.9, 6.62917 ),
/* 30.10 */ Temperature( 5.8, 15, 8.76181 ),
/* 31.10 */ Temperature( 0.7, 15, 6.01528 ),
/* 01.11 */ Temperature( -0.2, 9.7, 3.75842 ),
/* 02.11 */ Temperature( 6.4, 9.6, 8.00138 ),
/* 03.11 */ Temperature( 8.7, 13.1, 10.5676 ),
/* 04.11 */ Temperature( 8, 11.8, 9.54306 ),
/* 05.11 */ Temperature( 5.8, 15.9, 8.52345 ),
/* 06.11 */ Temperature( 5.5, 10.8, 7.16493 ),
/* 07.11 */ Temperature( 5.5, 8.9, 7.30172 ),
/* 08.11 */ Temperature( 7, 11.7, 8.96701 ),
/* 09.11 */ Temperature( 2.5, 8.4, 4.86528 ),
/* 10.11 */ Temperature( 3.7, 9, 5.20828 ),
/* 11.11 */ Temperature( 2.8, 10.6, 6.80756 ),
/* 12.11 */ Temperature( 2.7, 9.5, 5.07647 ),
/* 13.11 */ Temperature( 0.1, 5.4, 3.3945 ),
/* 14.11 */ Temperature( -0.7, 7.9, 2.02234 ),
/* 15.11 */ Temperature( -1.8, 6.5, 1.07778 ),
/* 16.11 */ Temperature( -4.4, 5.1, -0.693772 ),
/* 17.11 */ Temperature( -0.3, 3.4, 1.33229 ),
/* 18.11 */ Temperature( -0.4, 4.3, 2.4622 ),
/* 19.11 */ Temperature( 1.8, 3.6, 2.78282 ),
/* 20.11 */ Temperature( 1.3, 5.6, 2.95979 ),
/* 21.11 */ Temperature( 1.6, 5.7, 3.62284 ),
/* 22.11 */ Temperature( 3.1, 7.3, 5.60277 ),
/* 23.11 */ Temperature( 4.2, 7.7, 6.28166 ),
/* 24.11 */ Temperature( -0.5, 11.5, 3.25931 ),
/* 25.11 */ Temperature( -1, 8.8, 2.86505 ),
/* 26.11 */ Temperature( 1.2, 6.8, 3.09414 ),
/* 27.11 */ Temperature( -0.8, 7.5, 3.17805 ),
/* 28.11 */ Temperature( -2.8, 3.1, -0.920139 ),
/* 29.11 */ Temperature( -2.6, 1.7, -0.491696 ),
/* 30.11 */ Temperature( 1.3, 6.5, 3.85 ),
/* 01.12 */ Temperature( 4.1, 8.7, 5.88924 ),
/* 02.12 */ Temperature( 4.8, 9, 6.81667 ),
/* 03.12 */ Temperature( 3.5, 8.5, 6.23633 ),
/* 04.12 */ Temperature( 2.7, 6.6, 4.63045 ),
/* 05.12 */ Temperature( 4.3, 8.6, 6.85993 ),
/* 06.12 */ Temperature( 5.5, 9.3, 7.79201 ),
/* 07.12 */ Temperature( 3.1, 13.4, 8.79444 ),
/* 08.12 */ Temperature( 2.6, 6.3, 4.67093 ),
/* 09.12 */ Temperature( 3, 10.4, 5.75724 ),
/* 10.12 */ Temperature( 4.1, 6.8, 5.31834 ),
/* 11.12 */ Temperature( 4.1, 7.4, 5.28993 ),
/* 12.12 */ Temperature( 3.9, 6.4, 4.64479 ),
/* 13.12 */ Temperature( 1.7, 9.1, 4.15363 ),
/* 14.12 */ Temperature( 0.4, 1.8, 0.934602 ),
/* 15.12 */ Temperature( -4.5, 2.1, -1.17292 ),
/* 16.12 */ Temperature( -5, 4.8, -2.17431 ),
/* 17.12 */ Temperature( -5.6, 6.1, -1.35448 ),
/* 18.12 */ Temperature( -4.9, 6.4, -1.25502 ),
/* 19.12 */ Temperature( -4.4, 6.6, -1.02396 ),
/* 20.12 */ Temperature( -7.3, 5.2, -2.63854 ),
/* 21.12 */ Temperature( -8.5, 5.7, -3.58333 ),
/* 22.12 */ Temperature( -7.9, -5.3, -6.13438 ),
/* 23.12 */ Temperature( -6.1, -4.4, -5.23472 ),
/* 24.12 */ Temperature( -4.6, -3.3, -3.84291 ),
/* 25.12 */ Temperature( -4.9, -2.8, -3.9066 ),
/* 26.12 */ Temperature( -4.7, -1.9, -3.10379 ),
/* 27.12 */ Temperature( -1.9, -0.2, -0.679791 ),
/* 28.12 */ Temperature( -1.8, 0.5, -0.521875 ),
/* 29.12 */ Temperature( -2.2, 2.3, -0.430796 ),
/* 30.12 */ Temperature( 0.9, 5.2, 2.83437 ),
/* 31.12 */ Temperature( -1, 8.3, 2.27093 )
};

View File

@ -0,0 +1,28 @@
#ifndef _FRIEDBERG_2007_H_
#define _FRIEDBERG_2007_H_
class Temperature
{
public:
Temperature():
minValue( 0.0 ),
maxValue( 0.0 ),
averageValue( 0.0 )
{
}
Temperature( double min, double max, double average ):
minValue( min ),
maxValue( max ),
averageValue( average )
{
}
double minValue;
double maxValue;
double averageValue;
};
extern Temperature friedberg2007[];
#endif

View File

@ -0,0 +1,55 @@
#include <qapplication.h>
#include <qmainwindow.h>
#include <qcombobox.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include "plot.h"
class MainWindow: public QMainWindow
{
public:
MainWindow( QWidget * = NULL );
private:
Plot *d_plot;
};
MainWindow::MainWindow( QWidget *parent ):
QMainWindow( parent )
{
d_plot = new Plot( this );
setCentralWidget( d_plot );
QToolBar *toolBar = new QToolBar( this );
QComboBox *typeBox = new QComboBox( toolBar );
typeBox->addItem( "Bars" );
typeBox->addItem( "Tube" );
typeBox->setCurrentIndex( 1 );
typeBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
QToolButton *btnExport = new QToolButton( toolBar );
btnExport->setText( "Export" );
btnExport->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
connect( btnExport, SIGNAL( clicked() ), d_plot, SLOT( exportPlot() ) );
toolBar->addWidget( typeBox );
toolBar->addWidget( btnExport );
addToolBar( toolBar );
d_plot->setMode( typeBox->currentIndex() );
connect( typeBox, SIGNAL( currentIndexChanged( int ) ),
d_plot, SLOT( setMode( int ) ) );
}
int main( int argc, char **argv )
{
QApplication a( argc, argv );
MainWindow w;
w.setObjectName( "MainWindow" );
w.resize( 600, 400 );
w.show();
return a.exec();
}

View File

@ -0,0 +1,209 @@
#include "plot.h"
#include "friedberg2007.h"
#include <qwt_plot_zoomer.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_intervalcurve.h>
#include <qwt_legend.h>
#include <qwt_interval_symbol.h>
#include <qwt_symbol.h>
#include <qwt_series_data.h>
#include <qwt_text.h>
#include <qwt_scale_draw.h>
#include <qwt_plot_renderer.h>
#include <qdatetime.h>
class Grid: public QwtPlotGrid
{
public:
Grid()
{
enableXMin( true );
setMajorPen( Qt::white, 0, Qt::DotLine );
setMinorPen( Qt::gray, 0, Qt::DotLine );
}
virtual void updateScaleDiv( const QwtScaleDiv &xScaleDiv,
const QwtScaleDiv &yScaleDiv )
{
QwtScaleDiv scaleDiv( xScaleDiv.lowerBound(),
xScaleDiv.upperBound() );
scaleDiv.setTicks( QwtScaleDiv::MinorTick,
xScaleDiv.ticks( QwtScaleDiv::MinorTick ) );
scaleDiv.setTicks( QwtScaleDiv::MajorTick,
xScaleDiv.ticks( QwtScaleDiv::MediumTick ) );
QwtPlotGrid::updateScaleDiv( scaleDiv, yScaleDiv );
}
};
class YearScaleDraw: public QwtScaleDraw
{
public:
YearScaleDraw()
{
setTickLength( QwtScaleDiv::MajorTick, 0 );
setTickLength( QwtScaleDiv::MinorTick, 0 );
setTickLength( QwtScaleDiv::MediumTick, 6 );
setLabelRotation( -60.0 );
setLabelAlignment( Qt::AlignLeft | Qt::AlignVCenter );
setSpacing( 15 );
}
virtual QwtText label( double value ) const
{
return QDate::longMonthName( int( value / 30 ) + 1 );
}
};
Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
setObjectName( "FriedbergPlot" );
setTitle( "Temperature of Friedberg/Germany" );
setAxisTitle( QwtPlot::xBottom, "2007" );
setAxisScaleDiv( QwtPlot::xBottom, yearScaleDiv() );
setAxisScaleDraw( QwtPlot::xBottom, new YearScaleDraw() );
setAxisTitle( QwtPlot::yLeft,
QString( "Temperature [%1C]" ).arg( QChar( 0x00B0 ) ) );
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setPalette( Qt::darkGray );
canvas->setBorderRadius( 10 );
setCanvas( canvas );
// grid
QwtPlotGrid *grid = new Grid;
grid->attach( this );
insertLegend( new QwtLegend(), QwtPlot::RightLegend );
const int numDays = 365;
QVector<QPointF> averageData( numDays );
QVector<QwtIntervalSample> rangeData( numDays );
for ( int i = 0; i < numDays; i++ )
{
const Temperature &t = friedberg2007[i];
averageData[i] = QPointF( double( i ), t.averageValue );
rangeData[i] = QwtIntervalSample( double( i ),
QwtInterval( t.minValue, t.maxValue ) );
}
insertCurve( "Average", averageData, Qt::black );
insertErrorBars( "Range", rangeData, Qt::blue );
// LeftButton for the zooming
// MidButton for the panning
// RightButton: zoom out by 1
// Ctrl+RighButton: zoom out to full size
QwtPlotZoomer* zoomer = new QwtPlotZoomer( canvas );
zoomer->setRubberBandPen( QColor( Qt::black ) );
zoomer->setTrackerPen( QColor( Qt::black ) );
zoomer->setMousePattern( QwtEventPattern::MouseSelect2,
Qt::RightButton, Qt::ControlModifier );
zoomer->setMousePattern( QwtEventPattern::MouseSelect3,
Qt::RightButton );
QwtPlotPanner *panner = new QwtPlotPanner( canvas );
panner->setMouseButton( Qt::MidButton );
}
QwtScaleDiv Plot::yearScaleDiv() const
{
const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
QList<double> mediumTicks;
mediumTicks += 0.0;
for ( uint i = 0; i < sizeof( days ) / sizeof( days[0] ); i++ )
mediumTicks += mediumTicks.last() + days[i];
QList<double> minorTicks;
for ( int i = 1; i <= 365; i += 7 )
minorTicks += i;
QList<double> majorTicks;
for ( int i = 0; i < 12; i++ )
majorTicks += i * 30 + 15;
QwtScaleDiv scaleDiv( mediumTicks.first(), mediumTicks.last() + 1,
minorTicks, mediumTicks, majorTicks );
return scaleDiv;
}
void Plot::insertCurve( const QString& title,
const QVector<QPointF>& samples, const QColor &color )
{
d_curve = new QwtPlotCurve( title );
d_curve->setRenderHint( QwtPlotItem::RenderAntialiased );
d_curve->setStyle( QwtPlotCurve::NoCurve );
d_curve->setLegendAttribute( QwtPlotCurve::LegendShowSymbol );
QwtSymbol *symbol = new QwtSymbol( QwtSymbol::XCross );
symbol->setSize( 4 );
symbol->setPen( color );
d_curve->setSymbol( symbol );
d_curve->setSamples( samples );
d_curve->attach( this );
}
void Plot::insertErrorBars(
const QString &title,
const QVector<QwtIntervalSample>& samples,
const QColor &color )
{
d_intervalCurve = new QwtPlotIntervalCurve( title );
d_intervalCurve->setRenderHint( QwtPlotItem::RenderAntialiased );
d_intervalCurve->setPen( Qt::white );
QColor bg( color );
bg.setAlpha( 150 );
d_intervalCurve->setBrush( QBrush( bg ) );
d_intervalCurve->setStyle( QwtPlotIntervalCurve::Tube );
d_intervalCurve->setSamples( samples );
d_intervalCurve->attach( this );
}
void Plot::setMode( int style )
{
if ( style == Tube )
{
d_intervalCurve->setStyle( QwtPlotIntervalCurve::Tube );
d_intervalCurve->setSymbol( NULL );
d_intervalCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
}
else
{
d_intervalCurve->setStyle( QwtPlotIntervalCurve::NoCurve );
QColor c( d_intervalCurve->brush().color().rgb() ); // skip alpha
QwtIntervalSymbol *errorBar =
new QwtIntervalSymbol( QwtIntervalSymbol::Bar );
errorBar->setWidth( 8 ); // should be something even
errorBar->setPen( c );
d_intervalCurve->setSymbol( errorBar );
d_intervalCurve->setRenderHint( QwtPlotItem::RenderAntialiased, false );
}
replot();
}
void Plot::exportPlot()
{
QwtPlotRenderer renderer;
renderer.exportTo( this, "friedberg.pdf" );
}

View File

@ -0,0 +1,43 @@
#ifndef _PLOT_H_
#define _PLOT_H_
#include <qwt_plot.h>
#include <qwt_scale_div.h>
#include <qwt_series_data.h>
class QwtPlotCurve;
class QwtPlotIntervalCurve;
class Plot: public QwtPlot
{
Q_OBJECT
public:
enum Mode
{
Bars,
Tube
};
Plot( QWidget * = NULL );
public Q_SLOTS:
void setMode( int );
void exportPlot();
private:
void insertCurve( const QString &title,
const QVector<QPointF> &, const QColor & );
void insertErrorBars( const QString &title,
const QVector<QwtIntervalSample> &,
const QColor &color );
QwtScaleDiv yearScaleDiv() const;
QwtPlotIntervalCurve *d_intervalCurve;
QwtPlotCurve *d_curve;
};
#endif

View File

@ -0,0 +1,374 @@
#include "editor.h"
#include <qwt_plot.h>
#include <qwt_plot_canvas.h>
#include <qwt_scale_map.h>
#include <qwt_plot_shapeitem.h>
#include <qevent.h>
class Overlay: public QwtWidgetOverlay
{
public:
Overlay( QWidget *parent, Editor *editor ):
QwtWidgetOverlay( parent ),
d_editor( editor )
{
switch( editor->mode() )
{
case Editor::NoMask:
{
setMaskMode( QwtWidgetOverlay::NoMask );
setRenderMode( QwtWidgetOverlay::AutoRenderMode );
break;
}
case Editor::Mask:
{
setMaskMode( QwtWidgetOverlay::MaskHint );
setRenderMode( QwtWidgetOverlay::AutoRenderMode );
break;
}
case Editor::AlphaMask:
{
setMaskMode( QwtWidgetOverlay::AlphaMask );
setRenderMode( QwtWidgetOverlay::AutoRenderMode );
break;
}
case Editor::AlphaMaskRedraw:
{
setMaskMode( QwtWidgetOverlay::AlphaMask );
setRenderMode( QwtWidgetOverlay::DrawOverlay );
break;
}
case Editor::AlphaMaskCopyMask:
{
setMaskMode( QwtWidgetOverlay::AlphaMask );
setRenderMode( QwtWidgetOverlay::CopyAlphaMask );
break;
}
}
}
protected:
virtual void drawOverlay( QPainter *painter ) const
{
d_editor->drawOverlay( painter );
}
virtual QRegion maskHint() const
{
return d_editor->maskHint();
}
private:
Editor *d_editor;
};
Editor::Editor( QwtPlot* plot ):
QObject( plot ),
d_isEnabled( false ),
d_overlay( NULL ),
d_mode( Mask )
{
setEnabled( true );
}
Editor::~Editor()
{
delete d_overlay;
}
QwtPlot *Editor::plot()
{
return qobject_cast<QwtPlot *>( parent() );
}
const QwtPlot *Editor::plot() const
{
return qobject_cast<const QwtPlot *>( parent() );
}
void Editor::setMode( Mode mode )
{
d_mode = mode;
}
Editor::Mode Editor::mode() const
{
return d_mode;
}
void Editor::setEnabled( bool on )
{
if ( on == d_isEnabled )
return;
QwtPlot *plot = qobject_cast<QwtPlot *>( parent() );
if ( plot )
{
d_isEnabled = on;
if ( on )
{
plot->canvas()->installEventFilter( this );
}
else
{
plot->canvas()->removeEventFilter( this );
delete d_overlay;
d_overlay = NULL;
}
}
}
bool Editor::isEnabled() const
{
return d_isEnabled;
}
bool Editor::eventFilter( QObject* object, QEvent* event )
{
QwtPlot *plot = qobject_cast<QwtPlot *>( parent() );
if ( plot && object == plot->canvas() )
{
switch( event->type() )
{
case QEvent::MouseButtonPress:
{
const QMouseEvent* mouseEvent =
dynamic_cast<QMouseEvent* >( event );
if ( d_overlay == NULL &&
mouseEvent->button() == Qt::LeftButton )
{
const bool accepted = pressed( mouseEvent->pos() );
if ( accepted )
{
d_overlay = new Overlay( plot->canvas(), this );
d_overlay->updateOverlay();
d_overlay->show();
}
}
break;
}
case QEvent::MouseMove:
{
if ( d_overlay )
{
const QMouseEvent* mouseEvent =
dynamic_cast< QMouseEvent* >( event );
const bool accepted = moved( mouseEvent->pos() );
if ( accepted )
d_overlay->updateOverlay();
}
break;
}
case QEvent::MouseButtonRelease:
{
const QMouseEvent* mouseEvent =
static_cast<QMouseEvent* >( event );
if ( d_overlay && mouseEvent->button() == Qt::LeftButton )
{
released( mouseEvent->pos() );
delete d_overlay;
d_overlay = NULL;
}
break;
}
default:
break;
}
return false;
}
return QObject::eventFilter( object, event );
}
bool Editor::pressed( const QPoint& pos )
{
d_editedItem = itemAt( pos );
if ( d_editedItem )
{
d_currentPos = pos;
setItemVisible( d_editedItem, false );
return true;
}
return false; // don't accept the position
}
bool Editor::moved( const QPoint& pos )
{
if ( plot() == NULL )
return false;
const QwtScaleMap xMap = plot()->canvasMap( d_editedItem->xAxis() );
const QwtScaleMap yMap = plot()->canvasMap( d_editedItem->yAxis() );
const QPointF p1 = QwtScaleMap::invTransform( xMap, yMap, d_currentPos );
const QPointF p2 = QwtScaleMap::invTransform( xMap, yMap, pos );
#if QT_VERSION >= 0x040600
const QPainterPath shape = d_editedItem->shape().translated( p2 - p1 );
#else
const double dx = p2.x() - p1.x();
const double dy = p2.y() - p1.y();
QPainterPath shape = d_editedItem->shape();
for ( int i = 0; i < shape.elementCount(); i++ )
{
const QPainterPath::Element &el = shape.elementAt( i );
shape.setElementPositionAt( i, el.x + dx, el.y + dy );
}
#endif
d_editedItem->setShape( shape );
d_currentPos = pos;
return true;
}
void Editor::released( const QPoint& pos )
{
Q_UNUSED( pos );
if ( d_editedItem )
{
raiseItem( d_editedItem );
setItemVisible( d_editedItem, true );
}
}
QwtPlotShapeItem* Editor::itemAt( const QPoint& pos ) const
{
const QwtPlot *plot = this->plot();
if ( plot == NULL )
return NULL;
// translate pos into the plot coordinates
double coords[ QwtPlot::axisCnt ];
coords[ QwtPlot::xBottom ] =
plot->canvasMap( QwtPlot::xBottom ).invTransform( pos.x() );
coords[ QwtPlot::xTop ] =
plot->canvasMap( QwtPlot::xTop ).invTransform( pos.x() );
coords[ QwtPlot::yLeft ] =
plot->canvasMap( QwtPlot::yLeft ).invTransform( pos.y() );
coords[ QwtPlot::yRight ] =
plot->canvasMap( QwtPlot::yRight ).invTransform( pos.y() );
QwtPlotItemList items = plot->itemList();
for ( int i = items.size() - 1; i >= 0; i-- )
{
QwtPlotItem *item = items[ i ];
if ( item->isVisible() &&
item->rtti() == QwtPlotItem::Rtti_PlotShape )
{
QwtPlotShapeItem *shapeItem = static_cast<QwtPlotShapeItem *>( item );
const QPointF p( coords[ item->xAxis() ], coords[ item->yAxis() ] );
if ( shapeItem->boundingRect().contains( p )
&& shapeItem->shape().contains( p ) )
{
return shapeItem;
}
}
}
return NULL;
}
QRegion Editor::maskHint() const
{
return maskHint( d_editedItem );
}
QRegion Editor::maskHint( QwtPlotShapeItem *shapeItem ) const
{
const QwtPlot *plot = this->plot();
if ( plot == NULL || shapeItem == NULL )
return QRegion();
const QwtScaleMap xMap = plot->canvasMap( shapeItem->xAxis() );
const QwtScaleMap yMap = plot->canvasMap( shapeItem->yAxis() );
QRect rect = QwtScaleMap::transform( xMap, yMap,
shapeItem->shape().boundingRect() ).toRect();
const int m = 5; // some margin for the pen
return rect.adjusted( -m, -m, m, m );
}
void Editor::drawOverlay( QPainter* painter ) const
{
const QwtPlot *plot = this->plot();
if ( plot == NULL || d_editedItem == NULL )
return;
const QwtScaleMap xMap = plot->canvasMap( d_editedItem->xAxis() );
const QwtScaleMap yMap = plot->canvasMap( d_editedItem->yAxis() );
painter->setRenderHint( QPainter::Antialiasing,
d_editedItem->testRenderHint( QwtPlotItem::RenderAntialiased ) );
d_editedItem->draw( painter, xMap, yMap,
plot->canvas()->contentsRect() );
}
void Editor::raiseItem( QwtPlotShapeItem *shapeItem )
{
const QwtPlot *plot = this->plot();
if ( plot == NULL || shapeItem == NULL )
return;
const QwtPlotItemList items = plot->itemList();
for ( int i = items.size() - 1; i >= 0; i-- )
{
QwtPlotItem *item = items[ i ];
if ( shapeItem == item )
return;
if ( item->isVisible() &&
item->rtti() == QwtPlotItem::Rtti_PlotShape )
{
shapeItem->setZ( item->z() + 1 );
return;
}
}
}
void Editor::setItemVisible( QwtPlotShapeItem *item, bool on )
{
if ( plot() == NULL || item == NULL || item->isVisible() == on )
return;
const bool doAutoReplot = plot()->autoReplot();
plot()->setAutoReplot( false );
item->setVisible( on );
plot()->setAutoReplot( doAutoReplot );
/*
Avoid replot with a full repaint of the canvas.
For special combinations - f.e. using the
raster paint engine on a remote display -
this makes a difference.
*/
QwtPlotCanvas *canvas =
qobject_cast<QwtPlotCanvas *>( plot()->canvas() );
if ( canvas )
canvas->invalidateBackingStore();
plot()->canvas()->update( maskHint( item ) );
}

View File

@ -0,0 +1,66 @@
#ifndef _EDITOR_H_
#define _EDITOR_H_
#include <qobject.h>
#include <qregion.h>
#include <qpointer.h>
#include <qwt_widget_overlay.h>
class QwtPlot;
class QwtPlotShapeItem;
class QPainter;
class QPoint;
class Editor: public QObject
{
Q_OBJECT
public:
enum Mode
{
NoMask,
Mask,
AlphaMask,
AlphaMaskRedraw,
AlphaMaskCopyMask
};
Editor( QwtPlot * );
virtual ~Editor();
const QwtPlot *plot() const;
QwtPlot *plot();
virtual void setEnabled( bool on );
bool isEnabled() const;
void drawOverlay( QPainter * ) const;
QRegion maskHint() const;
virtual bool eventFilter( QObject *, QEvent *);
void setMode( Mode mode );
Mode mode() const;
private:
bool pressed( const QPoint & );
bool moved( const QPoint & );
void released( const QPoint & );
QwtPlotShapeItem* itemAt( const QPoint& ) const;
void raiseItem( QwtPlotShapeItem * );
QRegion maskHint( QwtPlotShapeItem * ) const;
void setItemVisible( QwtPlotShapeItem *item, bool on );
bool d_isEnabled;
QPointer<QwtWidgetOverlay> d_overlay;
// Mouse positions
QPointF d_currentPos;
QwtPlotShapeItem* d_editedItem;
Mode d_mode;
};
#endif

View File

@ -0,0 +1,22 @@
TARGET = itemeditor
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
editor.h \
shapefactory.h \
plot.h
SOURCES = \
editor.cpp \
shapefactory.cpp \
plot.cpp \
main.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,54 @@
#include "plot.h"
#include <qapplication.h>
#include <qmainwindow.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qcombobox.h>
class MainWindow: public QMainWindow
{
public:
MainWindow( QWidget * = NULL );
};
MainWindow::MainWindow( QWidget *parent ):
QMainWindow( parent )
{
Plot *plot = new Plot( this );
setCentralWidget( plot );
QToolBar *toolBar = new QToolBar( this );
QComboBox *modeBox = new QComboBox( toolBar );
modeBox->addItem( "No Mask" );
modeBox->addItem( "Mask" );
modeBox->addItem( "Alpha Mask" );
modeBox->addItem( "Alpha Mask/Redraw" );
modeBox->addItem( "Alpha Mask/Copy Mask" );
modeBox->setCurrentIndex( 1 );
modeBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
connect( modeBox, SIGNAL( currentIndexChanged( int ) ),
plot, SLOT( setMode( int ) ) );
QToolButton *btnExport = new QToolButton( toolBar );
btnExport->setText( "Export" );
btnExport->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
connect( btnExport, SIGNAL( clicked() ), plot, SLOT( exportPlot() ) );
toolBar->addWidget( modeBox );
toolBar->addWidget( btnExport );
addToolBar( toolBar );
}
int main( int argc, char **argv )
{
QApplication app( argc, argv );
MainWindow window;
window.resize( 600, 400 );
window.show();
return app.exec();
}

View File

@ -0,0 +1,120 @@
#include "plot.h"
#include "editor.h"
#include <qwt_plot_shapeitem.h>
#include <qwt_plot_magnifier.h>
#include <qwt_plot_canvas.h>
#include <qwt_legend.h>
#include <qwt_plot_renderer.h>
class Legend: public QwtLegend
{
protected:
virtual QWidget *createWidget( const QwtLegendData &data ) const
{
QWidget *w = QwtLegend::createWidget( data );
if ( w )
{
w->setStyleSheet(
"border-radius: 5px;"
"padding: 2px;"
"background: LemonChiffon;"
);
}
return w;
}
};
Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
setAutoReplot( false );
setTitle( "Movable Items" );
const int margin = 5;
setContentsMargins( margin, margin, margin, margin );
setAutoFillBackground( true );
setPalette( QColor( "DimGray" ).lighter( 110 ) );
QwtPlotCanvas *canvas = new QwtPlotCanvas();
#if 0
// a gradient making a replot slow on X11
canvas->setStyleSheet(
"border: 2px solid Black;"
"border-radius: 15px;"
"background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1,"
"stop: 0 LemonChiffon, stop: 0.5 PaleGoldenrod, stop: 1 LemonChiffon );"
);
#else
canvas->setStyleSheet(
"border: 2px inset DimGray;"
"border-radius: 15px;"
"background: LemonChiffon;"
);
#endif
setCanvas( canvas );
insertLegend( new Legend(), QwtPlot::RightLegend );
populate();
updateAxes();
for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
setAxisAutoScale( axis, false );
d_editor = new Editor( this );
( void ) new QwtPlotMagnifier( canvas );
}
void Plot::populate()
{
addShape( "Rectangle", ShapeFactory::Rect, "RoyalBlue",
QPointF( 30.0, 50.0 ), QSizeF( 40.0, 50.0 ) );
addShape( "Ellipse", ShapeFactory::Ellipse, "IndianRed",
QPointF( 80.0, 130.0 ), QSizeF( 50.0, 40.0 ) );
addShape( "Ring", ShapeFactory::Ring, "DarkOliveGreen",
QPointF( 30.0, 165.0 ), QSizeF( 40.0, 40.0 ) );
addShape( "Triangle", ShapeFactory::Triangle, "SandyBrown",
QPointF( 165.0, 165.0 ), QSizeF( 60.0, 40.0 ) );
addShape( "Star", ShapeFactory::Star, "DarkViolet",
QPointF( 165.0, 50.0 ), QSizeF( 40.0, 50.0 ) );
addShape( "Hexagon", ShapeFactory::Hexagon, "DarkSlateGray",
QPointF( 120.0, 70.0 ), QSizeF( 50.0, 50.0 ) );
}
void Plot::addShape( const QString &title,
ShapeFactory::Shape shape, const QColor &color,
const QPointF &pos, const QSizeF &size )
{
QwtPlotShapeItem *item = new QwtPlotShapeItem( title );
item->setItemAttribute( QwtPlotItem::Legend, true );
item->setLegendMode( QwtPlotShapeItem::LegendShape );
item->setLegendIconSize( QSize( 20, 20 ) );
item->setRenderHint( QwtPlotItem::RenderAntialiased, true );
item->setShape( ShapeFactory::path( shape, pos, size ) );
QColor fillColor = color;
fillColor.setAlpha( 200 );
QPen pen( color, 3 );
pen.setJoinStyle( Qt::MiterJoin );
item->setPen( pen );
item->setBrush( fillColor );
item->attach( this );
}
void Plot::exportPlot()
{
QwtPlotRenderer renderer;
renderer.exportTo( this, "shapes.pdf" );
}
void Plot::setMode( int mode )
{
d_editor->setMode( static_cast<Editor::Mode>( mode ) );
}

View File

@ -0,0 +1,33 @@
#ifndef _PLOT_H
#define _PLOT_H
#include <qwt_plot.h>
#include "shapefactory.h"
class QColor;
class QSizeF;
class QPointF;
class Editor;
class Plot: public QwtPlot
{
Q_OBJECT
public:
Plot( QWidget *parent = NULL );
public Q_SLOTS:
void exportPlot();
void setMode( int );
private:
void populate();
void addShape( const QString &title,
ShapeFactory::Shape, const QColor &,
const QPointF &, const QSizeF & );
Editor *d_editor;
};
#endif

View File

@ -0,0 +1,113 @@
#include "shapefactory.h"
QPainterPath ShapeFactory::path( Shape shape,
const QPointF &pos, const QSizeF &size )
{
QRectF rect;
rect.setSize( size );
rect.moveCenter( pos );
QPainterPath path;
switch( shape )
{
case Rect:
{
path.addRect( rect );
break;
}
case Triangle:
{
QPolygonF triangle;
triangle += rect.bottomLeft();
triangle += QPointF( rect.center().x(), rect.top() );
triangle += rect.bottomRight();
path.addPolygon( triangle );
break;
}
case Ellipse:
{
path.addEllipse( rect );
break;
}
case Ring:
{
path.addEllipse( rect );
const double w = 0.25 * rect.width();
path.addEllipse( rect.adjusted( w, w, -w, -w ) );
break;
}
case Star:
{
const double cos30 = 0.866025;
const double dy = 0.25 * size.height();
const double dx = 0.5 * size.width() * cos30 / 3.0;
double x1 = pos.x() - 3 * dx;
double y1 = pos.y() - 2 * dy;
const double x2 = x1 + 1 * dx;
const double x3 = x1 + 2 * dx;
const double x4 = x1 + 3 * dx;
const double x5 = x1 + 4 * dx;
const double x6 = x1 + 5 * dx;
const double x7 = x1 + 6 * dx;
const double y2 = y1 + 1 * dy;
const double y3 = y1 + 2 * dy;
const double y4 = y1 + 3 * dy;
const double y5 = y1 + 4 * dy;
QPolygonF star;
star += QPointF( x4, y1 );
star += QPointF( x5, y2 );
star += QPointF( x7, y2 );
star += QPointF( x6, y3 );
star += QPointF( x7, y4 );
star += QPointF( x5, y4 );
star += QPointF( x4, y5 );
star += QPointF( x3, y4 );
star += QPointF( x1, y4 );
star += QPointF( x2, y3 );
star += QPointF( x1, y2 );
star += QPointF( x3, y2 );
path.addPolygon( star );
break;
}
case Hexagon:
{
const double cos30 = 0.866025;
const double dx = 0.5 * size.width() - cos30;
const double dy = 0.25 * size.height();
double x1 = pos.x() - dx;
double y1 = pos.y() - 2 * dy;
const double x2 = x1 + 1 * dx;
const double x3 = x1 + 2 * dx;
const double y2 = y1 + 1 * dy;
const double y3 = y1 + 3 * dy;
const double y4 = y1 + 4 * dy;
QPolygonF hexagon;
hexagon += QPointF( x2, y1 );
hexagon += QPointF( x3, y2 );
hexagon += QPointF( x3, y3 );
hexagon += QPointF( x2, y4 );
hexagon += QPointF( x1, y3 );
hexagon += QPointF( x1, y2 );
path.addPolygon( hexagon );
break;
}
};
path.closeSubpath();
return path;
}

View File

@ -0,0 +1,21 @@
#ifndef _SHAPE_FACTORY_H_
#define _SHAPE_FACTORY_H_
#include <qpainterpath.h>
namespace ShapeFactory
{
enum Shape
{
Rect,
Triangle,
Ellipse,
Ring,
Star,
Hexagon
};
QPainterPath path( Shape, const QPointF &, const QSizeF & );
};
#endif

View File

@ -0,0 +1,23 @@
TARGET = legends
TEMPLATE = app
MOC_DIR = temp/moc
RCC_DIR = temp/rcc
UI_DIR = temp/ui
OBJECTS_DIR = temp/obj
DESTDIR = $$PWD/../bin
HEADERS = \
mainwindow.h \
panel.h \
settings.h \
plot.h
SOURCES = \
mainwindow.cpp \
panel.cpp \
plot.cpp \
main.cpp
include ($$PWD/../../qwt/qwt.pri)
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../../qwt

View File

@ -0,0 +1,14 @@
#include <qapplication.h>
#include "mainwindow.h"
int main ( int argc, char **argv )
{
QApplication a( argc, argv );
a.setStyle( "Windows" );
MainWindow w;
w.resize( 700, 500 );
w.show();
return a.exec();
}

View File

@ -0,0 +1,61 @@
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qlayout.h>
#include <qwt_plot_renderer.h>
#include <qwt_plot_canvas.h>
#include "plot.h"
#include "panel.h"
#include "mainwindow.h"
MainWindow::MainWindow( QWidget *parent ):
QMainWindow( parent )
{
d_plot = new Plot();
Settings settings;
settings.legend.isEnabled = true;
settings.legend.position = QwtPlot::BottomLegend;
settings.legendItem.isEnabled = false;
settings.legendItem.numColumns = 1;
settings.legendItem.alignment = Qt::AlignRight | Qt::AlignVCenter;
settings.legendItem.backgroundMode = 0;
settings.legendItem.size = d_plot->canvas()->font().pointSize();
settings.curve.numCurves = 4;
settings.curve.title = "Curve";
d_panel = new Panel();
d_panel->setSettings( settings );
QWidget *box = new QWidget( this );
QHBoxLayout *layout = new QHBoxLayout( box );
layout->addWidget( d_plot, 10 );
layout->addWidget( d_panel );
setCentralWidget( box );
QToolBar *toolBar = new QToolBar( this );
QToolButton *btnExport = new QToolButton( toolBar );
btnExport->setText( "Export" );
toolBar->addWidget( btnExport );
addToolBar( toolBar );
updatePlot();
connect( d_panel, SIGNAL( edited() ), SLOT( updatePlot() ) );
connect( btnExport, SIGNAL( clicked() ), SLOT( exportPlot() ) );
}
void MainWindow::updatePlot()
{
d_plot->applySettings( d_panel->settings() );
}
void MainWindow::exportPlot()
{
QwtPlotRenderer renderer;
renderer.exportTo( d_plot, "legends.pdf" );
}

View File

@ -0,0 +1,20 @@
#include <qmainwindow.h>
class Plot;
class Panel;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow( QWidget *parent = 0 );
private Q_SLOTS:
void updatePlot();
void exportPlot();
private:
Plot *d_plot;
Panel *d_panel;
};

View File

@ -0,0 +1,216 @@
#include "panel.h"
#include "settings.h"
#include <qcheckbox.h>
#include <qspinbox.h>
#include <qcombobox.h>
#include <qgroupbox.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qwt_plot.h>
#include <qwt_plot_legenditem.h>
Panel::Panel( QWidget *parent ):
QWidget( parent )
{
// create widgets
d_legend.checkBox = new QCheckBox( "Enabled" );
d_legend.positionBox = new QComboBox();
d_legend.positionBox->addItem( "Left", QwtPlot::LeftLegend );
d_legend.positionBox->addItem( "Right", QwtPlot::RightLegend );
d_legend.positionBox->addItem( "Bottom", QwtPlot::BottomLegend );
d_legend.positionBox->addItem( "Top", QwtPlot::TopLegend );
d_legend.positionBox->addItem( "External", QwtPlot::TopLegend + 1 );
d_legendItem.checkBox = new QCheckBox( "Enabled" );
d_legendItem.numColumnsBox = new QSpinBox();
d_legendItem.numColumnsBox->setRange( 0, 10 );
d_legendItem.numColumnsBox->setSpecialValueText( "Unlimited" );
d_legendItem.hAlignmentBox = new QComboBox();
d_legendItem.hAlignmentBox->addItem( "Left", Qt::AlignLeft );
d_legendItem.hAlignmentBox->addItem( "Centered", Qt::AlignHCenter );
d_legendItem.hAlignmentBox->addItem( "Right", Qt::AlignRight );
d_legendItem.vAlignmentBox = new QComboBox();
d_legendItem.vAlignmentBox->addItem( "Top", Qt::AlignTop );
d_legendItem.vAlignmentBox->addItem( "Centered", Qt::AlignVCenter );
d_legendItem.vAlignmentBox->addItem( "Bottom", Qt::AlignBottom );
d_legendItem.backgroundBox = new QComboBox();
d_legendItem.backgroundBox->addItem( "Legend",
QwtPlotLegendItem::LegendBackground );
d_legendItem.backgroundBox->addItem( "Items",
QwtPlotLegendItem::ItemBackground );
d_legendItem.sizeBox = new QSpinBox();
d_legendItem.sizeBox->setRange( 8, 22 );
d_curve.numCurves = new QSpinBox();
d_curve.numCurves->setRange( 0, 99 );
d_curve.title = new QLineEdit();
// layout
QGroupBox *legendBox = new QGroupBox( "Legend" );
QGridLayout *legendBoxLayout = new QGridLayout( legendBox );
int row = 0;
legendBoxLayout->addWidget( d_legend.checkBox, row, 0, 1, -1 );
row++;
legendBoxLayout->addWidget( new QLabel( "Position" ), row, 0 );
legendBoxLayout->addWidget( d_legend.positionBox, row, 1 );
QGroupBox *legendItemBox = new QGroupBox( "Legend Item" );
QGridLayout *legendItemBoxLayout = new QGridLayout( legendItemBox );
row = 0;
legendItemBoxLayout->addWidget( d_legendItem.checkBox, row, 0, 1, -1 );
row++;
legendItemBoxLayout->addWidget( new QLabel( "Columns" ), row, 0 );
legendItemBoxLayout->addWidget( d_legendItem.numColumnsBox, row, 1 );
row++;
legendItemBoxLayout->addWidget( new QLabel( "Horizontal" ), row, 0 );
legendItemBoxLayout->addWidget( d_legendItem.hAlignmentBox, row, 1 );
row++;
legendItemBoxLayout->addWidget( new QLabel( "Vertical" ), row, 0 );
legendItemBoxLayout->addWidget( d_legendItem.vAlignmentBox, row, 1 );
row++;
legendItemBoxLayout->addWidget( new QLabel( "Background" ), row, 0 );
legendItemBoxLayout->addWidget( d_legendItem.backgroundBox, row, 1 );
row++;
legendItemBoxLayout->addWidget( new QLabel( "Size" ), row, 0 );
legendItemBoxLayout->addWidget( d_legendItem.sizeBox, row, 1 );
QGroupBox *curveBox = new QGroupBox( "Curves" );
QGridLayout *curveBoxLayout = new QGridLayout( curveBox );
row = 0;
curveBoxLayout->addWidget( new QLabel( "Number" ), row, 0 );
curveBoxLayout->addWidget( d_curve.numCurves, row, 1 );
row++;
curveBoxLayout->addWidget( new QLabel( "Title" ), row, 0 );
curveBoxLayout->addWidget( d_curve.title, row, 1 );
QVBoxLayout *layout = new QVBoxLayout( this );
layout->addWidget( legendBox );
layout->addWidget( legendItemBox );
layout->addWidget( curveBox );
layout->addStretch( 10 );
connect( d_legend.checkBox,
SIGNAL( stateChanged( int ) ), SIGNAL( edited() ) );
connect( d_legend.positionBox,
SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );
connect( d_legendItem.checkBox,
SIGNAL( stateChanged( int ) ), SIGNAL( edited() ) );
connect( d_legendItem.numColumnsBox,
SIGNAL( valueChanged( int ) ), SIGNAL( edited() ) );
connect( d_legendItem.hAlignmentBox,
SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );
connect( d_legendItem.vAlignmentBox,
SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );
connect( d_legendItem.backgroundBox,
SIGNAL( currentIndexChanged( int ) ), SIGNAL( edited() ) );
connect( d_curve.numCurves,
SIGNAL( valueChanged( int ) ), SIGNAL( edited() ) );
connect( d_legendItem.sizeBox,
SIGNAL( valueChanged( int ) ), SIGNAL( edited() ) );
connect( d_curve.title,
SIGNAL( textEdited( const QString & ) ), SIGNAL( edited() ) );
}
void Panel::setSettings( const Settings &settings)
{
blockSignals( true );
d_legend.checkBox->setCheckState(
settings.legend.isEnabled ? Qt::Checked : Qt::Unchecked );
d_legend.positionBox->setCurrentIndex( settings.legend.position );
d_legendItem.checkBox->setCheckState(
settings.legendItem.isEnabled ? Qt::Checked : Qt::Unchecked );
d_legendItem.numColumnsBox->setValue( settings.legendItem.numColumns );
int align = settings.legendItem.alignment;
if ( align & Qt::AlignLeft )
d_legendItem.hAlignmentBox->setCurrentIndex( 0 );
else if ( align & Qt::AlignRight )
d_legendItem.hAlignmentBox->setCurrentIndex( 2 );
else
d_legendItem.hAlignmentBox->setCurrentIndex( 1 );
if ( align & Qt::AlignTop )
d_legendItem.vAlignmentBox->setCurrentIndex( 0 );
else if ( align & Qt::AlignBottom )
d_legendItem.vAlignmentBox->setCurrentIndex( 2 );
else
d_legendItem.vAlignmentBox->setCurrentIndex( 1 );
d_legendItem.backgroundBox->setCurrentIndex(
settings.legendItem.backgroundMode );
d_legendItem.sizeBox->setValue( settings.legendItem.size );
d_curve.numCurves->setValue( settings.curve.numCurves );
d_curve.title->setText( settings.curve.title );
blockSignals( false );
}
Settings Panel::settings() const
{
Settings s;
s.legend.isEnabled =
d_legend.checkBox->checkState() == Qt::Checked;
s.legend.position = d_legend.positionBox->currentIndex();
s.legendItem.isEnabled =
d_legendItem.checkBox->checkState() == Qt::Checked;
s.legendItem.numColumns = d_legendItem.numColumnsBox->value();
int align = 0;
int hIndex = d_legendItem.hAlignmentBox->currentIndex();
if ( hIndex == 0 )
align |= Qt::AlignLeft;
else if ( hIndex == 2 )
align |= Qt::AlignRight;
else
align |= Qt::AlignHCenter;
int vIndex = d_legendItem.vAlignmentBox->currentIndex();
if ( vIndex == 0 )
align |= Qt::AlignTop;
else if ( vIndex == 2 )
align |= Qt::AlignBottom;
else
align |= Qt::AlignVCenter;
s.legendItem.alignment = align;
s.legendItem.backgroundMode =
d_legendItem.backgroundBox->currentIndex();
s.legendItem.size = d_legendItem.sizeBox->value();
s.curve.numCurves = d_curve.numCurves->value();
s.curve.title = d_curve.title->text();
return s;
}

View File

@ -0,0 +1,52 @@
#ifndef _PANEL_
#define _PANEL_
#include "settings.h"
#include <qwidget.h>
class QCheckBox;
class QComboBox;
class QSpinBox;
class QLineEdit;
class Panel: public QWidget
{
Q_OBJECT
public:
Panel( QWidget *parent = NULL );
void setSettings( const Settings &);
Settings settings() const;
Q_SIGNALS:
void edited();
private:
struct
{
QCheckBox *checkBox;
QComboBox *positionBox;
} d_legend;
struct
{
QCheckBox *checkBox;
QSpinBox *numColumnsBox;
QComboBox *hAlignmentBox;
QComboBox *vAlignmentBox;
QComboBox *backgroundBox;
QSpinBox *sizeBox;
} d_legendItem;
struct
{
QSpinBox *numCurves;
QLineEdit *title;
} d_curve;
};
#endif

View File

@ -0,0 +1,263 @@
#include "plot.h"
#include "settings.h"
#include <qwt_plot_curve.h>
#include <qwt_plot_legenditem.h>
#include <qwt_legend.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_layout.h>
class LegendItem: public QwtPlotLegendItem
{
public:
LegendItem()
{
setRenderHint( QwtPlotItem::RenderAntialiased );
QColor color( Qt::white );
setTextPen( color );
#if 1
setBorderPen( color );
QColor c( Qt::gray );
c.setAlpha( 200 );
setBackgroundBrush( c );
#endif
}
};
class Curve: public QwtPlotCurve
{
public:
Curve( int index ):
d_index( index )
{
setRenderHint( QwtPlotItem::RenderAntialiased );
initData();
}
void setCurveTitle( const QString &title )
{
QString txt("%1 %2");
setTitle( QString( "%1 %2" ).arg( title ).arg( d_index ) );
}
void initData()
{
QVector<QPointF> points;
double y = qrand() % 1000;
for ( double x = 0.0; x <= 1000.0; x += 100.0 )
{
double off = qrand() % 200 - 100;
if ( y + off > 980.0 || y + off < 20.0 )
off = -off;
y += off;
points += QPointF( x, y );
}
setSamples( points );
}
private:
const int d_index;
};
Plot::Plot( QWidget *parent ):
QwtPlot( parent ),
d_externalLegend( NULL ),
d_legendItem( NULL ),
d_isDirty( false )
{
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setFocusIndicator( QwtPlotCanvas::CanvasFocusIndicator );
canvas->setFocusPolicy( Qt::StrongFocus );
canvas->setPalette( Qt::black );
setCanvas( canvas );
setAutoReplot( false );
setTitle( "Legend Test" );
setFooter( "Footer" );
// grid
QwtPlotGrid *grid = new QwtPlotGrid;
grid->enableXMin( true );
grid->setMajorPen( Qt::gray, 0, Qt::DotLine );
grid->setMinorPen( Qt::darkGray, 0, Qt::DotLine );
grid->attach( this );
// axis
setAxisScale( QwtPlot::yLeft, 0.0, 1000.0 );
setAxisScale( QwtPlot::xBottom, 0.0, 1000.0 );
}
Plot::~Plot()
{
delete d_externalLegend;
}
void Plot::insertCurve()
{
static int counter = 1;
const char *colors[] =
{
"LightSalmon",
"SteelBlue",
"Yellow",
"Fuchsia",
"PaleGreen",
"PaleTurquoise",
"Cornsilk",
"HotPink",
"Peru",
"Maroon"
};
const int numColors = sizeof( colors ) / sizeof( colors[0] );
QwtPlotCurve *curve = new Curve( counter++ );
curve->setPen( QColor( colors[ counter % numColors ] ), 2 );
curve->attach( this );
}
void Plot::applySettings( const Settings &settings )
{
d_isDirty = false;
setAutoReplot( true );
if ( settings.legend.isEnabled )
{
if ( settings.legend.position > QwtPlot::TopLegend )
{
if ( legend() )
{
// remove legend controlled by the plot
insertLegend( NULL );
}
if ( d_externalLegend == NULL )
{
d_externalLegend = new QwtLegend();
d_externalLegend->setWindowTitle("Plot Legend");
connect(
this,
SIGNAL( legendDataChanged( const QVariant &,
const QList<QwtLegendData> & ) ),
d_externalLegend,
SLOT( updateLegend( const QVariant &,
const QList<QwtLegendData> & ) ) );
d_externalLegend->show();
// populate the new legend
updateLegend();
}
}
else
{
delete d_externalLegend;
d_externalLegend = NULL;
if ( legend() == NULL ||
plotLayout()->legendPosition() != settings.legend.position )
{
insertLegend( new QwtLegend(),
QwtPlot::LegendPosition( settings.legend.position ) );
}
}
}
else
{
insertLegend( NULL );
delete d_externalLegend;
d_externalLegend = NULL;
}
if ( settings.legendItem.isEnabled )
{
if ( d_legendItem == NULL )
{
d_legendItem = new LegendItem();
d_legendItem->attach( this );
}
d_legendItem->setMaxColumns( settings.legendItem.numColumns );
d_legendItem->setAlignment( Qt::Alignment( settings.legendItem.alignment ) );
d_legendItem->setBackgroundMode(
QwtPlotLegendItem::BackgroundMode( settings.legendItem.backgroundMode ) );
if ( settings.legendItem.backgroundMode ==
QwtPlotLegendItem::ItemBackground )
{
d_legendItem->setBorderRadius( 4 );
d_legendItem->setMargin( 0 );
d_legendItem->setSpacing( 4 );
d_legendItem->setItemMargin( 2 );
}
else
{
d_legendItem->setBorderRadius( 8 );
d_legendItem->setMargin( 4 );
d_legendItem->setSpacing( 2 );
d_legendItem->setItemMargin( 0 );
}
QFont font = d_legendItem->font();
font.setPointSize( settings.legendItem.size );
d_legendItem->setFont( font );
}
else
{
delete d_legendItem;
d_legendItem = NULL;
}
QwtPlotItemList curveList = itemList( QwtPlotItem::Rtti_PlotCurve );
if ( curveList.size() != settings.curve.numCurves )
{
while ( curveList.size() > settings.curve.numCurves )
{
QwtPlotItem* curve = curveList.takeFirst();
delete curve;
}
for ( int i = curveList.size(); i < settings.curve.numCurves; i++ )
insertCurve();
}
curveList = itemList( QwtPlotItem::Rtti_PlotCurve );
for ( int i = 0; i < curveList.count(); i++ )
{
Curve* curve = static_cast<Curve*>( curveList[i] );
curve->setCurveTitle( settings.curve.title );
int sz = 0.5 * settings.legendItem.size;
curve->setLegendIconSize( QSize( sz, sz ) );
}
setAutoReplot( false );
if ( d_isDirty )
{
d_isDirty = false;
replot();
}
}
void Plot::replot()
{
if ( autoReplot() )
{
d_isDirty = true;
return;
}
QwtPlot::replot();
}

View File

@ -0,0 +1,32 @@
#ifndef _PLOT_H_
#define _PLOT_H_
#include <qwt_plot.h>
class Settings;
class LegendItem;
class QwtLegend;
class Plot: public QwtPlot
{
Q_OBJECT
public:
Plot( QWidget *parent = NULL );
virtual ~Plot();
public Q_SLOTS:
void applySettings( const Settings & );
public:
virtual void replot();
private:
void insertCurve();
QwtLegend *d_externalLegend;
LegendItem *d_legendItem;
bool d_isDirty;
};
#endif

View File

@ -0,0 +1,47 @@
#ifndef _SETTINGS_
#define _SETTINGS_
#include <qstring.h>
class Settings
{
public:
Settings()
{
legend.isEnabled = false;
legend.position = 0;
legendItem.isEnabled = false;
legendItem.numColumns = 0;
legendItem.alignment = 0;
legendItem.backgroundMode = 0;
legendItem.size = 12;
curve.numCurves = 0;
curve.title = "Curve";
}
struct
{
bool isEnabled;
int position;
} legend;
struct
{
bool isEnabled;
int numColumns;
int alignment;
int backgroundMode;
int size;
} legendItem;
struct
{
int numCurves;
QString title;
} curve;
};
#endif

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;
};

Some files were not shown because too many files have changed in this diff Show More