Add files from zip

This commit is contained in:
2023-10-31 09:22:42 +01:00
parent 6bacdc5f6d
commit 4dae68036f
2788 changed files with 492537 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "IncrementalPlot.h"
#include <QwtPlot>
#include <QwtPlotCurve>
#include <QwtSymbol>
#include <QwtScaleMap>
#include <QwtPlotDirectPainter>
#include <QwtPainter>
namespace
{
class CurveData : public QwtArraySeriesData< QPointF >
{
public:
virtual QRectF boundingRect() const QWT_OVERRIDE
{
if ( cachedBoundingRect.width() < 0.0 )
cachedBoundingRect = qwtBoundingRect( *this );
return cachedBoundingRect;
}
inline void append( const QPointF& point )
{
m_samples += point;
}
void clear()
{
m_samples.clear();
m_samples.squeeze();
cachedBoundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 );
}
};
}
IncrementalPlot::IncrementalPlot( QWidget* parent )
: QwtPlot( parent )
, m_curve( NULL )
{
m_directPainter = new QwtPlotDirectPainter( this );
if ( QwtPainter::isX11GraphicsSystem() )
{
#if QT_VERSION < 0x050000
canvas()->setAttribute( Qt::WA_PaintOutsidePaintEvent, true );
#endif
canvas()->setAttribute( Qt::WA_PaintOnScreen, true );
}
m_curve = new QwtPlotCurve( "Test Curve" );
m_curve->setData( new CurveData() );
showSymbols( true );
m_curve->attach( this );
setAutoReplot( false );
}
IncrementalPlot::~IncrementalPlot()
{
delete m_curve;
}
void IncrementalPlot::appendPoint( const QPointF& point )
{
CurveData* curveData = static_cast< CurveData* >( m_curve->data() );
curveData->append( point );
const bool doClip = !canvas()->testAttribute( Qt::WA_PaintOnScreen );
if ( doClip && m_curve->symbol() )
{
/*
Depending on the platform setting a clip might be an important
performance issue. F.e. for Qt Embedded this reduces the
part of the backing store that has to be copied out - maybe
to an unaccelerated frame buffer device.
*/
const QwtScaleMap xMap = canvasMap( m_curve->xAxis() );
const QwtScaleMap yMap = canvasMap( m_curve->yAxis() );
const QSize symbolSize = m_curve->symbol()->size();
QRect r( 0, 0, symbolSize.width() + 2, symbolSize.height() + 2 );
const QPointF center = QwtScaleMap::transform( xMap, yMap, point );
r.moveCenter( center.toPoint() );
m_directPainter->setClipRegion( r );
}
m_directPainter->drawSeries( m_curve,
curveData->size() - 1, curveData->size() - 1 );
}
void IncrementalPlot::clearPoints()
{
CurveData* curveData = static_cast< CurveData* >( m_curve->data() );
curveData->clear();
replot();
}
void IncrementalPlot::showSymbols( bool on )
{
if ( on )
{
m_curve->setStyle( QwtPlotCurve::NoCurve );
m_curve->setSymbol( new QwtSymbol( QwtSymbol::XCross,
Qt::NoBrush, QPen( Qt::white ), QSize( 4, 4 ) ) );
}
else
{
m_curve->setPen( Qt::white );
m_curve->setStyle( QwtPlotCurve::Dots );
m_curve->setSymbol( NULL );
}
replot();
}
#include "moc_IncrementalPlot.cpp"

View File

@@ -0,0 +1,30 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#pragma once
#include <QwtPlot>
class QwtPlotCurve;
class QwtPlotDirectPainter;
class IncrementalPlot : public QwtPlot
{
Q_OBJECT
public:
IncrementalPlot( QWidget* parent = NULL );
virtual ~IncrementalPlot();
void appendPoint( const QPointF& );
void clearPoints();
public Q_SLOTS:
void showSymbols( bool );
private:
QwtPlotCurve* m_curve;
QwtPlotDirectPainter* m_directPainter;
};

View File

@@ -0,0 +1,207 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "RandomPlot.h"
#include "MainWindow.h"
#include "start.xpm"
#include "clear.xpm"
#include <QAction>
#include <QLabel>
#include <QLayout>
#include <QStatusBar>
#include <QToolBar>
#include <QSpinBox>
#include <QCheckBox>
#include <QWhatsThis>
#include <QPixmap>
namespace
{
class ToolBar : public QToolBar
{
public:
ToolBar( QMainWindow* parent )
: QToolBar( parent )
{
}
void addSpacing( int spacing )
{
QLabel* label = new QLabel();
label->setFixedWidth( spacing );
addWidget( label );
}
};
}
class Counter : public QWidget
{
public:
Counter( const QString& prefix, const QString& suffix,
int min, int max, int step, QWidget* parent = NULL )
: QWidget( parent )
{
QHBoxLayout* layout = new QHBoxLayout( this );
if ( !prefix.isEmpty() )
layout->addWidget( new QLabel( prefix + " " ) );
m_counter = new QSpinBox();
m_counter->setRange( min, max );
m_counter->setSingleStep( step );
layout->addWidget( m_counter );
if ( !suffix.isEmpty() )
layout->addWidget( new QLabel( QString( " " ) + suffix ) );
}
void setValue( int value ) { m_counter->setValue( value ); }
int value() const { return m_counter->value(); }
private:
QSpinBox* m_counter;
};
MainWindow::MainWindow()
{
addToolBar( toolBar() );
#ifndef QT_NO_STATUSBAR
( void )statusBar();
#endif
m_plot = new RandomPlot();
const int margin = 4;
m_plot->setContentsMargins( margin, margin, margin, margin );
setCentralWidget( m_plot );
connect( m_startAction, SIGNAL(toggled(bool)), this, SLOT(appendPoints(bool)) );
connect( m_clearAction, SIGNAL(triggered()), m_plot, SLOT(clear()) );
connect( m_symbolType, SIGNAL(toggled(bool)), m_plot, SLOT(showSymbols(bool)) );
connect( m_plot, SIGNAL(running(bool)), this, SLOT(showRunning(bool)) );
connect( m_plot, SIGNAL(elapsed(int)), this, SLOT(showElapsed(int)) );
initWhatsThis();
setContextMenuPolicy( Qt::NoContextMenu );
}
QToolBar* MainWindow::toolBar()
{
setToolButtonStyle( Qt::ToolButtonTextUnderIcon );
setIconSize( QSize( 22, 22 ) );
m_startAction = new QAction( QPixmap( start_xpm ), "Start", this );
m_startAction->setCheckable( true );
m_clearAction = new QAction( QPixmap( clear_xpm ), "Clear", this );
QAction* whatsThisAction = QWhatsThis::createAction();
whatsThisAction->setText( "Help" );
QWidget* hBox = new QWidget();
m_symbolType = new QCheckBox( "Symbols", hBox );
m_symbolType->setChecked( true );
m_randomCount = new Counter( "Points", QString(), 1, 100000, 100 );
m_randomCount->setValue( 1000 );
m_timerCount = new Counter( "Delay", "ms", 0, 100000, 100 );
m_timerCount->setValue( 0 );
QHBoxLayout* layout = new QHBoxLayout( hBox );
layout->setContentsMargins( QMargins() );
layout->setSpacing( 0 );
layout->addSpacing( 10 );
layout->addWidget( new QWidget( hBox ), 10 ); // spacer
layout->addWidget( m_symbolType );
layout->addSpacing( 5 );
layout->addWidget( m_randomCount );
layout->addSpacing( 5 );
layout->addWidget( m_timerCount );
showRunning( false );
ToolBar* toolBar = new ToolBar( this );
toolBar->setAllowedAreas( Qt::TopToolBarArea | Qt::BottomToolBarArea );
toolBar->addAction( m_startAction );
toolBar->addAction( m_clearAction );
toolBar->addAction( whatsThisAction );
toolBar->addWidget( hBox );
return toolBar;
}
void MainWindow::appendPoints( bool on )
{
if ( on )
{
m_plot->append( m_timerCount->value(),
m_randomCount->value() );
}
else
{
m_plot->stop();
}
}
void MainWindow::showRunning( bool running )
{
m_randomCount->setEnabled( !running );
m_timerCount->setEnabled( !running );
m_startAction->setChecked( running );
m_startAction->setText( running ? "Stop" : "Start" );
}
void MainWindow::showElapsed( int ms )
{
QString text;
text.setNum( ms );
text += " ms";
statusBar()->showMessage( text );
}
void MainWindow::initWhatsThis()
{
const char* text1 =
"Zooming is enabled until the selected area gets "
"too small for the significance on the axes.\n\n"
"You can zoom in using the left mouse button.\n"
"The middle mouse button is used to go back to the "
"previous zoomed area.\n"
"The right mouse button is used to unzoom completely.";
const char* text2 =
"Number of random points that will be generated.";
const char* text3 =
"Delay between the generation of two random points.";
const char* text4 =
"Start generation of random points.\n\n"
"The intention of this example is to show how to implement "
"growing curves. The points will be generated and displayed "
"one after the other.\n"
"To check the performance, a small delay and a large number "
"of points are useful. To watch the curve growing, a delay "
" > 300 ms and less points are better.\n"
"To inspect the curve, stacked zooming is implemented using the "
"mouse buttons on the plot.";
const char* text5 = "Remove all points.";
m_plot->setWhatsThis( text1 );
m_randomCount->setWhatsThis( text2 );
m_timerCount->setWhatsThis( text3 );
m_startAction->setWhatsThis( text4 );
m_clearAction->setWhatsThis( text5 );
}
#include "moc_MainWindow.cpp"

View File

@@ -0,0 +1,38 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#pragma once
#include <QMainWindow>
class RandomPlot;
class Counter;
class QCheckBox;
class QAction;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
private Q_SLOTS:
void showRunning( bool );
void appendPoints( bool );
void showElapsed( int );
private:
QToolBar* toolBar();
void initWhatsThis();
private:
Counter* m_randomCount;
Counter* m_timerCount;
QCheckBox* m_symbolType;
QAction* m_startAction;
QAction* m_clearAction;
RandomPlot* m_plot;
};

25
examples/realtime/README Normal file
View File

@@ -0,0 +1,25 @@
1) Incremental plots
IncrementalPlot shows an example how to implement a plot that
displays growing data.
The example produces random data when you push the start button.
With 'Timer' you can adjust the intervall between the
the generation of the points, with 'Points' you can set the number
of points to be generated.
Unfortunately in Qt4 incremental painting is not possible with QPaintEngines
that doesn't support the QPaintEngine::PaintOutsidePaintEvent feature.
( These are all common paint engines beside the OpenGL engine, but this one
is not supported by Qwt yet. )
That is the reason why you can see much faster repaints with Qt3.
2) Stacked Zooming with scrollbars
ScrollZoomer adds scrollbars for zooming. There are a couple of
reasons why the implementation is a hack and therefore the class
is not part of the Qwt lib, but it should be working with all
types of QwtPlots. Copy the code of scrollbar.[h|cpp] and
scrollzoomer.[h|cpp] to the application code.
Uwe

View File

@@ -0,0 +1,150 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "RandomPlot.h"
#include "ScrollZoomer.h"
#include <QwtPlotGrid>
#include <QwtPlotCanvas>
#include <QwtPlotLayout>
#include <QwtScaleWidget>
#include <QwtScaleDraw>
#include <QwtMath>
#include <QPen>
#include <QTimer>
namespace
{
const unsigned int c_rangeMax = 1000;
class Zoomer : public ScrollZoomer
{
public:
Zoomer( QWidget* canvas )
: ScrollZoomer( canvas )
{
setRubberBandPen( QPen( Qt::red ) );
}
virtual QwtText trackerTextF( const QPointF& pos ) const QWT_OVERRIDE
{
QColor bg( Qt::white );
QwtText text = QwtPlotZoomer::trackerTextF( pos );
text.setBackgroundBrush( QBrush( bg ) );
return text;
}
virtual void rescale() QWT_OVERRIDE
{
QwtScaleWidget* scaleWidget = plot()->axisWidget( yAxis() );
QwtScaleDraw* sd = scaleWidget->scaleDraw();
double minExtent = 0.0;
if ( zoomRectIndex() > 0 )
{
// When scrolling in vertical direction
// the plot is jumping in horizontal direction
// because of the different widths of the labels
// So we better use a fixed extent.
minExtent = sd->spacing() + sd->maxTickLength() + 1;
minExtent += sd->labelSize(
scaleWidget->font(), c_rangeMax ).width();
}
sd->setMinimumExtent( minExtent );
ScrollZoomer::rescale();
}
};
}
RandomPlot::RandomPlot( QWidget* parent )
: IncrementalPlot( parent )
, m_timer( 0 )
, m_timerCount( 0 )
{
setFrameStyle( QFrame::NoFrame );
setLineWidth( 0 );
plotLayout()->setAlignCanvasToScales( true );
QwtPlotGrid* grid = new QwtPlotGrid;
grid->setMajorPen( Qt::gray, 0, Qt::DotLine );
grid->attach( this );
setCanvasBackground( QColor( 29, 100, 141 ) ); // nice blue
setAxisScale( QwtAxis::XBottom, 0, c_rangeMax );
setAxisScale( QwtAxis::YLeft, 0, c_rangeMax );
replot();
// enable zooming
( void ) new Zoomer( canvas() );
}
QSize RandomPlot::sizeHint() const
{
return QSize( 540, 400 );
}
void RandomPlot::appendPoint()
{
double x = qwtRand() % c_rangeMax;
x += ( qwtRand() % 100 ) / 100;
double y = qwtRand() % c_rangeMax;
y += ( qwtRand() % 100 ) / 100;
IncrementalPlot::appendPoint( QPointF( x, y ) );
if ( --m_timerCount <= 0 )
stop();
}
void RandomPlot::append( int timeout, int count )
{
if ( !m_timer )
{
m_timer = new QTimer( this );
connect( m_timer, SIGNAL(timeout()), SLOT(appendPoint()) );
}
m_timerCount = count;
Q_EMIT running( true );
m_timeStamp.start();
QwtPlotCanvas* plotCanvas = qobject_cast< QwtPlotCanvas* >( canvas() );
plotCanvas->setPaintAttribute( QwtPlotCanvas::BackingStore, false );
m_timer->start( timeout );
}
void RandomPlot::stop()
{
Q_EMIT elapsed( m_timeStamp.elapsed() );
if ( m_timer )
{
m_timer->stop();
Q_EMIT running( false );
}
QwtPlotCanvas* plotCanvas = qobject_cast< QwtPlotCanvas* >( canvas() );
plotCanvas->setPaintAttribute( QwtPlotCanvas::BackingStore, true );
}
void RandomPlot::clear()
{
clearPoints();
replot();
}
#include "moc_RandomPlot.cpp"

View File

@@ -0,0 +1,41 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#pragma once
#include "IncrementalPlot.h"
#include <QElapsedTimer>
class QTimer;
class RandomPlot : public IncrementalPlot
{
Q_OBJECT
public:
RandomPlot( QWidget* parent = NULL );
virtual QSize sizeHint() const QWT_OVERRIDE;
Q_SIGNALS:
void running( bool );
void elapsed( int ms );
public Q_SLOTS:
void clear();
void stop();
void append( int timeout, int count );
private Q_SLOTS:
void appendPoint();
private:
void initCurve();
QTimer* m_timer;
int m_timerCount;
QElapsedTimer m_timeStamp;
};

View File

@@ -0,0 +1,179 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "ScrollBar.h"
#include <QStyle>
#include <QStyleOption>
ScrollBar::ScrollBar( QWidget* parent )
: QScrollBar( parent )
{
init();
}
ScrollBar::ScrollBar( Qt::Orientation o, QWidget* parent )
: QScrollBar( o, parent )
{
init();
}
ScrollBar::ScrollBar( double minBase, double maxBase,
Qt::Orientation o, QWidget* parent )
: QScrollBar( o, parent )
{
init();
setBase( minBase, maxBase );
moveSlider( minBase, maxBase );
}
void ScrollBar::init()
{
m_inverted = orientation() == Qt::Vertical;
m_baseTicks = 1000000;
m_minBase = 0.0;
m_maxBase = 1.0;
moveSlider( m_minBase, m_maxBase );
connect( this, SIGNAL(sliderMoved(int)), SLOT(catchSliderMoved(int)) );
connect( this, SIGNAL(valueChanged(int)), SLOT(catchValueChanged(int)) );
}
void ScrollBar::setInverted( bool inverted )
{
if ( m_inverted != inverted )
{
m_inverted = inverted;
moveSlider( minSliderValue(), maxSliderValue() );
}
}
bool ScrollBar::isInverted() const
{
return m_inverted;
}
void ScrollBar::setBase( double min, double max )
{
if ( min != m_minBase || max != m_maxBase )
{
m_minBase = min;
m_maxBase = max;
moveSlider( minSliderValue(), maxSliderValue() );
}
}
void ScrollBar::moveSlider( double min, double max )
{
const int sliderTicks = qRound( ( max - min ) /
( m_maxBase - m_minBase ) * m_baseTicks );
// setRange initiates a valueChanged of the scrollbars
// in some situations. So we block
// and unblock the signals.
blockSignals( true );
setRange( sliderTicks / 2, m_baseTicks - sliderTicks / 2 );
int steps = sliderTicks / 200;
if ( steps <= 0 )
steps = 1;
setSingleStep( steps );
setPageStep( sliderTicks );
int tick = mapToTick( min + ( max - min ) / 2 );
if ( isInverted() )
tick = m_baseTicks - tick;
setSliderPosition( tick );
blockSignals( false );
}
double ScrollBar::minBaseValue() const
{
return m_minBase;
}
double ScrollBar::maxBaseValue() const
{
return m_maxBase;
}
void ScrollBar::sliderRange( int value, double& min, double& max ) const
{
if ( isInverted() )
value = m_baseTicks - value;
const int visibleTicks = pageStep();
min = mapFromTick( value - visibleTicks / 2 );
max = mapFromTick( value + visibleTicks / 2 );
}
double ScrollBar::minSliderValue() const
{
double min, dummy;
sliderRange( value(), min, dummy );
return min;
}
double ScrollBar::maxSliderValue() const
{
double max, dummy;
sliderRange( value(), dummy, max );
return max;
}
int ScrollBar::mapToTick( double v ) const
{
const double pos = ( v - m_minBase ) / ( m_maxBase - m_minBase ) * m_baseTicks;
return static_cast< int >( pos );
}
double ScrollBar::mapFromTick( int tick ) const
{
return m_minBase + ( m_maxBase - m_minBase ) * tick / m_baseTicks;
}
void ScrollBar::catchValueChanged( int value )
{
double min, max;
sliderRange( value, min, max );
Q_EMIT valueChanged( orientation(), min, max );
}
void ScrollBar::catchSliderMoved( int value )
{
double min, max;
sliderRange( value, min, max );
Q_EMIT sliderMoved( orientation(), min, max );
}
int ScrollBar::extent() const
{
QStyleOptionSlider opt;
opt.initFrom( this );
opt.subControls = QStyle::SC_None;
opt.activeSubControls = QStyle::SC_None;
opt.orientation = orientation();
opt.minimum = minimum();
opt.maximum = maximum();
opt.sliderPosition = sliderPosition();
opt.sliderValue = value();
opt.singleStep = singleStep();
opt.pageStep = pageStep();
opt.upsideDown = invertedAppearance();
if ( orientation() == Qt::Horizontal )
opt.state |= QStyle::State_Horizontal;
return style()->pixelMetric( QStyle::PM_ScrollBarExtent, &opt, this );
}
#include "moc_ScrollBar.cpp"

View File

@@ -0,0 +1,55 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#pragma once
#include <QScrollBar>
class ScrollBar : public QScrollBar
{
Q_OBJECT
public:
ScrollBar( QWidget* parent = NULL );
ScrollBar( Qt::Orientation, QWidget* parent = NULL );
ScrollBar( double minBase, double maxBase,
Qt::Orientation o, QWidget* parent = NULL );
void setInverted( bool );
bool isInverted() const;
double minBaseValue() const;
double maxBaseValue() const;
double minSliderValue() const;
double maxSliderValue() const;
int extent() const;
Q_SIGNALS:
void sliderMoved( Qt::Orientation, double, double );
void valueChanged( Qt::Orientation, double, double );
public Q_SLOTS:
virtual void setBase( double min, double max );
virtual void moveSlider( double min, double max );
protected:
void sliderRange( int value, double& min, double& max ) const;
int mapToTick( double ) const;
double mapFromTick( int ) const;
private Q_SLOTS:
void catchValueChanged( int value );
void catchSliderMoved( int value );
private:
void init();
bool m_inverted;
double m_minBase;
double m_maxBase;
int m_baseTicks;
};

View File

@@ -0,0 +1,503 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "ScrollZoomer.h"
#include "ScrollBar.h"
#include <QwtPlotLayout>
#include <QwtScaleWidget>
#include <QResizeEvent>
#include <QMargins>
class ScrollData
{
public:
ScrollData()
: scrollBar( NULL )
, position( ScrollZoomer::OppositeToScale )
, mode( Qt::ScrollBarAsNeeded )
{
}
~ScrollData()
{
delete scrollBar;
}
ScrollBar* scrollBar;
ScrollZoomer::ScrollBarPosition position;
Qt::ScrollBarPolicy mode;
};
ScrollZoomer::ScrollZoomer( QWidget* canvas )
: QwtPlotZoomer( canvas )
, m_cornerWidget( NULL )
, m_hScrollData( NULL )
, m_vScrollData( NULL )
, m_inZoom( false )
{
for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
m_alignCanvasToScales[ axisPos ] = false;
if ( !canvas )
return;
m_hScrollData = new ScrollData;
m_vScrollData = new ScrollData;
}
ScrollZoomer::~ScrollZoomer()
{
delete m_cornerWidget;
delete m_vScrollData;
delete m_hScrollData;
}
void ScrollZoomer::rescale()
{
QwtScaleWidget* xScale = plot()->axisWidget( xAxis() );
QwtScaleWidget* yScale = plot()->axisWidget( yAxis() );
if ( zoomRectIndex() <= 0 )
{
if ( m_inZoom )
{
xScale->setMinBorderDist( 0, 0 );
yScale->setMinBorderDist( 0, 0 );
QwtPlotLayout* layout = plot()->plotLayout();
for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
layout->setAlignCanvasToScale( axisPos, m_alignCanvasToScales[ axisPos ] );
m_inZoom = false;
}
}
else
{
if ( !m_inZoom )
{
/*
We set a minimum border distance.
Otherwise the canvas size changes when scrolling,
between situations where the major ticks are at
the canvas borders (requiring extra space for the label)
and situations where all labels can be painted below/top
or left/right of the canvas.
*/
int start, end;
xScale->getBorderDistHint( start, end );
xScale->setMinBorderDist( start, end );
yScale->getBorderDistHint( start, end );
yScale->setMinBorderDist( start, end );
QwtPlotLayout* layout = plot()->plotLayout();
for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
{
m_alignCanvasToScales[axisPos] =
layout->alignCanvasToScale( axisPos );
}
layout->setAlignCanvasToScales( false );
m_inZoom = true;
}
}
QwtPlotZoomer::rescale();
updateScrollBars();
}
ScrollBar* ScrollZoomer::scrollBar( Qt::Orientation orientation )
{
ScrollBar*& sb = ( orientation == Qt::Vertical )
? m_vScrollData->scrollBar : m_hScrollData->scrollBar;
if ( sb == NULL )
{
sb = new ScrollBar( orientation, canvas() );
sb->hide();
connect( sb,
SIGNAL(valueChanged(Qt::Orientation,double,double)),
SLOT(scrollBarMoved(Qt::Orientation,double,double)) );
}
return sb;
}
ScrollBar* ScrollZoomer::horizontalScrollBar() const
{
return m_hScrollData->scrollBar;
}
ScrollBar* ScrollZoomer::verticalScrollBar() const
{
return m_vScrollData->scrollBar;
}
void ScrollZoomer::setHScrollBarMode( Qt::ScrollBarPolicy mode )
{
if ( hScrollBarMode() != mode )
{
m_hScrollData->mode = mode;
updateScrollBars();
}
}
void ScrollZoomer::setVScrollBarMode( Qt::ScrollBarPolicy mode )
{
if ( vScrollBarMode() != mode )
{
m_vScrollData->mode = mode;
updateScrollBars();
}
}
Qt::ScrollBarPolicy ScrollZoomer::hScrollBarMode() const
{
return m_hScrollData->mode;
}
Qt::ScrollBarPolicy ScrollZoomer::vScrollBarMode() const
{
return m_vScrollData->mode;
}
void ScrollZoomer::setHScrollBarPosition( ScrollBarPosition pos )
{
if ( m_hScrollData->position != pos )
{
m_hScrollData->position = pos;
updateScrollBars();
}
}
void ScrollZoomer::setVScrollBarPosition( ScrollBarPosition pos )
{
if ( m_vScrollData->position != pos )
{
m_vScrollData->position = pos;
updateScrollBars();
}
}
ScrollZoomer::ScrollBarPosition ScrollZoomer::hScrollBarPosition() const
{
return m_hScrollData->position;
}
ScrollZoomer::ScrollBarPosition ScrollZoomer::vScrollBarPosition() const
{
return m_vScrollData->position;
}
void ScrollZoomer::setCornerWidget( QWidget* w )
{
if ( w != m_cornerWidget )
{
if ( canvas() )
{
delete m_cornerWidget;
m_cornerWidget = w;
if ( m_cornerWidget->parent() != canvas() )
m_cornerWidget->setParent( canvas() );
updateScrollBars();
}
}
}
QWidget* ScrollZoomer::cornerWidget() const
{
return m_cornerWidget;
}
bool ScrollZoomer::eventFilter( QObject* object, QEvent* event )
{
if ( object == canvas() )
{
switch( event->type() )
{
case QEvent::Resize:
{
const QMargins m = canvas()->contentsMargins();
QRect rect;
rect.setSize( static_cast< QResizeEvent* >( event )->size() );
rect.adjust( m.left(), m.top(), -m.right(), -m.bottom() );
layoutScrollBars( rect );
break;
}
case QEvent::ChildRemoved:
{
const QObject* child =
static_cast< QChildEvent* >( event )->child();
if ( child == m_cornerWidget )
{
m_cornerWidget = NULL;
}
else if ( child == m_hScrollData->scrollBar )
{
m_hScrollData->scrollBar = NULL;
}
else if ( child == m_vScrollData->scrollBar )
{
m_vScrollData->scrollBar = NULL;
}
break;
}
default:
break;
}
}
return QwtPlotZoomer::eventFilter( object, event );
}
bool ScrollZoomer::needScrollBar( Qt::Orientation orientation ) const
{
Qt::ScrollBarPolicy mode;
double zoomMin, zoomMax, baseMin, baseMax;
if ( orientation == Qt::Horizontal )
{
mode = m_hScrollData->mode;
baseMin = zoomBase().left();
baseMax = zoomBase().right();
zoomMin = zoomRect().left();
zoomMax = zoomRect().right();
}
else
{
mode = m_vScrollData->mode;
baseMin = zoomBase().top();
baseMax = zoomBase().bottom();
zoomMin = zoomRect().top();
zoomMax = zoomRect().bottom();
}
bool needed = false;
switch( mode )
{
case Qt::ScrollBarAlwaysOn:
needed = true;
break;
case Qt::ScrollBarAlwaysOff:
needed = false;
break;
default:
{
if ( baseMin < zoomMin || baseMax > zoomMax )
needed = true;
break;
}
}
return needed;
}
void ScrollZoomer::updateScrollBars()
{
if ( !canvas() )
return;
const int xAxis = QwtPlotZoomer::xAxis();
const int yAxis = QwtPlotZoomer::yAxis();
int xScrollBarAxis = xAxis;
if ( hScrollBarPosition() == OppositeToScale )
xScrollBarAxis = oppositeAxis( xScrollBarAxis );
int yScrollBarAxis = yAxis;
if ( vScrollBarPosition() == OppositeToScale )
yScrollBarAxis = oppositeAxis( yScrollBarAxis );
QwtPlotLayout* layout = plot()->plotLayout();
bool showHScrollBar = needScrollBar( Qt::Horizontal );
if ( showHScrollBar )
{
ScrollBar* sb = scrollBar( Qt::Horizontal );
sb->setPalette( plot()->palette() );
sb->setInverted( !plot()->axisScaleDiv( xAxis ).isIncreasing() );
sb->setBase( zoomBase().left(), zoomBase().right() );
sb->moveSlider( zoomRect().left(), zoomRect().right() );
if ( !sb->isVisibleTo( canvas() ) )
{
sb->show();
layout->setCanvasMargin( layout->canvasMargin( xScrollBarAxis )
+ sb->extent(), xScrollBarAxis );
}
}
else
{
if ( horizontalScrollBar() )
{
horizontalScrollBar()->hide();
layout->setCanvasMargin( layout->canvasMargin( xScrollBarAxis )
- horizontalScrollBar()->extent(), xScrollBarAxis );
}
}
bool showVScrollBar = needScrollBar( Qt::Vertical );
if ( showVScrollBar )
{
ScrollBar* sb = scrollBar( Qt::Vertical );
sb->setPalette( plot()->palette() );
sb->setInverted( !plot()->axisScaleDiv( yAxis ).isIncreasing() );
sb->setBase( zoomBase().top(), zoomBase().bottom() );
sb->moveSlider( zoomRect().top(), zoomRect().bottom() );
if ( !sb->isVisibleTo( canvas() ) )
{
sb->show();
layout->setCanvasMargin( layout->canvasMargin( yScrollBarAxis )
+ sb->extent(), yScrollBarAxis );
}
}
else
{
if ( verticalScrollBar() )
{
verticalScrollBar()->hide();
layout->setCanvasMargin( layout->canvasMargin( yScrollBarAxis )
- verticalScrollBar()->extent(), yScrollBarAxis );
}
}
if ( showHScrollBar && showVScrollBar )
{
if ( m_cornerWidget == NULL )
{
m_cornerWidget = new QWidget( canvas() );
m_cornerWidget->setAutoFillBackground( true );
m_cornerWidget->setPalette( plot()->palette() );
}
m_cornerWidget->show();
}
else
{
if ( m_cornerWidget )
m_cornerWidget->hide();
}
layoutScrollBars( canvas()->contentsRect() );
plot()->updateLayout();
}
void ScrollZoomer::layoutScrollBars( const QRect& rect )
{
int hPos = xAxis();
if ( hScrollBarPosition() == OppositeToScale )
hPos = oppositeAxis( hPos );
int vPos = yAxis();
if ( vScrollBarPosition() == OppositeToScale )
vPos = oppositeAxis( vPos );
ScrollBar* hScrollBar = horizontalScrollBar();
ScrollBar* vScrollBar = verticalScrollBar();
const int hdim = hScrollBar ? hScrollBar->extent() : 0;
const int vdim = vScrollBar ? vScrollBar->extent() : 0;
if ( hScrollBar && hScrollBar->isVisible() )
{
int x = rect.x();
int y = ( hPos == QwtAxis::XTop )
? rect.top() : rect.bottom() - hdim + 1;
int w = rect.width();
if ( vScrollBar && vScrollBar->isVisible() )
{
if ( vPos == QwtAxis::YLeft )
x += vdim;
w -= vdim;
}
hScrollBar->setGeometry( x, y, w, hdim );
}
if ( vScrollBar && vScrollBar->isVisible() )
{
int pos = yAxis();
if ( vScrollBarPosition() == OppositeToScale )
pos = oppositeAxis( pos );
int x = ( vPos == QwtAxis::YLeft )
? rect.left() : rect.right() - vdim + 1;
int y = rect.y();
int h = rect.height();
if ( hScrollBar && hScrollBar->isVisible() )
{
if ( hPos == QwtAxis::XTop )
y += hdim;
h -= hdim;
}
vScrollBar->setGeometry( x, y, vdim, h );
}
if ( hScrollBar && hScrollBar->isVisible() &&
vScrollBar && vScrollBar->isVisible() )
{
if ( m_cornerWidget )
{
QRect cornerRect(
vScrollBar->pos().x(), hScrollBar->pos().y(),
vdim, hdim );
m_cornerWidget->setGeometry( cornerRect );
}
}
}
void ScrollZoomer::scrollBarMoved(
Qt::Orientation o, double min, double max )
{
Q_UNUSED( max );
if ( o == Qt::Horizontal )
moveTo( QPointF( min, zoomRect().top() ) );
else
moveTo( QPointF( zoomRect().left(), min ) );
Q_EMIT zoomed( zoomRect() );
}
int ScrollZoomer::oppositeAxis( int axis ) const
{
using namespace QwtAxis;
switch( axis )
{
case XBottom:
return XTop;
case XTop:
return XBottom;
case YLeft:
return YRight;
case YRight:
return YLeft;
default:
;
}
return axis;
}
#include "moc_ScrollZoomer.cpp"

View File

@@ -0,0 +1,68 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#pragma once
#include <QwtPlotZoomer>
#include <QwtPlot>
class ScrollData;
class ScrollBar;
class ScrollZoomer : public QwtPlotZoomer
{
Q_OBJECT
public:
enum ScrollBarPosition
{
AttachedToScale,
OppositeToScale
};
ScrollZoomer( QWidget* );
virtual ~ScrollZoomer();
ScrollBar* horizontalScrollBar() const;
ScrollBar* verticalScrollBar() const;
void setHScrollBarMode( Qt::ScrollBarPolicy );
void setVScrollBarMode( Qt::ScrollBarPolicy );
Qt::ScrollBarPolicy vScrollBarMode () const;
Qt::ScrollBarPolicy hScrollBarMode () const;
void setHScrollBarPosition( ScrollBarPosition );
void setVScrollBarPosition( ScrollBarPosition );
ScrollBarPosition hScrollBarPosition() const;
ScrollBarPosition vScrollBarPosition() const;
QWidget* cornerWidget() const;
virtual void setCornerWidget( QWidget* );
virtual bool eventFilter( QObject*, QEvent* ) QWT_OVERRIDE;
virtual void rescale() QWT_OVERRIDE;
protected:
virtual ScrollBar* scrollBar( Qt::Orientation );
virtual void updateScrollBars();
virtual void layoutScrollBars( const QRect& );
private Q_SLOTS:
void scrollBarMoved( Qt::Orientation o, double min, double max );
private:
bool needScrollBar( Qt::Orientation ) const;
int oppositeAxis( int ) const;
QWidget* m_cornerWidget;
ScrollData* m_hScrollData;
ScrollData* m_vScrollData;
bool m_inZoom;
bool m_alignCanvasToScales[ QwtAxis::AxisPositions ];
};

View File

@@ -0,0 +1,51 @@
/* XPM */
static const char *clear_xpm[] = {
/* width height num_colors chars_per_pixel */
" 32 32 12 1",
/* colors */
". c #000000",
"# c #004040",
"a c #303030",
"b c #400000",
"c c #404000",
"d c #585858",
"e c #808080",
"f c #a0a0a4",
"g c #bdbdbd",
"h c #c0c0c0",
"i c #dcdcdc",
"j c #ffffff",
/* pixels */
"gggggggggggggggggggggggggggggggg",
"gggggggggggggg..gggggggggggggggg",
"gggggggggg....ficggggggggggggggg",
"ggggggg...fdad#ai......ggggggggg",
"gggg...fhjjidfbc#f.fffe...gggggg",
"ggg.fhjjjjihc#dhef.fhhhffe.ggggg",
"ggg.#jjjjjihhhhhe..ehhhfff.ggggg",
"ggg.#dffjjjjiihhcadehhfddd.ggggg",
"ggg.iiiffhfjjjjjhhhfdddddd.ggggg",
"ggg.#fjjiiffeeeeddddeeeddd.ggggg",
"gggg.#eeiiiiifffffffeee...gggggg",
"gggg.ffffffiifffffffddddd.gggggg",
"gggg.fffjfffeeeeddddeed.d.gggggg",
"gggg.fefiiiifhffeeeeded.d.gggggg",
"gggg.fefijhfhifefff.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fefijeffifeefe.ded.d.gggggg",
"gggg.fffijeffifeefe.deddd.gggggg",
"gggg.ffiijeffifeefeddedd#.gggggg",
"gggg.eiijjjeiifdffedded#..gggggg",
"ggggg..fjjiiiiffffedddd..ggggggg",
"ggggggg...fhhfffffdd...ggggggggg",
"gggggggggg..........gggggggggggg"
};

View File

@@ -0,0 +1,17 @@
/*****************************************************************************
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "MainWindow.h"
#include <QApplication>
int main( int argc, char* argv[] )
{
QApplication app( argc, argv );
MainWindow window;
window.show();
return app.exec();
}

View File

@@ -0,0 +1,24 @@
######################################################################
# Qwt Examples - Copyright (C) 2002 Uwe Rathmann
# This file may be used under the terms of the 3-clause BSD License
######################################################################
include( $${PWD}/../examples.pri )
TARGET = realtime
HEADERS = \
ScrollZoomer.h \
ScrollBar.h \
IncrementalPlot.h \
RandomPlot.h \
MainWindow.h
SOURCES = \
ScrollZoomer.cpp \
ScrollBar.cpp \
IncrementalPlot.cpp \
RandomPlot.cpp \
MainWindow.cpp \
main.cpp

266
examples/realtime/start.xpm Normal file
View File

@@ -0,0 +1,266 @@
/* XPM */
static const char *start_xpm[] = {
/* width height num_colors chars_per_pixel */
" 32 32 227 2",
/* colors */
".. c #040204",
".# c #848684",
".a c #c4c2b4",
".b c #843a04",
".c c #444244",
".d c #ece2cc",
".e c #fca234",
".f c #c45e04",
".g c #bca27c",
".h c #646264",
".i c #e4c69c",
".j c #847254",
".k c #c4a684",
".l c #443e34",
".m c #a48e6c",
".n c #f4f2e4",
".o c #24261c",
".p c #a44a04",
".q c #c4825c",
".r c #644634",
".s c #b4b2ac",
".t c #747274",
".u c #844e2c",
".v c #ece6dc",
".w c #c4b6a4",
".x c #a49274",
".y c #343634",
".z c #fcd69c",
".A c #b4aa9c",
".B c #8c8e8c",
".C c #545254",
".D c #f4f2ec",
".E c #fcb67c",
".F c #e4965c",
".G c #e46634",
".H c #141614",
".I c #d4c2a4",
".J c #746a5c",
".K c #fcc2a4",
".L c #342a1c",
".M c #fc9204",
".N c #a45e2c",
".O c #94521c",
".P c #a4560c",
".Q c #645e54",
".R c #ec7a04",
".S c #f4deac",
".T c #5c462c",
".U c #bcaa8c",
".V c #d4be9c",
".W c #fcfaf4",
".X c #d4cab4",
".Y c #1c0a04",
".Z c #6c6a6c",
".0 c #e4caa4",
".1 c #2c2a1c",
".2 c #74462c",
".3 c #84562c",
".4 c #f4eee4",
".5 c #c4beb4",
".6 c #a49a84",
".7 c #f4ba7c",
".8 c #dc966c",
".9 c #948674",
"#. c #fc8a04",
"## c #f4eab4",
"#a c #fcb26c",
"#b c #c4ae94",
"#c c #f4e6d4",
"#d c #9c8e74",
"#e c #fc7e04",
"#f c #140604",
"#g c #b4a28c",
"#h c #6c625c",
"#i c #8c7e64",
"#j c #f4ae84",
"#k c #e4decc",
"#l c #ac5204",
"#m c #e48a4c",
"#n c #7c7a7c",
"#o c #ccba9c",
"#p c #fcd2b4",
"#q c #bcae9c",
"#r c #dcc6a4",
"#s c #ac723c",
"#t c #e4ceb4",
"#u c #ec9e74",
"#v c #8c8a8c",
"#w c #8c4204",
"#x c #4c4a34",
"#y c #7c3a04",
"#z c #fcfecc",
"#A c #2c221c",
"#B c #ac4e04",
"#C c #d48264",
"#D c #bcb2a4",
"#E c #a49684",
"#F c #b4aeac",
"#G c #5c5a5c",
"#H c #fcf2ec",
"#I c #fcb28c",
"#J c #7c6e5c",
"#K c #fcce9c",
"#L c #3c2e24",
"#M c #bc9e71",
"#N c #fc922c",
"#O c #bc622c",
"#P c #b45604",
"#Q c #f47a08",
"#R c #fcdeb8",
"#S c #544e44",
"#T c #fcfefc",
"#U c #e4ceaa",
"#V c #8c5a2c",
"#W c #e49e7c",
"#X c #f4eadb",
"#Y c #9c9284",
"#Z c #f4ae90",
"#0 c #c47e5c",
"#1 c #bc824c",
"#2 c #e47634",
"#3 c #e46e24",
"#4 c #b48e6c",
"#5 c #7c5a4c",
"#6 c #744e2c",
"#7 c #fcba9c",
"#8 c #cccacc",
"#9 c #f4722c",
"a. c #c46224",
"a# c #e47a54",
"aa c #ac663c",
"ab c #fce2cc",
"ac c #945634",
"ad c #fceacc",
"ae c #3c3e3c",
"af c #ec9e54",
"ag c #843e1c",
"ah c #fccab0",
"ai c #8c8274",
"aj c #4c4634",
"ak c #ecc2ac",
"al c #8c765c",
"am c #7c7264",
"an c #e49a7c",
"ao c #6c4e34",
"ap c #fc9a2c",
"aq c #4c4a4c",
"ar c #ccbea4",
"as c #fcf6dc",
"at c #3c3a3c",
"au c #949294",
"av c #fceebc",
"aw c #fcaa7c",
"ax c #ecdac8",
"ay c #0c0604",
"az c #fc8204",
"aA c #847664",
"aB c #e4d6c4",
"aC c #fcd2ac",
"aD c #1c1a14",
"aE c #342e2c",
"aF c #240e04",
"aG c #2c2e2c",
"aH c #fcbe7c",
"aI c #fc8e14",
"aJ c #fc7a14",
"aK c #944604",
"aL c #7c3e14",
"aM c #fcfadc",
"aN c #645244",
"aO c #bcb6b4",
"aP c #bc5604",
"aQ c #7c522c",
"aR c #cc8264",
"aS c #dccab0",
"aT c #ac9a84",
"aU c #f4e2cc",
"aV c #a45e3c",
"aW c #9c5634",
"aX c #fca634",
"aY c #c4aa89",
"aZ c #a44e07",
"a0 c #b4b6b4",
"a1 c #c4baa9",
"a2 c #a4967c",
"a3 c #b4aea4",
"a4 c #d4c6a8",
"a5 c #5c4a34",
"a6 c #bcae94",
"a7 c #845a2c",
"a8 c #948a7c",
"a9 c #c4b299",
"b. c #b4a690",
"b# c #6c6658",
"ba c #fcd6b4",
"bb c #2c261d",
"bc c #fcf6f0",
"bd c #fcb694",
"be c #fc9624",
"bf c #646664",
"bg c #747674",
"bh c #eceadc",
"bi c #545654",
"bj c #b49e7c",
"bk c #6c6e6c",
"bl c #fc8e04",
"bm c #fcb66c",
"bn c #7c7e7c",
"bo c #5c5e5c",
"bp c #8c8674",
"bq c #fc8604",
"br c #bc5a04",
"bs c #fca23c",
"bt c #443e3c",
"bu c #a4927c",
"bv c #b4aaa4",
"bw c #746a64",
"bx c #342a24",
"by c #fcfafc",
"bz c #2c2a24",
"bA c #a49a8c",
"bB c #bcbabc",
"bC c #9c8e7c",
"bD c #8c7e6c",
"bE c #ccbaa4",
"bF c #fcd2bc",
"bG c #fcb294",
/* pixels */
"#Gbi#G.#bnbg.t.Zbfbf.hbo#G.Caqaq.c.C.C.C.C.C.C.C.C.C.C.Cbi#Gbi#G",
"#Gbi#Gbg#8#8.a#8#8#8#8#8#8#8#8.B#8#8#8#8#8#8#8#8#8#8#8.C#Gbi#Gbi",
"bi#Gbi#n#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#T#T#T#T#T#T#T#8aq#6afbm#z",
"#Gbi#Gbk#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#T#T#T#T#T#T#T#8#6af#aavaX",
"bi#Gbibk#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#T#T#T#T#T#T#T#6af#a##aX#.",
"#Gbi#Gbk#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#T#T#T#T#T#T.3af#a.S.e#.bq",
"#Gbi#G.Z#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#T#T#T#T#TaQaf#a#R.e#eazbq",
"bi#GbibkaubBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBbBa7af#aba.e#eazbq.M",
"#Gbi#G.Z#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#T#T#T#Vaf#ababs#ebqbq#.az",
"#Gbi#Gbf#8#T#T#T#T#T#T#T#T#T#TbB#T#T#Tby#T#saf#a#Kap#ebqbqbl#Q.f",
"bi#Gbi.Z#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#T.Naf#a.z#N#ebqbqbl.R.f#l",
"#Gbi#Gbf#8#T#T#T#T#T#T#T#T#T#TbB#T#T#T#1af.EaHbe#ebqbq#..Rbr#B#y",
"bi#Gbibf#8#T#T#T#T#T#T#T#T#T#TbB#T#T.F.7#jawaI#ebqbqbl.R#PaZ.b..",
"#Gbi#GbfaubBbBbBbBbBbBbBbBbBbBbBbBbG#RaMak#m#ebqbqbl#Q#P#B#w.Y.y",
"bi#Gbibf#8#T#T#T#T#T#T#T#T#T#TaObyaC.Wab#Z#2bqbq.M.RaP.p#way.y.y",
"#Gbi#G.h#8#T#T#T#T#T#T#T#T#Tbya0#I#Tad.K#j#2#QaJ.Rbr.p#yaF.y.yat",
"bi#Gbi.h#8#T#T#T#T#T#T#T#Tby.W.saCasba#Za#.G#9#3aPaZaK.Y.y.yat.c",
"#Gbi#Gbo#8#T#T#T#T#T#T#Tby.Wbc#I#T#p#7.8#0a.#O.P.paLay...yatbtaq",
"bi#Gbi.h#8#T#T#T#T#T#Tby.Wbc.DaCadah#W#0aa.O.2.ragaF#h..ataeaq.C",
"#Gbi#GboaubBbBbBbBbBaOa0.sa3bdasahanaRaV.u.Ta5ae#f.Q#S..aeaq.Cbi",
"bi#Gbibo#8#T#T#T#T.Wbcbc.D#HaCbF#uaRaWaQa5ajbt.HbDai#J..aq.Cbibi",
"#Gbi#Gbo#8#T#Tby.W.W.D#H.nbdab#u#Cac.uaN.o..bDaiaia8#i...Cbibi#G",
"bi#Gbibo#8#T#Tbybc.Dbc.n.4#4.8.q#5.r.l..#vbDaia8a2#g#d..bibi#Gbi",
"#Gbi#G#G#8#T.Wbc.D#H.D#X.j.Lao#5#L.H#vaibpbpbCaT.U#oa2..bi#Gbi#G",
"bi#Gbi#G#8.Wbc.D#H.n.4bjajaD#A...#bpai.9bC#E#ga9.V#r.gbb#Gbi#Gbi",
"#Gbi#Gbiaua0.s.s#Fa3bvaG....#vbwb#b#.JbwaA#i.9bC.m.xal.1bi#Gbi#G",
"bi#Gbi#G#8.D#H.4.4#X.v#x#v#qbAb##Y.6b.a6ar.I#r#r.0.i.g.Lbi#Gbi#G",
"bi#Gbibi#8.D.4.4#X#c.vax.X.AbAamb.#D#oa4aS#r.0.0.i.i#M#A#Gbi#Gbi",
"#Gbi#G.C#8.n.4#X#X.daUaBaS.wa6aiar#raS.0#U#U.0.i.0#r#Mbb#Gbi#Gbi",
"bi#Gbiaq#8.4#Xbh.v#c.d#kaB.Xa4buaS#U#t#U#U.0.0#r.i.i#Mbbbi#Gbi#G",
"#Gbi#Gae.a.a.5a1bE.w.w.w#ba6.U#iaYaYaY.k.g.g.g#M#M#M#M.Lbi#Gbi#G",
"bi#Gbi.HbxaEbxaEbz.LaEbzbzbbbzbbbbbxbb.Lbbbb.1.Lbb.1#Aay#Gbi#Gbi"
};